The case against over-engineering
Filipe Ximenes • 2 August 2017
"Premature optimization is the root of all evil." - Donald Knuth
Like any professional, we developers want to do things the right way. We want to do things the best way we possibly can. With no errors, no blind spots, covering all possible cases. This is just the natural behavior of the human being. Why would anyone want to fail? Why would anyone want to have clients, the people paying for your work, complaining about the software you wrote? The problem with this posture is that developing software does not work the same way as most other products or services we are accustomed.
Take a surgeon for instance. What are the indicators that she did a good job? Well, we can say that any surgery that went on without complications and fixed whatever ill the patient had can be considered successful. This is a good measure of the work done. But how do we, software developers measure how good is the software we write? One might say it is by running it against a well-thought test suit. Other might say it would be better to have a domain specialist performing a QA analysis. It could also be mathematically proving the correctness and completeness of the software. For most software running in the real world, none of that is usually the case.
In most situations, the best metric of a software product is how much value it delivers. The word 'value' is vague, and in this case, it's a good thing. It might mean how many users are using the product, a measure of how often people come back, how easy it is to use, how better it is than its competitors or the most common meaning: how much revenue it generates.
The meaning of value will depend on who is your customer. Is she the boss of a big corporation? Is it a bootstrapped company thriving to start profiting? Or is it a company that's aiming for a billion dollar IPO? Once you understand who is the client and what is that she want's to achieve, then you will be in a good position to evaluate what is value. Always start from that. Listen to the customer and understand what is trying to be achieved. The second step is a little harder. It requires some discipline. For every new line of code you want to write you will ask yourself:
How much value is this line of code adding to this product?
If the answer is "none", drop it. Do not write that line. If it's not adding value, then it's probably removing value. Be it by increasing the complexity of the code base, wasting the client's money or delaying some other more valuable feature.
There's yet another very good reason why you should never over-engineer. It's the same reason why we stopped doing Waterfall and started doing Agile: you cannot assume anything is right until it's in the hands of the user. The agile manifesto is almost 20 years now. 'The Lean Startup' is turning 10. You should know by now the importance of "Customer collaboration over contract negotiation", "Responding to change over following a plan" and the "Build-Measure-Learn" cycle. By over-engineering, you are doing the complete opposite of all of this.
An over-engineered code is a code that assumed the most complicated path before even testing if the simplest one was to deliver the most value.
If not covering that particular edge case it's only going to waste your team 1 hour per month to fix an eventual issue; maybe it's better to wait till it's consuming 5 hours per month till it's worth to invest that 20 hours to write the code to fix it.
"It's not a problem until it's a problem."
Summing up, all you need to do is always to be asking these two simple questions:
- How much value is this adding?
- Is it worth to do it right now?