top | item 9605733

Yagni

271 points| petercooper | 10 years ago |martinfowler.com | reply

178 comments

order
[+] eridius|10 years ago|reply
Something this article largely ignores is that often you want to build the support for the presumptive feature now because the act of implementing it affects architectural decisions. It came close to this by saying

> it does not apply to effort to make the software easier to modify

But there's a difference between making software easier to modify (where the same effort could be expended later to retrofit the software) versus making architectural decisions. Often times trying to implement something teaches you that your architecture isn't sufficient and you need to change it. If you can learn that while you're building the original architecture, then you've avoided a potential huge amount of work later trying to retrofit it.

To use the example from the article, what if supporting piracy risks reveals that the fundamental design used for representing pricing decisions isn't sufficient to model the piracy risks, and the whole thing needs to be reimplemented? If you can learn this while implementing the pricing in the first place, then you haven't lost any time reimplementing. But if you defer the piracy risks by 4 months, and then discover that your pricing model needs to be re-done, now you need to throw away your previous work and start over, and now your 2-month feature is going to take 3 or 4 months instead.

[+] saganus|10 years ago|reply
As I get older, both as a person and as a dev, I have come to the same realization as you: that a lot of the time I end up building things that I don't need "right now", but which I have to at least plan at the architectural level, lest be it a nightmare later on.

And then it hit me.. THIS is one of the areas of software development where I don't think reading more articles, techniques "mantras" etc will help. Only more practice will help. It ends up boiling down to how much experience as a developer you have, making those particular decisions.

I.e. It's a craft, not a science.

So as you grow up as a developer you suddenly find that you start to have certain "intuition" as to why I should actually plan for something that I don't need, vs actually ignoring something (a real "yagni"), but you just can't explain it in terms of generalizations. You end up saying.. "well.. it just feels like I Should do this, because I have been burned in the past when I ignored this intuition"

And I don't think I'm alone in this train of thought.

[+] lowbloodsugar|10 years ago|reply
1. My team will not have to throw away our previous work. It works for storm pricing. It is deployed. Customers are using it and we are making money.

Your company has yet to deploy a storm pricing model because it got caught in the complexity of the piracy model.

2. When it comes time to write the piracy pricing system, my team has already gained a huge amount of relevant experience from writing the storm pricing system. In my experience a team that already has developed a simpler system will be better able to develop the more complex system.

3. If piracy pricing is a significant risk then it should be prioritized higher. If it is late because you thought it would take two months and it took you four, then you failed to assess risk. A really good way to assess risk is to implement something similar (may I suggest storm pricing).

However, in my experience, even if we know we want to ship storm and then piracy immediately after, I will still ask my team to develop storm first to completion. And I will stand any one of my teams up against a team that is going to "do it all in one go", and we'll get them both done before the other team.

4. Basically when you make an argument that is "Suppose you have this situation...", then it is equivalent to saying "This thing happened in the past, and if we had known then what we know now...."

They are equivalent because now matter how your frame your "thought experiment", it is guaranteed to never happen in real life. The whole point of YAGNI is that you cannot know the future, and no one ever has. The only way to know for sure that "this is how its going to turn out" is to actually be in the future.

So, yes, if you had a time machine, you could argue that big upfront design would work.

Of course, if you were to start your argument with "Suppose I had a time machine and I could go back in time and tell my team that the piracy model is a perfect superset of the storm model, but is twice as complex because of x, y and z, but there are no other unknowns, and customers love it, and the Navy doesn't kill the pirates, and so therefore we should do it all in one go" then it would be much more obvious that your argument was flawed.

[+] mkozlows|10 years ago|reply
So the thing is, yes, this hypothetical thing will affect your architecture. That's true. But what's also true is that a) this other thing over here you're not aware of will ALSO affect your architecture; and b) the thing you're planning ahead for might never happen.

Which is to say the really obvious: The future is unknowable.

Some people react to this by saying "okay, let's make everything as general as possible then, so we can be prepared for an unknowable future" and architect up a forest of abstractions.

Some people (the YAGNI crowd) react to this by saying "okay, let's making everything as simple as possible, so it's easy to change in the future when we know things" and rigorously eschew unnecessary abstraction.

In my experience (which includes creating, maintaining, and managing a single large application for a decade), the YAGNI crowd has the right of it. Complexity is a cost, and you should only incur it if you absolutely, no-question need it.

