if Yagni (YouArentGonnaNeedIt
) is considered in isolation from other practices (the naive approach). It is obviously foolish to follow Yagni and only Yagni, though some proponents of XP sound like Yagni alone will solve every problem. Of course, BookXp
does not take this naive approach, and neither do most of those proponents (as you may find if you ask them questions to get at the root of what they mean). Often there is an underlying assumption that Yagni will be immediately followed by ReFactoring
, but this assumption is not always spelled out. Not spelling out this assumption is a big reason that Yagni and XP are misunderstood by those unfamiliar with them.
Then there is the issue that eventually
going to need some feature. The trouble seems to be figuring out WhenAreWeGonnaNeedIt
is pretty clear on this, but there are misunderstandings in the community at large.
Then there is the ultimate issue that sometimes following Yagni means you make a decision not
to include a feature, and that feature ends up being needed. As long as the customer is the one making the decisions about what to include and what not to include, this is a perfectly valid course of action from an economical standpoint. See the EconomicsOfYagni
. This is often difficult for experienced developers to accept because they know
that a certain feature is going to be needed, and they believe that it will be cheaper to implement it now than later. However, it is not up to the developers to make decisions about business value. Consider for example that the customer may have the need to show features A, B, and C to her superiors, but not feature X. The developer may know
that delaying feature X will end up costing more down the road. In this case, the developer might decide to implement A, B, and X instead, disregarding C. But perhaps C was 'minor' in the developer's eyes, yet 'critical' in the superior's eyes. This is not the developer's decision to make. The developer should instead communicate to the customer the cost-estimates for including or excluding feature X and let the customer make the final decision.
I'll argue your example of A, B, C, and X. If X is the next UserStory on the stack, then you are gonna need it. That's the definition of what you're going to need: the most important feature to add is the next one the customer wants implemented. YAGNI doesn't apply to user stories, it applies to coding constructs to implement those stories.
is the one XP principle that I just can't buy. If you were told to make a system produce 3 reports, Yagni would tell you that you should just implement those reports in the most direct, and probably non-extensible way. But I would rather design a metadata-driven reporting engine from the start that makes it a snap to add additional reports when they are requested... because even though you supposedly won't need it, trust me, you will.
But wait! See TheSimplestCode.
What would happen if you never implemented a feature you didn't need right now, but you
did keep the code very clean and modular?
Would keeping code clean and modular (which by the way everyone should do, not just XPers) for a feature that was designed in one particular way provide any amount of head start or save any money when you had to re-implement the same feature in a more generic way? Possibly and possibly not. I think you would have to answer that question on a case by case basis. I don't think you can just say YouArentGonnaNeedIt
it all the time, just like you can't say YouAreGonnaNeedIt
all the time. My point in starting this purposefully provocatively titled YagniIsBologna
page was to point out that I think there are a lot more YagniExceptions
out there than most XPers care to admit. I want XP to account for these exceptions and give guidelines to, as another pointed out, WhenAreWeGonnaNeedIt
Maybe you will need it. However, it still might be the best choice to defer the generalized implementation until you actually do need it. When this moment comes,
- you'll have more information than you do now.
- you'll have a simple, malleable codebase because
Is a metadata solution the best? There might be a better way. Why not just implement the reports in a direct way, refactoring the common parts into one place? It is possible that you have superior Spidey-Sense when it comes to knowing this sort of thing, or maybe in this particular situation. However, when we run out of confidence, we fall back on to the techniques of traveling light and listening to the code.
If you are tasked with code to produce 3 reports, doesn't that mean that (most likely), you'll write one report program, then start the second, which will reveal loci for refactoring, which will then result in a (at least) partially generic report program, and finally the third report program will be there to allow further refinement of the metadata-driven report generator? -- PeteHardie
When I see people use Yagni and Dtsttcpw on this site, I get the impression they really mean it. So, if someone said "code this report" they would have some routines that hard code all the logic for that particular report. That is the simplist thing that could work and it doesn't look forward at all into future needs. If someone says "oh, we need this other report", well, isn't the most simple thing just to repeat the idea behind the first report and hard code the second? etc. etc. At some point you must realize
hey, we ARE going to need it and design a more generic solution. There are a lot of verbal gymnastics on this page to basically blur the moment when someone realizes "yes, we will now need it" and we need to make it more generic. Let's face it, unless you are working on a very limited app, you KNOW you are going to need a robust reporting engine. Might as well implement it the right way from the start. And that doesn't mean BigDesignUpFront. You can still do it in iterations. I think Pete and I are agreeing here in some respects although we are saying it from two different starting points.
You are forgetting refactoring here -- PeteHardie
Practically, refactoring means making code clearer and cleaner and simpler and elegant. Or, in other words, clean up after yourself when you code. Examples would run the range from renaming a variable to introducting a method into a third-party class that you don't have source for.
Refactoring is not rewriting, although many people think they are the same.
It sounds like XP needs to answer the question, "If we aren't going to need it right now, how will we know WhenAreWeGonnaNeedIt
See also EconomicsOfYagni
I don't understand this question. If we don't need it right now, who cares WhenAreWeGonnaNeedIt
? We have other things that we DO need right now, and those must be given priority. We'll know that we need it when we have finished these other things and have gone on to a different feature that REQUIRES it, and written a UnitTest
or two, and they fail. Why would you want to go off and write wonderfully generic code that you KNOW you don't need right now, and DON'T have any unit tests for, instead of focusing on what your tests have proven that you do need? -- AnonymousDonor
If you are tasked with code to produce 3 reports, doesn't that mean that (most likely), you'll write one report program, then start the second, which will reveal loci for refactoring, which will then result in a (at least) partially generic report program, and finally the third report program will be there to allow further refinement of the metadata-driven report generator?
This is pretty much what we did in WyCash
. When we need to add a column total we wrote the column total as a simple sum. When we needed a running sum, as in the balance of a checkbook, we wrote that too and factored out the common stuff. Then we added three or four more variations before we stopped ever getting requests for more. Along the way we discovered that the type of calculation was just an attribute of the column and never needed to be adjusted by the user. The result is that users get right calculation without asking, we get to focus on handling missing values correctly, and nobody has to write or learn some formula hack that would pawn the coding problem off on the end user. -- WardCunningham
(That is not to say I haven't made good money consulting to people who have done the formula hack and now find that they have severe performace problems to boot. And they never even got to thinking about missing values.)
Ward, what do you mean when you say "investment in slack" in the above document?
You probably notice that the words aren't exactly those we use today, but the ideas are. One notion that I talked about a lot back then was slack
. With some slack you can code off in an unanticipated direction and come out all right. You will use up slack as you do so you can't do this indefinitly. Programming gets hard when you run out of slack. Lots of people think that they just got to the hard part of the problem. I bet they didn't. They just don't understand slack and they especially don't understand that you can always get more by refactoring. It's good to know how much slack you are going to need and how much is available. XP doesn't require this though. Instead XP asks that you take very small steps to avoid running out of slack and then refactor immediately to gain as much slack back as possible.
So what is the problem with YAGNI? A comment on this page stated that it was easier to implement the three needed reports directly. What is your rationale for wanting to spend additional time and effort on the report function, beyond "I would rather design a metadata-driven reporting engine?" This is the heart of YAGNI, don't waste your time on unnecessary things. -- WayneMack
In every job I've had where the application needed to produce reports, my experience has been that it is better to have a generic reporting engine because reports are added and altered often. Perhaps there are some business apps where that is not going to be the case, but I've never worked on one. So, my point is in some cases I know that I'm gonna need it, even if my customer is not telling me yet. It is easier and less resource intensive to do the work up front. Hard coding reports is not the same as doing it in a more generic way. It takes rewriting (not refactoring, see WhatIsRefactoring) to get from the hard coded solution to the generic solution. You end up spending more resources getting where you knew you need to be in the first place. I simply am not going to toss out years of experience that have served me well about various domains and blindly follow a rule that says to delay doing anything that is not specified by the customer (Perhaps some people get around this in real life by convincing customers they are gonna need it?). The reporting engine was just an example, there are others I could give, and some I mention elsewhere on the page, such as internationalization and localization.
If it is easier to use an existing report engine instead of designing one from scratch, that is certainly within the definition of YAGNI. Selecting a more difficult approach in the hopes that there will be some future need for it is not. I've seen cases were reporting engines were worthwhile and seen cases sere reporting engines were thrown at a job where a simple set of counts were needed (and the reporting engine became an ongoing support issue). DoTheSimplestThingThatCouldPossiblyWork
to solve the problems of today and worry about the problems of tomorrow, tomorrow. That is what YAGNI is all about. -- WayneMack
''This issue is also very developer-centric. I have implemented generalized report writers before
so I'd probably say it's easier to do that than the create specific reports. For another developer who hasn't
done it before they may say it's too difficult. Difficulty is not objectively representible by
a number on some scale, it has to be calculated in context.'' -- AnonymousDonor
If someone said, we don't need to support multiple languages in this app, would you build an entire million line shrink wrap app release for the U.S. in a way where all the strings are hard-coded and there is no accounting for localization? Yagni says you should. I disagree. I'm going to go to the trouble right up front to externalize strings and make localization possible because I've been there enough times to know that in some cases you are going to need it.
Following YAGNI means that you assume you're dealing with only English. Following OnceAndOnlyOnce
means you only make this assumption in one place. I suspect that a system that is like this will look very similar to one developed with i18n in mind, but the motivation is different. (See ThreeStagesInJeetKuneDo
That's false. You can't constructively eliminate every assumption because you cannot constructively enumerate every assumption. This would be equivalent to predicting all the requirements ahead of time, thus reducing the two horns to one, against your favour--i.e. you've equated YouArentGonnaNeedIt to BigDesignUpFront.
The erroneous premise is confusing the architectural decisions with the design decisions. You defer design decisions as late as possible, but architectural decisions are extremely expensive to alter because they require massive changes to the design. Architectural decisions include: choice of language, choice of platform, whether or not to be distributed, whether or not to be multithreaded, whether or not to be globalized.
On YagniExceptions, we discuss this same failure to understand where and where not refactoring can save you. In that case, a database schema, you have lost control over the decision. You can no longer fix it. You must violate YAGNI and implement some system to manage migration such as versioned data representations. Similarly, for the internationalized string table, either you decide to do it when you start, or you don't. Making the mistake of deferring that decision to version 3.0 when you enter foreign markets will be needlessly expensive.
It may be more expensive. But when you are writing version 3.0 to enter foreign markets you may also have more resources to invest in the new venture. Right now, just starting out, you may not have the resources. Are we minimizing total investment, or maximizing total return?
The failure on the other side is not understanding the principles of economic value. Betting that your product will make it to 3.0 and then expending the resources
now may be more expensive in the long run. The capital expenditure to initially do the work, plus the cost of maintenance over the life, amortized with interest, is
usually greater than the cost of fixing the system at 3.0. This is a business problem and it comes down to educated gambling. -- SunirShah
P.S. Globalization violates OnceAndOnlyOnce. It's not a fair measure for XP. Or then again, maybe it is.
Following YAGNI means that you assume you're dealing with only English. Following OnceAndOnlyOnce
means you only make this assumption in one place.
You've embedded the strings. There's no reason what so ever to do something more complicated. The out for every YAGNI problem is to point out some other principle that would change the YAGNI code to be something different. You should drop YAGNI because it seems to never really apply when confronted with real life scenarios.
Perhaps another way of saying this is to ask how you know that you are even making the assumption that you're dealing only with English. You are probably assuming you are only dealing with the Gregorian calander. And you are probably assuming 24 hours per day, which won't work on Mars. And you might be assuming that an employee is a person, not a robot. When do these assumptions become something that you need to state explicitely and ensure that they are encapsulated in one place, and when can you just ASSUME them and get on with life? In general, you will make an uncountable number of assumptions, and you can't hide them all. Part of the problem with relying on OnceAndOnlyOnce
to solve YAGNI is that OnceAndOnlyOnce
is magical, too.
About six months ago, I internationalized a Web application that was built using XP. We had followed YAGNI, so it was absolutely not designed with internationalization in mind, but it was well-factored and had good tests. Supporting localized output took a pair about three days, and localized input required about five. Most of that time was spent in research. Internationalizing input required only four lines of code! (One three-line method, and a change to an existing line of code to call that method.) That code has had no reported bugs. From this experience, and others, I strongly contend that YAGNI, along with XP-style design, tests, and refactoring, really does work.
Yagni thinking may cost $250 million. Developers said we won't have X connections and Y nodes for years, let's just do what we need now. Customer creates a system with more than X and Y and breaks the system which makes them very nervous and may delay or lose a very
large contract. Somehow they are not impressed with all the Yagni arguments detailed here.
Developers said we won't have ...
YAGNI is part of XP. There are other parts of XP that are being ignored here. XPers do not advocate YAGNI on its own, they advocate YAGNI along with all the other XP practices that reinforce each other. In XP, the developers would not be making such business decisions as above. The customer would decide how scalable they want the system to be. The developers would build that scalable system as simply as they could, but the system would still be scalable.
And let's say, for arguments sake, that the customer made a bad decision on the scalability issue. Another part of XP that is being ignored is refactoring. If the developers built the system with the YAGNI principle supported by refactoring, it would be far less expensive and far more straightforward to modify the system to accommodate increased scalability needs.
If all you want is to get someone here to admit that YAGNI can be harmful in some situations, then sure, we admit it. But there are other practices that do in fact reinforce YAGNI, which you may like to read about, such as ReFactoring
, and OnsiteCustomer
. To get a further understanding of how they reinforce each other, try ExtremeProgrammingRoadmap
The developers would build that scalable system as simply as they could, but the system would still be scalable.
Not possible. The difference between 1, 10, 100, 100000 is fundamental. There
is no architecture that handles any scale. The scale determines the
design choices made and the designs for different scales will be fundamentally different.
You may mean the system is the same because at the top most level all
all designs have a JustDoit?
method, but the innards will be completely different.
This is where I agree with XP. Any refactoring is possible if the system is well factored. Well factored code requires the minimum of alteration for any particular change. This isn't entirely possible since there must be some coupling in the code somewhere (unless you are programming in Linda). 'Once and only...' tries to avoid duplication. 'Refactor mercilessly...' asks for minimum grain size, reducing coupling. In that situation it is much easier to remap the function across different structures because the code may be cut up in any way you like.
The only problem is that cohesion may be difficult to see. A fully refactored class will probably sprout lots of little classes just so you can tell what it is doing (deep structuring), or it will get a lot of private methods (wide structuring). Or both.
In the minimum grain, minimum duplication context YAGNI may be applied. It is the pay-off for all that hard work. If you can't apply YAGNI, then you aren't factoring properly, or you've stumbled on one of the really hard problems of this universe.
Refactoring != architecture. You can refactor all you want a car isn't a dump truck. Scale is a
fundamental design attribute, not something that can be refactored into existence. Not unless
refactoring to you means changing everything, which seems odd.
There's alos a bit of if the world is perfect then we can do X in your statement.
A lot of code is not well factored. This is a reality. Thus many of your conclusions do not
Interesting, but the engine, suspension, wheels, steering wheel, windhshield designed originally seperatelly for a dump truck and a car? I'd suggest that the 'motorized carriage' is
very well factored.
I have still not been swayed to believe that Yagni makes a whole lot of sense sometimes. Sure you shouldn't gold plate, but some things need to be thought out up front. Notice I didn't say "designed"; I said thought out. In fact, I just came off of a project where we were doing XP, following Yagni and so forth. Problem is these darn humans were involved, right? So our onsite customer didn't know exactly what was needed, so new requirements were discovered almost weekly. At the beginning the requirements were for desktop app/single user. That became client server with serious concurrency. Because we had followed Yagni, a huge rewrite ensued. It was a rewrite, not a refactor. Another page asks CanAnArchitectureEmerge
? Sure it can, if you call rewriting a system a couple times nearly from scratch "emerging".
One of my favorite things about YouArentGonnaNeedIt
is that I am too dumb to do everything in one shebang. I generally don't know what we'll need in the future and when I find out through refactoring I often think, "Man, I would never have guessed this was how it would turn out." I learn so much about how things should work through ReFactoring
, doing more work up front seems silly. I just don't know enough. -- BrianRobinson
You don't have to know everything. Depending on your experience you can know a lot of things
which can be a good investment. What you get wrong can just be refactored like you
would do anything else.
see also EconomicsOfYagni WhenAreWeGonnaNeedIt OppositeOfYagni
CategoryExtremeProgramming CategoryExtremeProgrammingDiscussion CategoryDecisionMaking