This content originally appeared on Level Up Coding - Medium and was authored by Giedrius Kristinaitis
You must have robust code to apply the YAGNI principle
What you’re about to read is my view that’s formed over my career as a software engineer. If you’re looking for a magic recipe that says “do this and you’ll succeed”, you can click away now.
YAGNI stands for “you aren’t gonna need it”. It comes from extreme programming (XP). It can also be phrased as “don’t implement functionality when you think you’re gonna need it, only implement it when you actually need it”.
The principle may be easy to follow, but it’s not as easy to understand as it seems.
You Need Good Design at All Times
Does anything from the definition of YAGNI catch your attention? There’s one important detail that should be pointed out. It’s the word “functionality”. It seems like the whole focus is placed on the word “need” when people talk about YAGNI while forgetting about functionality.
The word “functionality” is often understood as “anything”, and the whole definition of YAGNI becomes “don’t do anything unless you need it”. That also eventually gets shortened to “don’t do anything”. That sounds like excellent advice… if you want to mess up your codebase and then sit there regretting it until the heat death of the universe while putting all the blame on those stupid requirements… if only they weren’t so stupid…
You shouldn’t apply the “don’t do anything” part. There’s one important thing that you do need at all times. What is it? Good code design. No matter what features you’ll be implementing or when, you always need to have good design.
YAGNI and bad design don’t go together
The bad part is that the time to implement new requirements always comes. You can get a request for any new feature at any time. Without a codebase where you can easily add new features, you’re doomed. YAGNI and KISS are not going to help in such a case.
The problem is that YAGNI is often used as an excuse to not take measures to make a codebase easy to modify, because “you won’t need to modify it in the future”.
YAGNI goes hand in hand with good code design. Without good code design YAGNI doesn’t make sense, because no matter when you choose to add new functionality, it’s going to be expensive either way, likely even more expensive later.
What Does and Doesn’t Fall Under YAGNI
The question that follows is what does actually fall into the YAGNI category and what doesn’t?
Anything that’s a part of a feature or functionality you foresee needing falls under the YAGNI category. Any code that is written with the assumption that it’s for that particular feature you’ll need in the future. It’s most obvious when such code produces actual visible effects in the system.
Sometimes the code that falls under the YAGNI category doesn’t produce visible effects in the system. So how to know whether you’re doing something unneeded or not?
If you’re writing something with the thought of some specific feature in mind, then don’t do it because you won’t need it.
If you’re writing something without a specific future feature in mind, then it’s fine. For example, decoupling something is fine, splitting responsibilities is fine, encapsulating concepts is fine…
The keyword here is specific.
Let’s say you decide to create an interface that allows you to save a user record in some form of storage when you only need to display it on the screen (just the interface, no concrete implementations). That’s something you shouldn’t do, because you don’t need to save records, you only need to show them on the screen. This is an example where the change you want to do is related to a specific feature, which is the storage in this case.
However, let’s say you decide to create an interface that consumes a user record with the purpose of decoupling ways of record processing from the rest of the system, then it’s fine. Then, if and when the time comes to save the records, your design will allow you to do so easily, and all you’ll need to do is to create a new implementation of that consumer interface.
The difference in the latter example is that the decision to create an interface was made to improve the existing design and make it more robust, because, previously, displaying records on screen was coupled to other parts of the system, and creating an interface for storage wouldn’t have made any difference to improve the design. As you can see, no specific feature in mind in the second example. It’s an example of how good design decisions complement YAGNI, the decoupling wasn’t done for storage specifically, and the ease of saving later was a nice side effect.
Good design is essential if you want to apply YAGNI.
The changes that are not visible in the system are why many discussions arise. I recall discussions where simply applying the single responsibility principle was argued to be a thing that’s not needed, because “we won’t ever have to modify that class in the future”. The discussions literally took more time than actually making changes in the code.
When arguing about something takes more time than actually making code changes then it’s very hard to call it overengineering (I don’t mean obvious cases, like creating a constant for every variable that’s used in one place), if anything, the discussion itself was overengineering.
YAGNI Doesn’t Mean You Should Be Reckless
YAGNI doesn’t mean that you should ignore software design and start writing code recklessly, because that’s how a lot of people interpret the principle.
It seems that YAGNI is constantly being abused as an excuse to deliver garbage, along with DRY and KISS. DRY is being abused in a way that introduces a lot of coupling, and KISS is being abused in the same way as YAGNI, to write anything as long as it works. The simpler a principle sounds, the easier it is to abuse and misinterpret.
It feels like we’re at the point where the ideas of software design got lost to time, because of the rising number of software developers who got into the field just to make money and don’t care about good software design at all, and we’re driven by trends, and everyone wants to challenge old ideas because it’s cool and gets a lot of clicks, and it’s obviously “overengineering” and an “anti-pattern” if you apply them, and rules, patterns, strict types, and all that kind of stuff is for the old Java dudes who like to write boilerplate-driven instant-legacy code. I’m being sarcastic here.
I know, every rule has an exception, it’s just that the “every rule has an exception” statement is being taken to the extreme, and any code that is independent of the framework or is not a part of a React hook is “overengineering”, so everyone should stop writing it because YAGNI. That’s just reckless if you ask me.
TL;DR, if you’re having trouble deciding whether or not something should not be done because YAGNI, think about the reason you’re making the change. If you’re doing it to improve an existing design, go for it, if you’re doing it for that specific feature in the future, then don’t.
To apply the YAGNI principle you need a robust code design, so don’t be afraid to invest some time to achieve such a design.
Good design decisions are not something “you won’t need in the future”, so don’t make that excuse.
Stop Using YAGNI as a Lazy Excuse to Write Bad Code was originally published in Level Up Coding on Medium, where people are continuing the conversation by highlighting and responding to this story.
This content originally appeared on Level Up Coding - Medium and was authored by Giedrius Kristinaitis
Giedrius Kristinaitis | Sciencx (2022-11-04T02:44:44+00:00) Stop Using YAGNI as a Lazy Excuse to Write Bad Code. Retrieved from https://www.scien.cx/2022/11/04/stop-using-yagni-as-a-lazy-excuse-to-write-bad-code/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.