[+] nostrademons|10 years ago|reply
I don't think YAGNI ignores this so much as explicitly rejects it. I've participated in the type of rewrites you mention here. Yes, they suck. Yes, they happen far too often. But I've also observed that they seem to happen regardless of how much you plan ahead to future requirements: even if you are exhaustively brainstorming possible future directions and are absolutely sure you're going to want something, you're very often wrong. And the inevitable rewrite that happens is a lot more painful when you have to carryover requirements that you don't actually need.

YAGNI fundamentally is a statement about costs and benefits. And it's a statement about personal experiences of costs and benefits, with a counterintuitive conclusion. I've found, however, that the teams I've worked on that just accept that they'll have to rewrite or throw away 90% of what they write end up performing at a much higher level (in terms of their impact on the broader industry) than the teams who figure "But if we could just get that 90% down to 50%, we'll be 5x more effective than other teams!"

Another way to look at this is in terms of external vs. internal drivers of success. YAGNI makes sense when the primary drivers of success are external and you need to quickly react to changing market conditions or customer requirements. It doesn't when the primary drivers of success are internal and you need to quickly act to get from known point A to known point B as efficiently as possible. Some engineers are lucky (unlucky?) enough to work on the latter, but typically it only happens when you either have a monopoly or you're deep in the bowels of a corporation and only need to report up to an executive who never changes her mind.

To use the example from the article - if the biggest risk or change in the external environment you'll face is your software, go ahead and build the feature into it. But who knows? You may be able to close a round of venture funding in 2 months and then hire the Gondor navy to eliminate piracy. Or Gondor may enter into a trade agreement with Rohan and redoing all your contracts takes primacy. Or Aragorn may arrive with the Army of the Dead and suddenly piracy is not a problem anymore, but a lucrative business in life insurance may pick up.

