There’s a “problem of the extremes” that is often encountered in project development. The issue is not with each of the methods per se, but with wholeheartedly sticking to a certain method or approach, regardless of the circumstances. Most of the time, people do it with the best intentions, sincerely thinking it’s the “most optimal” way. But, just like different clothes can be good for different weather conditions, there is no path that is the “most” optimal in all situations.
Some things that could be good ideas – or not – depending on the circumstances:
- Having lots of unit tests, or just a few, or none?
- Pull request being reviewed by everyone on the team, or only some people, or merged without a review?
- Having a separate issue explaining the plan, or just opening a pull request right away?
- Sometimes it is a good thing to ask for a roadmap, sometimes it isn’t (R&D – research and development)
- Sometimes it is a good idea to have a lot of repositories or folders, but most of the time a monorepo will be better.
- Sometimes it is a good idea to abstract code, most of the time it isn’t (people often abstract too early based on what they imagine the code would become later. Doing that makes it harder to read the code, change a small part of it, etc. Abstraction is good when you have a clear practical explanation for it).
Choosing a single path is a mistake I made regularly, but I try to be aware of it now and always analyze my approach. For some people I meet, this issue remains unresolved, getting deeper over time. Most of those cases are due to perfectionism – when a person wants to “do one thing, and do it right”. They genuinely like their project and don’t want to mess anything up. However, in the long run this “good intention” becomes a reason the project becomes globally “slow”, regardless of what the chosen “single rule” is. This also becomes a hot issue for arguing among the employees – since people who want to ship fast and perfectionists don’t get along with each other, half of your team will become disgruntled with the state of things.
You don’t need to try making everyone happy 100% of the time, but it is important to accept both extremes for everything: people, rules, cases, parts of the code. Embracing multiple rules that always have limits (implicit or explicit) in order to avoid making an inappropriate choice just because “it’s the way we do everything”.
For example, in a startup, you usually have these categories of tasks, based on how critical their failure is:
- Vital. Anything related to payments, user data protection, security. If something fails here, your business will suffer severe damages or will be destroyed completely, so you should take extra precautions here.
- Planned features that are well-prepared and have to be done. For example, things that competitors are doing, so they should be also implemented to keep up with the competition. Here, you should mainly focus on having operational review, and sometimes can tolerate letting some edge cases not be managed at all.
- Pure ideas that may completely fail. Here, you should make everything possible to be very fast, but also to not complexify the codebase if you need to remove the feature. Basically, you should try to protect the rest of the system from becoming more complex.
Having a lax attitude towards vitals may eventually be catastrophic. But treating every feature as if it was vital greatly extends the development time and leads to a waste of resources. Ideas should be tested fast to get a quick feedback that will indicate if it should be pursued or discarded.
Stay flexible, do not hesitate to have not one but two or more processes; do not hesitate to say “this is the default expected behavior, but in some particular cases, another process is preferred instead”.
Here are a few approaches to the issue:
- You can try to have better “exception handling” of the general rules, or multiple rulesets.
- Another approach is to educate and encourage people to not just strictly stick to the given rules, but be adaptive. Then remove most of the hard rules and let people choose what they think to be the most appropriate “need” (not rule) for the current step.
I have some friends who own startups that also tried different things that are worth being considered:
- Regularly, reset all rules and let the team update their own team rules. Most members of the team will collectively choose to apply some rules that work for them right from the day one, some will try to have no rules and only add some only when problems appear, etc. I think this method is very cool if you have the chance to have different autonomous teams, so you can experiment with multiple things at the same time and also “compare” with the others.
- Another approach I like, “the rule of three”, is the one from the Swedish “parti pirate” which goes like this. Anyone in the organization can come up with an idea. Then they suggest it to a second person. If that person disagrees, the idea is rejected at this stage. If the person doesn’t have any opinion, they can recommend asking someone else instead. If the first person finds someone else who agrees with the idea, they look for a third person. Again, if that person disagrees, the idea is discarded, but if that person agrees, all three of them start implementing the idea, and are all equally responsible for it.
I like the philosophy of trying fast and being error-friendly. It even becomes a skill to be prepared for the bad decisions, since some inevitably will be made. Instead of finding the best protocol, the best library, anything “best”, we concentrate on finding the most viable “upgrading strategy” in order to support having a first choice that is just okay, and then switch to a better one (which most probably is still not the best, but better than the previous one).
Related: Why I trash V1 of my projects (and so should you).