YAGNI and DRY — the KISS of Death for Your Software Project
Learn why popular programming mantras like YAGNI, DRY, and KISS can be as destructive as they are seductive.
Software development is full of mantras that are chanted by developers of all levels as prima facie evidence that justifies and proves the rationality of their decisions.
Who amongst us hasn’t heard people or told people to YAGNI, DRY, or KISS? They’re popular mantras because, when followed properly, they work to guide and nudge thinking towards more effective development and programming.
However, they have a dark side.
Because these terms are intentionally vague and broad, they can be misapplied or over-applied in many situations. These memes are then used as justification to continue applying the wrong approach to a problem.
They’re hard to argue against because philosophically these generalized statements are correct. We want to believe them. We have to believe them. To not believe them makes one feel as if they are not a developer. This makes them difficult to argue against, combined with the fact that they contain only the broadest of truths and are not applicable in every situation.
KISS — Keep it Simple, Stupid
Despite hurting feels across the world, KISS, or “keep it simple, stupid” is often used to promote simplicity and prevent the over-engineering tendencies many engineers have.
There might be a hundred ways to implement any one requirement. KISS implies that the simplest method is often the best in terms of complexity, speed, and cost.
For example — an engineer may need to implement a way to change the program configuration. They may be evaluating two different approaches: read from the database, or read from a file.
Developers apply KISS in this situation: avoid complexity and dependencies caused by the additional database tables by choosing the simpler method of reading from a file.
What’s wrong with it?
The dark side of KISS is that is can lead you down the path of the minimum, which if applied over time eventually results in subpar outcomes.
Let’s suppose a second requirement follows that the configuration needs to be changeable during runtime by internal employees.
A KISS-focused iteration after this could be to give internal administrators access to the server to change the configuration file. However, this goes down a path that results in more ineffective results than you would have had you taken the slightly more complex option of putting it in a database table.
KISS is also often used to defend under-developed solutions and gloss over implicit or unspoken requirements. In the example above, one of the unspoken requirements is that we don’t want the server to go down if we changed the configuration. However, because we’ve gone down the route offered by KISS, this constraint is not even mentioned or addressed.
Sometimes situations involve real complexity, and in these situations, KISS can dangerously scope out important considerations.
YAGNI — You Aren’t Gonna Need It
YAGNI is often used to prevent engineers from over-engineering their solutions in an effort to address situations or requirements that don’t currently need to be addressed.
Let’s face it — engineers have a tendency to overbuild for use cases they will never see, or inappropriately delay value delivery for minimal gains in architectural and code cleanliness — code-golf is a thing, as are ivory towers.
YAGNI is the mantra that acts as the counter-balance to the path of infinite “what if?” questions that engineers can travel down. It prevents scope creep that comes from attempting to address the problems of an uncertain future that are better left to be solved for when they actually occur (if they ever).
What’s wrong with it?
YAGNI has a dark side. It is often used by engineers as a reason for under-engineering in a misguided attempt to justify sloppy work with nebulous promises of unverifiable gains in development speed.
How do you tell if it is being misapplied? When YAGNI is used as the reason for NOT doing something, it’s time to ask yourself some questions:
Is it being used to avoid solving a problem that is inherent to the domain?
Is it being used to avoid developing something inherently foundational to the product or software (eg. authorization for web applications)?
Are speed benefits from avoiding the additional work being tracked to ensure it actually leads to faster development?
Is the cost of doing it or implementing it actually as costly as believed?
YAGNI can be a powerful guiding principle when applied judiciously. However, it can also be used as a crutch to excuse sloppy development and low quality work in the name of faster delivery speeds that never materialize.
A tale of a highly detailed project
I once worked on a project that had almost no abstractions. Instead, every line of code was at the lowest possible level of detail. Functions were thousands of lines long, forcing you to read every line to understand what it was doing. There were few classes or reusable libraries.
The team was hesitant to create classes or even move code into functions. They believed it was over-engineering and yelled “YAGNI”: why move code into a function when it wouldn’t be called by anything else? Why create abstractions we didn’t need when copy-pasting was so much faster?
Keep reading with a 7-day free trial
Subscribe to Joseph Gefroh to keep reading this post and get 7 days of free access to the full post archives.