[+] pimlottc|10 years ago|reply
But on the gripping hand, deferring an implementation often means you understand the problem better by the time you get to it, so that your actual implementation is better than the naïve version you would have written earlier.
[+] krupan|10 years ago|reply
I dealt with this recently. We wrote a system that had a hard-coded data size in it. Later, that data size had to change to a flexible value chosen on the fly, and I was the one that had to go through all the code to make all the changes so we could handle that. It took a long time. Partly because we had no unit tests (a whole 'nother discussion), partly because I wasn't familiar with the area (all the areas) of the code that needed to change, and partly because we had said, "YAGNI" and not made our code configurable enough from the get go.

I started to curse YAGNI in the middle of that chore, but then I paused and thought about the many months of productive use of this code that we had been enjoying before this point. And even though it took me significant time to make that change, the production code was still running along just fine during all that time, still bringing us value. I decided that I was glad we had said, "YAGNI" at the start.

[+] rsp1984|10 years ago|reply
In my years of experience (both in big corporate R&D as well as startups) I've never seen a project fail because of the end product being too simple or not having enough features.

However on the other hand I've seen countless projects suffering delays, staff departures, emotional team arguments and eventually bad end product because of too complicated software architecture that overwhelmed its creators and because of obscure features that well-meaning engineers built in because "it'll save time in the long run".

Btw this well known XKCD sums it up just perfectly: http://xkcd.com/974/

[+] beat|10 years ago|reply
As always, it's a joy to read Martin Fowler.

It's so, so hard to resist the siren song of premature optimization, though. It's even harder in a corporate environment where "Well, why didn't you plan for that?" is a question lurking behind every failure or delay. Overplanning isn't punished.

[+] pbreit|10 years ago|reply
In startups, overplanning is punished by company failure.
[+] mkozlows|10 years ago|reply
This is becoming less true over time. As enterprises start adopting Lean practices, it becomes obvious to everyone why building something now when you won't use it for months is waste.
[+] briandear|10 years ago|reply
I disagree. If overbuilding or over planning is wrong. Then the question comes as to why you spent $200k building a feature that just got thrown out. Or worse, they try to use a unneeded feature just to justify the fact that it was built.
[+] jonahx|10 years ago|reply
These days, I think "Yagni" is often used as an excuse for sloppy code and as a justification to avoid thinking about design.

I think the principle as Fowler describes it is valuable, but it can be easily abused. Taking the application of "Yagni" at the microlevel to its logical conclusion can be used to justify a mindless, just move on it and fix it later style of coding into which good architecture cannot be retrofit.

[+] lmm|10 years ago|reply
I have yet to see up-front "architecture" add value, and I have seen it sink a company.
[+] robmcm|10 years ago|reply
Unfortunatly most "buzz words" can be used to avoid doing work, this seems to be the selling point of Agile in a lot of places I have worked.

I think what the pro and anti YAGNI groups can agree on is that maluable code is better.

[+] endymi0n|10 years ago|reply
We have one rule when planning product features: Everyone may shout YAGNI at every time. Saved us so much time and complexity, it's incredible.

On the other hand, I have a love/hate relationship with YAGNI, as it requires careful weighing - additional features that need to be reflected in architectural changes which would not only take refactoring code but API and data model changes as well, possibly with data migrations, coordinated across multiple teams are a completely different picture. The costs of building it now may be an order of magnitude cheaper than doing it later. Further down the road, startup mechanics and traction apply as well. If you have an order of magnitude more resources to fix YAGNI later, it might be worth the additional speed right now. I feel that putting all of these into context and doing something that makes sense is just freaking hard every single time.

[+] bsder|10 years ago|reply
Except that Fowler used YAGNI to produce the "Chrysler Comprehensive Compensation System" that FAILED MISERABLY. I still don't understand why people continue to listen to him--he has yet to demonstrate a large project he was in charge of that succeeded.

YAGNI gets you the easy 80%. The problem is that YAGNI means you didn't prepare for the hard 20%, and now you're going to get killed.

Of course, YAGNI is really good if you're an ambitious manager since you'll be gone when the 20% comes home to roost.

[+] chris_va|10 years ago|reply
I think this is trying to simplify an already simple idea, succinctly: "Optimize your time intelligently".

Rules of thumb (like YAGNI) may not be correct, depending on the situation. Estimating time complexity is hard, so deferring development defers mistakes in estimation. Great.

However, if you know that you have a 90% chance of needing a feature in 6 months, and it will be 2x easier to build now when you have a team actively engaged on a similar project, then YAGNI is the wrong choice. Counter examples exist, like you are in such an extreme environment where (like first month of a startup) the opportunity cost of those programmers is very high.

Regardless, I would ask "Is this the best use of time now" rather than "YAGNI".

[+] pbreit|10 years ago|reply
The whole point of the article is that you're wrong. And I tend to agree. Not trying to predict feature needs down the road is extremely empowering. Building you're unnecessary feature now is just as likely to increase the complexity of everything in the future as it is to be 2x easier to build now. YAGNI dramatically simplifies the answering of your question: if it's not needed now, don't do it.
[+] sbov|10 years ago|reply
It's still not that straightforward.

What if features X, Y, and Z needed in < 6 months each are 2x harder to code because of the planning of feature B that has a 90% chance of being needed after them? You potentially "saved" time by doing feature B but depending upon the total time to code feature X, Y, and Z, 10% of the extra difficulty in features X Y and Z may still outstrip 90% of the time saved in feature B.

Nevermind that as feature B goes unused for 6 months bugs and incompatibilities may creep in. Eventually what you wrote for feature B may be mostly useless when you finally get around to actually needing it. I have had this happen on projects before.

[+] jmadsen|10 years ago|reply
I think it is important to differentiate between "early building" of features you don't yet need, and building in a way that doesn't require much refactoring in order to extend/add those features on.

More common than overbuilding features is overbuilding function or library capability. The right balance, IMHO, is _thinking_ about the extendability & designing for it but leaving out the actual details. This tends to lead toward good, SOLID designs that are easy to work with later rather than a blind-ally you need to spaghetti-mofongorate to get to work.

"Refactor later" is fine for folks like Martin Fowler who know _how_, and who haven't painted themselves into a corner with bad early decisions. It is a bit dodgy to tell the average mid-level dev who just wants to "get it done" so his Project Manager can check off their Excel spreadsheet that they are on time.

[+] moron4hire|10 years ago|reply
Extensibility is itself a feature, so YAGNI would imply it shouldn't be assumed until proven necessary.

I personally use the "zero, one, many" rule (i.e. those are the only counts of things, there is no such thing as 2 or 3, etc.) as my proof of necessity. If I ever get to the point that I need two of something, I make it useful for many of something.

[+] phamilton|10 years ago|reply
I'm always a bit surprised when we treat "cost" as something binary.

Successful people, in my experience, are those who take calculated risks and are right often enough to differentiate themselves. Software is no different.

When faced with a YAGNI situation, you need to make a judgement call. There will be costs in building it now. Those costs might be less now vs later (sometimes just because the context is fresh). The cost may vary depending on how much work you do.

There will also be "expected benefits". The estimated (judgement call) likelihood of actually needing it times the cost savings (future cost - current cost). Compare the expected benefits between projects and pick the one you expect to add the most value.

As pointed out by others, this often means simply drawing the abstraction in the right spot to make future development easier. Even if future development never happens, it's likely you built a good abstraction that was well thought out. The cost is low (you had to frame the abstraction somewhere) and the expected benefits are high.

[+] angersock|10 years ago|reply
Yagni only applies to capabilities built into the software to support a presumptive feature, it does not apply to effort to make the software easier to modify.

And here is where the actual frontlines of the battle are fought--because it's needlessly verbose and abstract architectures (or what people think are them, anyways) that are railed against by folks chanting "yagni yagni yagni".

This article neatly sidesteps the actual thorny issue of "well, when is designing extra actual a good idea?" by ignoring one of the biggest use-cases of yagni.

[+] apalmer|10 years ago|reply
I hear you, I think this article is really good for someone who isn't familiar with the term YAGNI. However as the above poster mentioned it sidesteps a big issue which is when YAGNI is wrong.

Generally I feel like YAGNI is appropriate for features but not appropriate for architecture. I feel like the purpose of architecture is to try to plan ahead, or to make the determination how far ahead one is attempting to plan. Its perfectly find to architecturally choose not to support something, but it should be a conscious decision.

[+] oinksoft|10 years ago|reply
This is just my experience, but "YAGNI" is often shorthand for "I don't want to think about it." I'm not talking about criticisms of wasteful design/features, but somebody actually saying "YAGNI" with little elaboration. It's imprecise and lazy.
[+] wrsh07|10 years ago|reply
Agreed -- the article cleanly argues for Yagni by moving the heart of the discussion to a bolded sentence near the end.
[+] webtards|10 years ago|reply
I think the ability to use YAGNI scales with the experience and abilities of the developer and the team. I have walked into wonderful lean codebases where an experienced hand has kept featuritus down to a minimum, but I have also walked into codebases where multiple kitchen sinks were not only present and plumbed in, but a pile of new ones were ready and waiting by the side to join them, and it was a massive distraction.
[+] addisonj|10 years ago|reply
These comments seem to illustrate something I have felt for a while: yagni is incredibly divisive topic and for every person saying praising it is another who is at the very least cautious of its application.

It makes me wonder where the divide is.

Perhaps more large 'enterprise' shops where projects can spin out of control into what they 'must have' whereas the small shops where you need to get a product out ASAP?

Or maybe age of developer, with the young eager guy confident he can whip out all n features in 3 weeks so we might as well add that feature too vs the experienced dev who knows better and we will add it once it is needed?

I have put some time and effort into asking people about this very question, but still am no closer to understanding why some really appreciate it and others hate the phrase.

Personally, my guiding principle after being bit by yagni is that it is a wonderful principle to use when making product/feature decisions but should be exercised very carefully when making architecture decisions. Which makes sense, features come on and go, but architecture is generally something you need to live with. In other words, whenever yagni is used is an argument against what are more good coding and design practices than practical problems, then it may be something more of a case of 'no really, we are going to need it'

[+] mtVessel|10 years ago|reply
Funny, I think of the age divide running the other way. Younger devs, who came up during the age of agile, take YAGNI as a given, while older devs have seen the results of too many hasty decisions.

The advice I was given when I started out was, "it's cheaper to fix something upstream". Catching a potential problem during design is always cheaper than catching it during development, which is cheaper again than catching it after release.

This argument always seems to get lost in the YAGNI discussion.

[+] spookylukey|10 years ago|reply
YAGNI only makes sense in the context of other extreme programming[1] practices, such as making code safe to modify through unit tests[2] and easy to modify because you refactored mercilessly[3] to produce a nice, modular design.

I suspect the divide in reactions to YAGNI comes between people who have embraced those practices and those who haven't (and probably don't even know what they would look like, and can't imagine an environment that uses them).

In the context of a project where making changes is hard and dangerous, and where you have few automated tests, you will be tempted to change a lot at once, so that you can then manually check everything works once, rather than having to do that multiple times. And that might well be the better strategy.

Consider the question "What if we need extra fields in our 'product' table?". The Extreme Programming answer is both 'embrace change' and YAGNI. That means 1) we absolutely definitely require some general mechanism to be able to add columns to tables in the future, so we must have that in place, and not assume the product table schema is fixed forever 2) we have no idea what columns or how many columns will be needed in the future, so we don't add any now speculatively.

