This blog post answers these questions:
A couple of years ago, I was a part of a team building software for embedded devices. Writing code for embedded devices is excellent, but you can also screw up things badly. One day, it happened to us. We got a call from one of our customers complaining that our service caused the entire device to crash. We looked into it and found that we were using a 3rd party library with a memory leak.
We started brainstorming solutions for this issue: replacing the library with another one or fixing the library’s bug. We even considered writing our implementation for it. But then, one of the developers asked — Why? Why are we using this library? It turned out we were using it in only one feature of our product. Then we asked ourselves — Why do we need this feature? It turned out that this feature was not in use. We created it for future customers. Eventually, we decided to delete this feature. To this day, this feature is not a part of this product.
This incident is an excellent example of what happens when we don’t follow the YAGNI principle.
YAGNI is a principle of Extreme Programming, an acronym for “You aren’t gonna need it”. According to Extreme Programming co-founder Ron Jeffries, you should “Always implement things when you actually need them, never when you just foresee that you need them”.
This principle is so important because when we don’t follow it, we pay a couple of different prices, explained thoroughly by Martin Fowler:
When we build something, we pay the cost of building it. Humans are not good at predicting the future, and this cost is wasted when we build something that we eventually don’t need. But what happens if we manage to predict the future correctly? Even if we build the right thing too early, we still pay some prices.
When we build something we will need in the future, we are not working on things we need right now. Our customers and our company need stuff from us right now. When we work on future needs — we delay those required immediately.
The cost of carrying is the cost of maintaining the code from the moment we create it until someone uses it. Our code gets compiled and tested a couple of times a day. When other features are developed, we need to check how they interact with the existing ones. Our code is being read by other developers and by ourselves. All of this costs us a lot of time and money.
We often refactor our code or change how it is structured. When doing so, we pay the price of repairing our code to be built in a way we now know is the right way. If the specific code that is not needed yet were written after the refactor, the cost of repairing it would have been saved.
If we build something too early, we always pay the cost of delay and carry. In case what we build is not needed eventually, we also pay the cost of build. If we discover later that it was built wrong, we pay the cost of repair. We avoid wasting those prices when we build the right feature when it is needed.
So what can we do?
Your code should fit your needs right now, be easy to read, and be easy to change. Don’t add extra functionality. Don’t add additional interfaces to make it easier to extend in the future.
Ask why? Ask your product manager: Why are we building this feature? Ask your colleague during the design review: Why do we need this interface? Ask yourself: Why do I need this function? And if the answer starts with “Because in the future we may want to…” it is a good indication that you are not gonna need it.