Defending YAGNI

March 2, 2004 12:27 AM

Apparently, YAGNI is arrogant. I feel that given the amount of stick it's received over the last few days, I should put a word in for it.

First, let's clear away the straw men, and present a reasonable argument for "You Aren't Going to Need It".

  1. You can build it now, or you can build it later
  2. If you build it now, it will take 'x' amount of time
  3. If you build it later, it will take 'y' amount of time
  4. You don't need it now
  5. That's 'x' amount of time that could have been spent on something you do need now
  6. Or, that's 'x' amount of time earlier that you could have delivered working code, if you weren't busy doing something you didn't need to do
  7. If you do it, and it turns out you don't need it after all, that's 'x' time wasted
  8. If you don't do it and it turns out you do need it, you've wasted the difference between 'x' and 'y'
  9. Additionally, unused code, or code that is complicated due to requirements that are not yet realised:
    1. Is still a potential source of bugs
    2. Slows development
    3. Hinders maintenance

YAGNI tells us that too often we over-estimate the difference between 'x' and 'y', and we over-estimate the probability that we will actually need the thing that we envision now. Chances are that later, when we need it, it will take a completely different form because of the way it must interact with other pieces of the program that have been created since.

YAGNI is a defense against pretty much every programmer's (including my own) desire to find general solutions, even when we are being paid to do something specific. We often fail to notice that the cost of making something flexible enough to meet future requirements now is about the same as it would cost to add the same flexibility later. We vastly underestimate what a good programmer can do with a codebase given a free afternoon and a good refactoring-aware IDE.

Is it really that scary now? Stripped of the zealotry on both sides, it's a pretty simple equation. In many cases, the values of x and y are pretty close together, even indistinguishable. This is the case with most individual 'features' of a program. In many others, there are some basic design and factoring steps you can take to move them closer together and avoid problems in the future. This is why we tend to layer systems and encapsulate components.

Of course, applying any doctrine blindly is dangerous. In some situations, such as when you are publishing interfaces to a third party, you just can't bring the two values closer. You just have to bite the bullet and decide if you're willing to wear the risk of spending the time on something that you may not need. Similarly, the cost of adding things "later" that pervade an entire program, like security or robust error-handling, spirals out of control the bigger the program gets, and must be catered for from the start.

YAGNI protects us from wasting time, and protects us from over-architecting. Applied blindly, it can lead us to code ourselves into corners that take an age to dig out of. Taken to ridiculous extremes, it results in overly simplistic software that collapses under its own weight and has to be rewritten from scratch. Used rationally, however, it tells us not to implement features or architect clever "flexible" solutions just in case: it asks us to keep in mind that there is a cost to everything, and that we should prioritize development of things we know we need over things we might need later.

It's not a radical idea, really.

Previously: On Brand Loyalty

Next: Bugs, Bugs Everywhere!