But many people work in environments where adding a column to a table would be a massively expensive task (thousands of stored procedures that need rewriting etc.). In this context, the 'YAGNI' response which just refuses to think about future does sound stupid, because it is.

[1] http://c2.com/cgi/wiki?ExtremeProgramming [2] http://c2.com/cgi/wiki?UnitTest [3] http://c2.com/cgi/wiki?RefactorMercilessly

[+] TillE|10 years ago|reply
> It makes me wonder where the divide is.

I think it works beautifully if you're applying it along with "refactor mercilessly", backed by good unit tests. It's a principle that doesn't necessarily stand on its own; it needs to be part of a healthy, iterative system of development.

If refactoring becomes difficult or dangerous for whatever reason (eg, designing an API for long-term, widespread usage), then YAGNI may not work.

[+] robmcm|10 years ago|reply
The use case in these discussions is never about framework or shared code.

Taking the example of the lookup tables for error messages, imagine if you shipped your framework and lots of teams started using it, then you iterate to change your APIs in a breaking way and suddenly the cost of that change is multiplied by all the teams refactoring.

It is also worth considering the cost of changing existing production code, this is typically where most bugs are introduced, especially when someone else is implementing the fix without the domain knowledge of the original author. Unit tests won't help if they also have to be re-written to match the new API, as they are by definition new/different tests.

