Simplicity is a desirable quality attribute in any software system. In this article I try to collect the main software design principles that address the importance of simplicity.
KISS means “Keep it simple, stupid”. It is probably one of the oldest principles of software design (but we keep forgetting it).
“The KISS principle states that most systems work best if they are kept simple rather than made complex; therefore simplicity should be a key goal in design and unnecessary complexity should be avoided.”
Software systems must be maintained by human developers with limited capabilities, thus any increase in a system’s complexity also augments the difficulty to maintain it.
“Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it.” -Brian Kernighan
“Always implement things when you actually need them, never when you just foresee that you need them.” – Ron Jeffries
The YAGNI principle is related to the “Last Responsible Moment” concept of Lean Software Development:
“Decide as late as possible: Delaying decisions as much as possible until they can be made based on facts and not on uncertain assumptions and predictions.”
Occam’s Razor: “A principle of parsimony, economy, or succinctness used in logic and problem-solving. It states that among competing hypotheses, the hypothesis with the fewest assumptions should be selected.”
Michael Lant has written an interesting article about Occam’s Razor applied to software development. He says:
“Modern interpretation is often quoted as ‘The simplest solution is almost always the best’. The modern interpretation, however, misses the important point that ‘simplest’ as meant by Occam means the ‘fewest assumptions’.”
Thus, we should as much as possible avoid basing our design on assumptions. In this sense the principle of Occam’s Razor is aligned with YAGNI.
When the simplicity principles above are not observed, the resulting software systems may have complexity in the form of:
- Unneeded features.
The first case is that of systems with more features than necessary:
Feature Creep: “The ongoing expansion or addition of new features in a product. Extra features go beyond the basic function of the product and so can result in over-complication rather than simple design.”
Feature Creep is particularly common in software systems, in which it is relatively easy to add new features that were not part of the original design. One of the consequences of this feature expansion is known as Software Bloat.
Software Bloat: “A process whereby successive versions of a computer program become perceptibly slower, use more memory or processing power, or have higher hardware requirements than the previous version whilst making only dubious user-perceptible improvements.”
The second case of high complexity is that of systems which are over-engineered:
Over-engineering: “The designing of a product to be more robust or complicated than is necessary for its application.”
A typical example of over-engineering is that of having too many abstraction layers.
“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.” – C.A.R. Hoare
Of course we want to eliminate complexity from our designs. But when trying to do a simple design, we must be very careful to avoid the trap of Simplistic Designs. This is the definition of “simplistic” from a dictionary:
Simplistic: “Treating complex issues and problems as if they were much simpler than they really are.”
A simplistic software design may be one that focuses only on present requirements and ignores future needs such as maintainability, extensibility and reusability. As I’ve discussed in a previous post, wise developers foresee the consequences of their design.
I think that the danger of simplistic design is very well expressed by this quote:
“Keep it simple, as simple as possible, but not simpler.” – Albert Einstein
What do you think? How do you cope with complexity in software systems? Please share your experience in the comments below.