Startups tend to have a rough label of offering long hours coupled with little pay. Successful startups tend to be looked at as well paying but high pressure environments. It's not always fun and definitely not very inclusive. I've collected a few principles that I try to practice every day, in an effort to make product engineering culture a little bit better.
A common metric in modern development teams is the occurrence of errors (or bugs 🐛) – the fewer, the better. However, using the number of times a system fails, rather than the number of times a system works perfectly, is not an effective to way measure the performance of a team. As a logical consequence, this leads to reactive thinking when responding to what goes wrong, as opposed to focusing on what goes right.
Safety 2 is the ability to succeed under varying conditions, so that the number of intended and acceptable outcomes is as high as possible1. Contrary to previous (Safety 1) thinking, success is measured by the things that go right.
One of the ways this is accomplished, is by actively embracing, even provoking, failure. These failures are followed by a defined process where the situation is discussed and learned from and safeguards and improvements are put into place. Navy Seals do something similar and call it AAR – after action review. While a zero-defect policy might sound great to management, it severely handicaps a business as it inhibits teams from pushing boundaries without consequences. Creating room for and even provoking mistakes while proactively creating error boundaries will be much more advantageous to a product or service in the long run.
1 Erik Hollnagel: Safety-I and Safety-II, the past and future of safety management
Creating features in the hopes that customers will appreciate them, will not make a service better. When eating at an expensive restaurant, menus will often only offer 2-3 options to choose from. Each course meticulously crafted to perfection. The same thing goes for digital products. If an interface is cluttered with features, it hints that there is a lack of understanding what customers need. It's okay to implement features, that haven't been validated, but it is important to measure if users are engaging with them. If not – they should be removed.
I have come across different teams in the past, that preach common programming principles like "DRY" (don't repeat yourself). I like to repeat myself. DRY means abstracting and reusing parts of code in different areas. While reusing code might seem like a good thing, doing so prematurely forces a team into making decisions about the future of a product that they can't possibly know. A product is usually a intensely dynamic pice of software, with many changes daily. Making changes to a piece of code that is used in many parts of a product may cause errors in many other parts of that product without being noticed. That requires teams to then examine and test numerous other areas of a product before deploying features – severely limiting the pace of product development. The right time for abstracting code is usually when it has been implemented about two to three times. Only then will it be more evident what the abstraction requires. Maintaining isolated components and not over-abstracting code also keeps teams out of dependecy-hell and in turn helps keep codebases clean and readable, allowing to keep a fast pace of development and limiting tech-debt.
To be continued...