“Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away.” – Antoine de Saint-Exupery
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
YAGNI means “You Aren’t Gonna Need It”. It is a principle of Extreme Programming (XP) that states that a programmer should not add functionality until really necessary.
“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.
Informative. One can talk of these concept and apply them also (do not know exactly how yet). I have got to know how Occam’s Razor is used in design context.
I would like to see case studies or applications of these principles to multiple designs and their evaluation.
Thanks, Putcha. In my future posts I will try to illustrate software design principles with more concrete examples.
Pingback: Bumper Sticker Philosophy | Form Follows Function
First, by fairly strict architecture peer reviews on any major design. If the rest of the team needs more than one clarification of the design, it’s too complicated.
Add to that, simplicity is driven from the top down in our group. The Director of Software Architecture defines “Elegance” as “A design so simple it makes the task look easy”. Everything accounted for is questioned. Every design pattern is questioned. He doesn’t insist we deliberately cripple our designs, but he does force us to think twice about our decisions.
Finally, architects participating in the requirements gathering process. We help refine requirements so that we have time to plan and so that we have a chance to help guide the discussions. That’s not directly a software design principle, but it helps when I start designing something, it’s not the first time I’ve seen the requirements and that I’ve helped shape the requirements into something more easily built.
Thanks, Matt. I agree with the importance of reviews. We could say that complexity is always relative: Complex in relation to what alternative? I talk more about that in my post about Effective Design Reviews:
Matt’s suggestion re: architects participating in the requirements process is important. Unfortunately, people have a tendency to ask for a specific solution rather than just outlining the problem. I can’t count the number of times that I’ve seen requirements that could be realized in a simpler manner or worse, goals achieved without any work at all because there’s existing functionality that the requester is unaware of (dev teams aren’t the only ones that lose track of detail via job changes, etc.).
I agree, Gene. In other words, software developers also have this tendency of “reinventing the wheel” just because they believe that their specific wheel must certainly be very different from all other wheels…
Hayim, I just stumbled across your blog. This is really, really good stuff. I think over-engineering and feature creep is all too common in most B2B software apps. I hate it.
I just wrote a blog a few days ago in the same vein as this one: http://getclearstream.com/the-art-of-good-product-design/
Thanks, Michael. I agree with you that “good design makes the product understandable”.
Good points, Hayim.
However, I think the problem with mantras like KISS, YAGNI and Occam’s Razor is that they are often misued to jump straight into the code under the assumption things can be changed or added later. However, this is rarely the case where hardware and network changes are involved. Adding security, availability or performance to an existing system usually requires a rewrite.
The critical thing is to understand the system. The design can reflect the system’s intention only if the intention is known. It can only make the task look easy when the task is understood. Simplicity is relative, not absolute.
Thanks, Anthony. I agree that principles such as KISS and YAGNI are often misused, and for this reason I emphasized the danger of “Simplistic Design”.
But, as you say, some people have a simplistic approach to Problem Solving, and try to start solving a problem even before they fully understand it…
I think a good antidote to this temptation is Poppendiecks’ explanation of what they meant by deferring decisions until the last responsible moment. It doesn’t mean lazily “do nothing till you have to”, it means you do the hard work now of designing for a reverseable decision later. As an example, to defer the decision about a choice of database will probably require a design which hides that decision within a component that abstracts the persistence interface.
Which I think underlines your point that understanding the system is critical. You can only pick the right decisions to defer, and do it in the right way, if the intention is known & the task understood.
Pingback: 35 Agile Development Best Practices | Effective Software Design
Pingback: Attention Agile Programmers: Project Management is not Software Engineering | Effective Software Design
Pingback: Bumper Sticker Philosophy | Iasa Global
Pingback: Do SOLID design principles make code slow? | Effective Software Design
Pingback: Context Makes The Pattern | Gustin's Software Development Blog
Pingback: Python – The Hard Way | The Bytelion Blog
Pingback: Indefinite Optimism: the Problem with the Agile and Lean Mindsets | Effective Software Design
Pingback: Simplicity’s Not So Simple: Occam’s Razor and Tech – A Logical Pursuit
Pingback: How Form and Function Play into the Rise of Good Design - Proto.io Blog
Pingback: Becoming a software developer – episode VIII | Piotr Gankiewicz
Very good article, easy to understand!
KISS also means “Keep It Simple and Straigtforward” as given on http://www.softwaretree.com
Pingback: Worthless software: risks and prevention - Small Business Programming
Pingback: How Form and Function Play into the Rise of Good Design | Proto.io Blog
Pingback: Keep Software Design Simple – Computer Science Discovery at WSU
Pingback: Agila utvecklare måste även skriva sin kod på ett agilt sätt för att var helt agila – Robert Forsström's Blogg
Pingback: Agila utvecklare måste även skriva sin kod på ett agilt sätt för att vara helt agila – Robert Forsström's Blogg
Very nice, and also very succinct article. I wrote-up a much lengthier blog-post back in 2006 with mostly the same conclusions (particularly regarding Occam’s Razor, and simplicity-vs-simplistic). It’s “saving grace” was the plethora of great quotes on the subject of simplicity:
“Simple ain’t Easy: Myths and Misunderstandings about Simplicity”
Thanks Brad, I really enjoyed your blog post. Unfortunately I think that since 2006 the number of developers that misunderstand the meaning of simplicity only increased. For this new generation of Bootcamp Programmers, simple means easy. As easy as copy-and-paste from Stack Overflow.
Hi Hayim! I think its even worse than that, since this new generation of agile foragers, followers, neophytes and wannabes expand far beyond software development and even IT, and have an even more simplistic (mis)understanding. For programmers, the software craftmanship movement was a bastion of hope (swearing off copy/paste and subscribing to the notion that duplication/copying “is the root of all evil”). For when copying is exalted, we have moved outside the domain that agile was targeting (creative/mindful knowledge work requiring “artful making” rather than rote/mindless action leading to “repetitive making” that should instead be automated or eliminated).
Pingback: lesson learned from years of Telehealth implementation - Baby Live Advice