Over several decades of developing software, one of the statements that has stood out for me most says that “There are two ways to develop software: Make it so simple that there are obviously no bugs, or so complex that there are no obvious bugs.”
“I conclude that there are two ways of constructing a software design: One way is to make it so simple that there are obviously no deficiencies and the other way is to make it so complicated that there are no obvious deficiencies.
The first method is far more difficult. It demands the same skill, devotion, insight, and even inspiration as the discovery of the simple physical laws which underlie the complex phenomena of nature. It also requires a willingness to accept objectives which are limited by physical, logical, and technological constraints, and to accept a compromise when conflicting objectives cannot be met. No committee will ever do this until it is too late.”
I was impressed by this quote because it expresses very clearly something that I already knew from experience but had never really been aware of explicitly. Once I read this elegant phrasing, I immediately understood how accurate it was and what a great guideline it provides.
It’s not true, of course, that these two extremes are the only two ways to design software. In real life, most cases fall somewhere in the middle, involving various levels of complexity and various levels of “bug obviousness”. But it makes you ask yourself, at critical points of the design, whether you have gone too far with complexity.
When I reflect back on my software design career, I see that one of the worst mistakes I made was trying to construct algorithms and systems that were too sophisticated. It wasn’t only the debugging of the written code that became almost impossible, but the design itself whose components became so inter-dependent that I always felt I was missing something important. I paid the price for deviating from the dictum “keep it simple”.
There are certain complex issues that cannot be solved by simple designs, or at least not by most of us, since we generally lack the “skill, devotion, insight, and even inspiration” that Hoare speaks of in the quote above. But stopping from time to time to review the complexity of our decisions can be helpful.
We always want to add functionality, support additional features and improve the product, but at some point the added complexity is going to kill our product’s quality.
I sometimes wonder to what extent over-sophistication should be avoided in other aspects of building a successful high-tech company. I strongly believe that in most cases it is a drawback. For example, in legal contracts, the apparent completeness and totality of protection that you hope to obtain using lengthy documents with endless conditions sometimes make its essence so obscure, that should you ever need to exercise it in the future, it might actually turn out to be less helpful than if it had been written simply. Or in software terms, one cannot truly “debug” these convoluted contracts, as they are too complex.
I also suspect that over-complicating presentations and marketing campaigns is an error which intelligent people are inclined to make, and that excessive complexity or creativity can also stifle a startup’s go-to-market strategy. But as with most complex issues, it’s not easy to pinpoint these flaws with certainty. The “bugs aren’t obvious”, and avoiding such bugs is essentially the premise of this post.