I think writing malleable code is the key takeaway from this article, and if thinking about future possibilities helps with this, then it should be encouraged.

Being unable to predict the future doesn't mean you shouldn't anticipate and prepare for change.

[+] anigbrowl|10 years ago|reply
There's an extensive literature on opportunity costs in economics, but you wouldn't know it from reading this article, even though that's basically what it's about. Discussions of programming methodology often seem to involve reinvention of the wheel. Has there been any work done to quantify these theories?
[+] lowbloodsugar|10 years ago|reply
I used to play Age of Empires. Its a real time strategy game where a common match is for two teams of three to try to kill each other. A feature of the game is that each player can spend resources (gold, wood, etc) to reach new "ages". Players start in the stone age, and advance to tool, bronze and iron ages. Each new age offers better weapons, better technology, greater efficiency.

Consider two games. In the first game, we observe that the players take on average 30 minutes to get to tool age, and only one player ever makes it to iron age before a team is victorious after about two hours.

In a second game, we observe that the players average ten minutes to bronze age and all but one player makes it to iron age before the game is won after about an hour. All players invest in technology before fighting.

Who are the better players?

[+] pdpi|10 years ago|reply
I can only assume that the point you're trying to make is that there's not nearly enough information for a reasonable answer. It's certainly hard to come up with solid ideas without a clear understanding of the game's pacing.

In RTS games, teching and building armies compete for resources, so I'd hazard guessing that Game 1 happens because somebody opted for early aggression, which forces everybody to spend money on units to fight off the early threat. Looks like a well balanced game where both teams kept the aggression level high, which justifies the long duration, and the low-tech end-game.

Second game looks like there was little to no early-game aggression, which meant that everybody got to funnel resources into teching up early. I'm not sure if late-tech battles are more all-or-nothing, or whether one team was just clearly stronger than the other -- though if that's the case, why didn't they push for an advantage earlier? AoE is much more symmetrical than, say, Starcraft IIRC, so one team having a weaker early game but a stronger late game doesn't seem likely.

I'm curious, though: how does this relate to the article?

[+] regularfry|10 years ago|reply
The best* players are the ones who gank their opponents in 10 minutes using clubs and pointy sticks.

*For certain values of "best"

[+] mc808|10 years ago|reply
Other than the navy wiping out all the pirates, I foresee a couple of other unforeseen scenarios:

1. Within the next few months, a new risk emerges with higher priority than piracy. Implementing this feature will delay the piracy addition, but only by 1 month because much of the basic "support multiple risks" problem will be solved by this other feature.

2. Within the next few months, a new product or tool will become available/known that makes it trivial to support storms, piracy, and a dozen other risks, making this whole effort redundant. It may be impossible to migrate to the superior alternative if all the resources are already tied up in a half-finished project that has generated no benefits to date.

[+] pbreit|10 years ago|reply
I love how these types of articles always bring out the architecture astronauts with all their pronouncements of "it depends" and whatnot. How hard is it to understand the notion of "building what you need, and not what you don't"?
[+] asgard1024|10 years ago|reply
> How hard is it to understand the notion of "building what you need, and not what you don't"?

Very hard, because it's in fact a tradeoff. Let's say you are building a house. Will you have wife and kids in the future? YAGNI says you can always expand your house once you have kids. But do people really build houses that way?

To take more extreme example, first thing you expect from housing is a protection from elements. So according to YAGNI, you should build the roof first, and see if it's good enough for you (and you don't bother, for instance, that you can only stand in the middle of the room). Again, no one really does that with real houses.

The whole art of engineering is to pick the reasonable tradeoffs, and this includes hedging against the risk of future expansion. That's why simple pronouncements as YAGNI are not of much help.