This doesn't mean you should avoid building flexibility into your code. It means you shouldn't overengineer something based on what you think you might need later on.
This also follows the KISS theorem: Keep it simple, stupid!
There are two main reasons to practise YagNi:
You're working on some class. You have just added some functionality that you need. You realize that you are going to need some other bit of functionality. If you don't need it now, don't add it now. Why not?
And unless your mind is very different from mine, there is a high chance that you won't need it after all, or that you'll need to rewrite or fix it once you do need it. If either of these happens, not only will you waste time overall, you will prevent yourself from adding things that you do need right now.
To the tune of "We're Not Gonna Take It" by The Who, from the classic rock opera "Tommy", which is highly recommended.
You ain't gonna need it! Never did and never will! Don't need featuritis And the users will never tell. You ain't gonna need it Half a feature's better than none... ||: Test me... Code me.. Refactor me... In'grate me... :|| (x8) List'ning to you, we get the features Planning with you, we get priorit-eees Coding for you, we build releases Pairing for you, we make deliver-eees - Phlip (on the XP mailing list)P.S. There is another song with the same name, featured in the teen testosterone flick "Iron Eagle", "Twisted Sister". ''Both bands did (rather different) songs of that name; the takeoff here is based on the rather earlier one by The Who.
You have a ReleasePlan: each UserStory has been assigned to an Iteration where it will be done. Under the current IterationPlan, you are working on an EngineeringTask that you signed up for, in support of one of the Iteration's UserStories. As always, you have signed up for as much IdealProgrammingTime as your LoadFactor indicates you can accomplish.
You are evolving the system to have the new functionality required by the UserStory, defined in the EngineeringTask. You add capability to any class we need to, directly growing from the requirement. If you find yourself writing duplicate code, you refactor to eliminate it, even (perhaps) adding an abstract class, or making a subclass, etc. You and your co-programmers always keep the code clean.
You're building a class, and suddenly you get an idea for a feature you could add to it. You don't need it right now, but "Someday we're gonna need ...", you say to yourself.
Keep in mind that you are employing other ExtremeProgramming practices that allow you to deal with the future when it happens. CollectiveCodeOwnership allows you to change anybody else's code to give it the functionality you want. RefactorMercilessly and OnceAndOnlyOnce make it easier to understand the best way to add your functionality. UnitTests help ensure that your added functionality won't break any past functionality. So if you do need to implement this feature in the future, it probably won't be much harder than it would be to implement now.
At this moment, you have a choice: continue working on what you signed up to do, or begin working on something you didn't sign up to do, and that isn't needed in this Iteration.
Therefore, tell yourself YouArentGonnaNeedIt. Set aside your thoughts and fears about tomorrow and get back to work on today. Without a clear use for the feature, you don't know enough about what is really needed. Spending time on it is speculative at best.
How serious are we about this? Here's how serious: if a developer finds a method in the system that is not sent, she should remove it. Ditto unused classes, in spades.
The upside in a nutshell: it keeps the system small and understandable.
The downside would seem to be that it may take longer in the future to do something that would have taken less time now. This turns out not to be the case. It has never happened in two years on the C3 project that we wish we had added functionality we didn't need at the time. There's something of the self-fulfilling prophecy about this argument. I've been trying to persuade myself to adopt YAGNI more rigorously for several years, but I haven't managed it yet. As a result, I occasionally come across cases where I think I'm glad I didn't. On the other hand, if you've gone bankrupt implementing features you didn't actually need, you'll self-fulfill in the other direction.
Replacement/paraphrase of deleted comment: "Ummm...but the C3 project didn't turn out so well, as I understand it, so how well does it really serve as an anecdote?"
There are, on the other hand, places where the system isn't what it ought to be. These are mostly due to these causes:
Traditionally, ordering your implementation efforts has been done by subsystem - you implement everything in a subsystem's interface, and then move on to implementing the next subsystem, and that makes for a lot of useless overhead with a BigBang at the end where you do all your testing and QA. YouArentGonnaNeedIt is suited to an iterative or evolutionary development method whereby you do a fair amount of planning and architecture definition up front, and then implement by feature-set rather than by subsystem. -- PeterMerel
As I just wrote in ShieldPattern, I think this is an example of a force, not a pattern. There are circumstances where premature work would be wasted. There are also circumstances where a little bit of forethought and planning has saved me enormous effort further down the line. The best way to balance conflicting forces may not be to yield to one of them. (PS. I think identifying forces, and their strengths, is a valuable contribution - see PatternComponent.) -- DaveHarris
I suggest that the forces are the cost of investing now, vs savings then, or something like that. The pattern would be "Do it now" or "Do it later", perhaps?
Not only might you not need it in the future - even if you do, it might not take the exact form then, that you can anticipate now. Also, how are you going to test it, if you don't need it now?
The one exception that I would make to this is consistency with standards. For example, if I have a standard that I always provide a getter for any setter, I will add it immediately, even if I don't need it now, lest someone trying to maintain the class later assume that I really intended the attribute to be write-only. -- RussellGold
I've been meaning to say this for a while. Here goes. I think that much of the conversation that we have been having about ExtremeProgramming practices, and many of the contentions, have been because of PrematureGeneralization. Not in code, but in concepts. YouArentGonnaNeedIt has spawned an incredible number of subpages and back and forth discussions. I'm now convinced that this is because the words YouArentGonnaNeedIt themselves have no context. At first glance, that is without reading further and looking at Ron's page and much of the discussion, the words can be used to justify just about any form of avoidance right down to hacking.
That said, I understand what is intended by the words YouArentGonnaNeedIt, but it is only through context and example. The words themselves are aphorism that can be taken to be very general. I am excited about ExtremeProgramming and I hope that descriptions are published, but I also hope that enough context is published to prevent misunderstanding. -- MichaelFeathers
This is an interesting and important point, IMO. Kent and I both like strong statements, memorable phrases. "ExtremeProgramming" for example. To try to learn what a pattern is from its name, however evocative, is perilous. ExtremeProgramming and YouArentGonnaNeedIt aren't even patterns yet, they are characterizations of a philosophy that is undergoing change and testing every day. We XPers may be generalizing prematurely in thinking we know what we are doing: our readers are certainly generalizing prematurely if they assume that a phrase like YouArentGonnaNeedIt justifies hacking or writing only half a function. Thanks for putting this idea so clearly. Rewrote the lead-in in response. -- RonJeffries
Twice, in different organizations that practiced traditional CodeOwnership, I've seen situations where a developer got ahead of the rest of the team, and, rather than helping the team catch up, spent time making their yet-to-be-used code "reusable," adding features that would certainly be needed. But by the time the team caught up, more was known about the problem, requirements had drifted, the design had changed, etc. But there sat the developer with the work of art into which he'd poured all of his talents, unwilling to acknowledge that it wasn't quite what the rest of the team needed after all, and resisting requests for changes. -- DaveSmith
The "did you finish high priority task X?", "No, but I wrote this neat new feature" conversation doesn't just happen between programmer and PMs. More than a few times as a programmer I've had to prod my fellow coders to complete work I'm dependent on for my progress. As much as I might like to do mine and my co-workers tasks, I've never found that conducive to meeting schedules. -- StevenNewton
In the large C and C++ projects I've worked on, the implied message is often "we don't want to touch that part again," since touching often means recompiling, and touching the lower levels may imply rebuilding most or all of the product. The fear I perceive in my co-workers is that if you don't do the lower levels right the first time, you're going to spend 60+% of your time just waiting for the product to build.
Change can be difficult when the tools don't support it. When it's possible you should choose your tools and processes to make change easy, but you don't always have that luxury, and the practices must bend accordingly. Nonetheless, all things being equal, a process that invests less in unnecessary futures will have more to spend on necessary presents (for the staff). The question becomes: what's necessary.
You can refactor C++, but it takes focus. The less people are allowed to refactor, the more the "get it right" fear takes hold. But if you have comprehensive unit tests for every part of the system, and you work hard all the time to reduce the compile time impact of changes - tightening up use of forward declarations, narrowing the interfaces between different packages - you can make it easier to have highly changeable C++.
People can refactor in C++. The perception that it's hard to do so is most of the problem.
And how large does a system have to be before you can't build it every day anyway?
If I was applying YouArentGonnaNeedIt while I was implementing #isLeapYear in Date, and I knew, from previous difficult experience, about all the various flavors of leap years, and I was acting as a moral developer (or if I was tempted not to, at least my partner was acting moral), then I would implement UnitTests representing all the interesting problems I knew about and I wouldn't be done with the EngineeringTask until they worked. If I didn't know about such problem, but I suspected them, I would do the necessary research before starting.
YouArentGonnaNeedIt is not the same as forgetting experience, acting stupid, or abandoning morals. It is a challenge to developers to abandon their fears of a far-flung future that may never happen and do an absolutely stellar job of solving today's problems today. Actually, when I violate this rule, it is typically because I am overwhelmed by my fears of not being good enough for today's task. Solving tomorrow's problem is an excellent avoidance strategy, because you can't be proven wrong.
A consistent thread here is that there are two different time periods, now and later. The anti-YAGNI folks seem to believe that in now, there is enough time to implement the needed features plus extra time to add possibly-desired future features (including generality and flexibility). This is good thing, because later there won't be enough time to add the newly-needed features, and only the efficient use of the extra now time allows later work to be successful.
If this is true, then what happens when it's even later? Does the project collapse under it's own weight? Does there need to be more time spent now to plan for the features needed even later (since there certainly isn't extra time later)?
The YAGNI rebuttal is that since there will always be an even later, treat now the same as later by doing now's work now and later's work later. -- JeremyCromwell
At times, I've seen the idea of leaving extra unused fields in data structures to be useful for expansion and backward compatibility. I'm not sure how to reconcile it with ExtremeProgramming, but in my experience it can work. Of course, empty space is not functionality. -- CayteLindner
When I have an "inspiration" to add a method to a class that isn't needed right away, I create it, but the body just throws an exception. That way I "save" the idea, don't spend the time writing the method, and it's easily caught in testing when it _is_ used.
Kind of like eating carrots when you really want a smoke. On C3, we would have to build a special convention. One of the ways we remind ourselves YouArentGonnaNeedIt is that all engineers routinely remove methods that have no senders. -- RonJeffries
... Bit aggressive that: do you dispense with backing up if you don't have a crash for a while too? :-o -- AndrewCates
How about an example: A client asks for a system to hold ten objects, so I write code using an array of size ten. A week later the client says that they want to add more objects on the fly. So I rebuild using a Vector (I'm programming in Java). I could've used a Vector first time 'round, but didn't because of YAGNI, and an array is by most definitions simpler. And now I've got to start from scratch. Is this a problem with YAGNI, or how I'm interpreting it?
When the client changes, amends, or further explains a requirements, some changes are to be expected. The point is to keep the roots of a change shallow to make it easy to pull out later. To guess and guess wrong about what a client's future intentions may be only grows those entwining roots deeper and make the choice even harder to rip out later.
In the example you've got, there's three sets of objects. They are the container, the objects to go into the container, and the clients to the container. The last two wouldn't have to be changed, assuming you've got decent encapsulation.
But if you choose the Vector to begin with, you might not be so careful about enforcing encapsulation. So if the customer asks you to store a list of Strings along with objects, and you have to change your container from Vector to HashMap, the change might be difficult.
The point is that the requirements are always going to change in unpredictable ways, so trying to design for that unpredictable future is a losing proposition. But you'll always need flexibility, so designing for flexibility is a winning proposition. If you have flexibility, then the cost of putting in the feature when it's actually needed shouldn't be much higher than putting it in at the start.
And is an array necessarily simpler than a container class? DoTheSimplestThingThatCouldPossiblyWork is a subjective standard and will vary somewhat individual to individual. (See WhatIsSimplest for more.)
Concur. The "simplest" thing is not a license to implement an under-designed solution to a system, particularly when your vision of the client's needs may extend beyond his own.
In other words, there is another pattern at work here: TheCustomerWillAlwaysWantMore?. No, really. Every single time.
No, you miss the point. If you put the customer's objects into a TreeMap instead of an ArrayList, just because you thought he would eventually ask you to index them by string, you're screwing the pooch. Do what is right for right now, and write good code. That's all.
I exercise forethought when we go on a car trip. I run around grabbing everything we might need or want on the road -- food, six different things to read, umbrellas, and of course baby stuff: the stroller, some blankets, toys, two snuglis, lots of formula, one diaper per hour, a whole big package of wipes...
My wife, on the other hand, exercises more forethought: she points out that we don't actually need most of the stuff, and that there's a lot of benefit to traveling light - we get going faster, we have room to bring stuff back with us, we don't have a bunch of stuff to bring in from the car when we get home late at night.
I wonder how she'd react to a new nickname: "Yagni". -- GeorgePaci
Perhaps, if you know that you're going to need to do X, then adding X isn't a violation of YAGNI or DTSTTCPW.
But suppose you implement X (needed now) and Y (you claim (correctly) that you'll need it) and the time taken to implement Y now takes you beyond a time limit of which you weren't aware. The project is cancelled, so you really didn't need Y after all. What's more, if you hadn't spent the time on Y you would have satisfied the GoldOwner/GoalDonor enough that the project would not have been cancelled.
I've worked with "balls out, get the job done quickly" programmers, and while that seems to be very YAGNI, it wasn't very Good.
That may seem to be very YAGNI but I don't think it's what the pro-YAGNI folks are talking about. YAGNI is a principle meant to be applied within the context of XP, or at the very least a set of practices that includes refactoring. As KentBeck points out toward the top of the page, adhering to YAGNI without the pairing, unit testing and refactoring (i.e. balls out, get the job done quickly) "clearly doesn't work." -- JasonArhart Huh? Blowing off mental masturbation and avoiding issues that aren't actually pressing doesn't require XP at all. YAGNI, and the sky ain't gonna fall!
I can't help thinking that there are essentially a set of well known exceptions to YouArentGonnaNeedIt where no experienced developer would seriously consider waiting until later on to implement a probable requirement. At the moment the only one I can can think of is internationalization. Would you really write a large financial application for a European multi-national with hard coded messages everywhere and worry about internationalization later? -- DavidPlumpton
If the client is deploying this application around the world, then you are going to need it, and it will be reflected in the UserStories to prove it. If the client is only deploying it in one office in the US, you aren't gonna need it. In the latter case, many would (and have) argue that you should put it in anyway; YAGNI disagrees.
There's no question that i18n is difficult. The question is: Is it much more difficult if you wait to do it when you need it? If somebody gave me pre-existing software and told me to internationalize it, the first thing I would do would be search all the code for instances of text-delimiting characters like ", ', and (if your language uses "here" documents) <<. I wonder if that would take care of the problem ... -- francis
No, I think i18n is a good example of something you would want to start doing from the beginning (or not too far into development). There are many considerations to be made throughout the development. However, YAGNI still holds if the client doesn't make it a priority.
It seems to me that hard-coded constants of any kind - messages, magic numbers, whatever - are inherently inflexible and should be avoided on general principles. You can make it possible to internationalize later without taking the time to fully implement your interface in ten different languages.
I think what causes much confusion for the readers (ok, I admit it: I talk about myself here) is where to draw the line between "foresightment" and "programming unneeded features".
Hardcoding messages for the user into the code does not sound smart - but it would apply to the YAGNI rule. I know when I write a program, that with high probability there will be an point in the future when someone wants a change to a message. Be it that the program is released in another language, or just that there is an spelling error.
If you used the YAGNI rule, you would have to search through the code for every message. If you had foreseen that (from experience), and written something to make messages easily accessible, you could have saved a lot of time. Or am I wrong here?
So is foreseeing later problems always bad?
Aren't UnitTests in some way breaking the YAGNI rule? Since you write something you only need if you write bad code?
ProblemDomain and applicability
May I make a suggestion. I think YAGNI, like most XP policies, is a good set of ideas to keep in mind, but another is "know your problem space". YAGNI doesn't mean you should choose an array of 10 spaces over a Vector. Most programmers know that if you need two, you need many, so if you have the choice, you choose a solution with the ability to expand. [A]
My motto has always been more along the lines of: Understand the problem space to the best of your abilities including required, optional and possible requirements. Once you have done this, program so as not to preclude the optional/possible requirements wherever possible.
There are exceptions. Twos may just be binary splitting; threes are almost always manys. -- Joshua Hudson [B]
I've very recently had an AhaMoment regarding this topic. For ages I've considered YAGNI harmful for various reasons, but what if we shift the emphasis to the YOU, as in YOU aren't gonna need it. Suddenly, we can drop all these discussions about time as YAGNI ceases to be a statment about now and then, and becomes a statement about you and them. This formulation sits a lot better with me, though of course it is very open ended as to who exactly you are (developer, team, or company?). -- RichardCordova
What is the OppositeOfYagni?
Would CoupleLeapingWithLooking serve the purpose?
Sometimes YouAreGonnaNeedIt (a good solution) because if you start out with something bad and continue to hack the bad solution (YouArentGonnaNeedIt), it might end up worse than if you had done some thoughtful design first.
However, HdykYagni? and SyrtYagni? are applicable as principles to counter such justification. I suppose that such a counter could get into even more questionable principles such as ButWeHaveNeverNeededItBefore? or EvenIfWeMayNeedItWeCantMessWithItNow?.
-- CarlCastro? (Carl R Castro)
Several people on this page have mentioned something I believe to be key to understanding YAGNI. Every programmer makes judgment calls all the time about whether to invest now for the future, or delay work to the future. The programmer must evaluate the costs of implementing more general and reusable code vs the cost of doing that more powerful implementation. It's the simple standard question of investment, which every programmer does on a daily basis. These things play out when deciding if you should invest in code:
1- What's the cost of the investment, of writing the "better" code now?
2- What's the cost of delaying? AKA How much harder would it be to write later vs now?
3- What's the likelihood of the investment being used, and how much value would having this investment be?
4- What is your time horizon? Do we need something now, and the future is less important? This is a very normative question which depends on the company, share holders, etc.
5- Opportunity cost. Could your time be better spent elsewhere?
YAGNI is simply an observation that many people do not base their designs on cost benefit analysis. They program for fun, for academic reasons, etc., and not for the company's bottom line, and this is a very bad kind of programmer to have in a company.
For example: the aforementioned case of using Java built-in array vs Java Vector. It's a simple decision. There is no cost to invest in the better implementation, the implementation using Java Vector, thus you should invest. You may or may not use the more powerful aspects of a dynamically resizing container, but you lose nothing by using Vector over an array.
However, you might have a case where you need to decide between single threaded, multi threaded, or distributed. There are definite costs in implementing the "better" system over the simpler system, so you need to do the proper cost benefit analysis as outlined above in order to reach a reasonable conclusion.
As a vague claim unsupported by facts, I tend to believe that a little investment up front for a cleaner design almost always pays off in the end. Not very YAGNI I know. However, in my current company, I see many many places where I wish people did practice YAGNI, instead of producing overcomplicated designs that are a pain to debug, enhance, and maintain.
Someone added the following text to the original story. I removed it to here because I think we reserve the first section for arguments in favor of an article. Maybe create YouAreGonnaNeedIt if you feel the need to embellish the story.
"Ron, stop being a dramatic prick. Let me explain this in terms even your feeble mind can understand. I have spent the last few days concentrating on this issue, and it is fresh in my mind. The probability of me generating bugs by adding the feature now is much lower than if I came back to this in a year or two and attempted to do it with imperfect understanding. Any programmer with any experience in the field understands this concept. If you don't understand this, you have no business being a programmer. Furthermore, there is some non-zero probability that it won't be me maintaining this code. It might even be--God help us--you maintaining the code. I know you'll get it wrong in various and subtle ways, so I'm saving the company from that."
YouArentGonnaNeedIt has generated many related pages. If you have comments or questions about YAGNI, please consider using one of the pages below rather than adding new comments to this page.
You might or might not need it: