A while back, I wrote a post in which I talked about offering too much code and too many options to other potential users of your code. A discussion emerged in the comments roughly surrounding the merits of the design heuristic affectionately known as “YAGNI,” or “you ain’t gonna need it.”
In a vacuum, this aphorism seems to be the kind of advice you give a chronic hoarder: “come on, just throw out 12 of those combs — it’s not like you’re going to need them.” So what does it mean, exactly, in the context of programming, and is it good advice in general? After all, if you applied the advice that you’d give a hoarder to someone who wasn’t, you might be telling them to throw out their only comb, which wouldn’t make a lot of sense.
The Motivation for YAGNI
As best I understand, the YAGNI principle is one of the tenets of Extreme Programming (XP), an agile development approach that emerged in the 1990s and stood in stark contrast to the so-called “waterfall” or big-design-up-front approach to software projects. One of the core principles of the (generally unsuccessful) waterfall approach is a quixotic attempt to figure out just about every detail of the code to be written before writing it, and then, afterward, to actually write the code.
I personally believe this silliness is the result of misguided attempts to mimic the behavior of an Industrial Revolution-style assembly line in which the engineers (generally software architects) do all the thinking and planning so that the mindless drones putting the pieces together (developers) don’t have to hurt their brains thinking. Obviously, in an industry of knowledge workers, this is silly … but I digress.
YAGNI as a concept seems well suited to address the problematic tendency of waterfall development to generate massive amounts of useless code and other artifacts. Instead, with YAGNI (and other agile principles) you deliver features early, using the simplest possible implementation, and then you add more and refactor as you go.
YAGNI on a Smaller Scale
But YAGNI also has a smaller scale design component as well, which is evident in my earlier post. Some developers have a tendency to code up classes and add extra methods that they think might be useful to themselves or others at some later point in time. This is often referred to as “gold plating,” and I think the behavior is based largely on the fact that this is often a good idea in day-to-day life.
“As long as I’m changing the lightbulb in this ceiling lamp, I may as well dust and do a little cleaning while I’m up here.”
“as long as I’m cooking tonight, I might as well make extra so that I have leftovers and can save time tomorrow.”
But the devil is in the details with speculative value propositions. In the first example, clear value is being provided with the extra task (cleaning). In the second, the value is speculative, but the odds of realization are high and the marginal cost is low. If you’re going to the effort of making tuna casserole, scaling up the ingredients is negligible in terms of effort and provides a very likely time savings tomorrow.
But doesn’t that apply to code? I mean, adding that GetFoo() method will take only a second and it might be useful later.
Well, consider that the planning lifespan for code is different than casserole. With the casserole, you have a definite timeframe in mind — some time in the next few nights — whereas with code, you do not. The timeframe is “down the line.” In the meantime, that code sits in the fridge of your application, aging poorly as people forget its intended purpose.
You wind up with a code-fridge full of containers with goop in them that doesn’t exactly smell bad, but isn’t labeled with a date and you aren’t sure of its origin. And I don’t know about you, but if I were to encounter a situation like that, the reaction would be “I don’t feel like risking it, I’m ordering Chinese.” And, “nope, I’m out of here,” isn’t a good feeling to have when you open your application’s code.
Does YAGNI Always Apply?
So there is an overriding design principle YAGNI, and there is a more localized version — both of which seem to be reactions toward a tendency to comically over-plan and a tendency to gold plate locally, respectively. But does this advice always hold up, reactions notwithstanding?
I’m not so sure. I mean, let’s say that you’re starting on a new .NET web application and you need to test that it displays “hello world.” The simplest thing that could work is F5 and inspection. But now let’s say that you have to give it to a tester. The simplest thing is to take the compiled output and manually copy it to a server. That’s certainly simpler than setting up some kind of automated publish or continuous deployment scenario. And now you’re in sort of a loop, because at what point is this XCopy deploy ever not going to be the simplest thing that could work for deploying? What’s the tipping point?
Getting Away from Sloganeering
Now I’m sure that someone is primed to comment that it’s just a matter of how you define requirements and how stringent you are about quality. “Well, it’s the simplest thing that could possibly work but keeping the overall goals in mind of the project and assuming a baseline of quality and” — gotta cut you off there, because that’s not YAGNI. That’s WITSTTCPWBKTOGIMOTPAAABOQA, and that’s a mouthful.
It’s a mouthful because there’s suddenly nuance.
The software development world is full of metaphorical hoarders, to go back to the theme of the first paragraph. They’re serial planners and pleasers that want a fridge full of every imaginable code casserole they or their guests might ever need. YAGNI is a great mantra for these people and for snapping them out of it. When you go sit to pair or work with someone who asks you for advice on some method, it’s a good reality check to say, “dude, YAGNI, so stop writing it.”
But once that person gets YAGNI — really groks it by adopting a practice like TDD or by developing a knack for getting things working and refactoring to refinement — there are diminishing returns to this piece of advice. While it might still occasionally serve as a reminder/wake-up call, it starts to become a possibly counterproductive oversimplification. I’d say that this is a great, pithy phrase to tack up on the wall of your shop as a reminder, especially if there’s been an over-planning and gold-plating trend historically. But that if you do that, beware local maxima.
I really enjoyed reading your thoughts about this, Erik. I was a firm (bull-headed?) proponent of this, but after working a couple of years with someone who would appropriately challenge me, I have come to soften my stance. Your example of setting up an automated build/deploy setup for testers is an excellent point. Another driver for this is if you are working within a team that is really truly trying to be agile, and that goal starts to blind them to non-minimum-viable-product work. I can offer another example that happened to me. Late in the v1 development of a project,… Read more »
Hi Eric, With all due respect I don’t really see how your v1-v2 example problems were caused by a “YAGNI mentality”. Without knowing the details, your story seems like one of just not being given enough time to properly implement something or to resolve technical debt. Instead of “simplest”, you were forced to build the “worst thing that could possibly work”. We’ve all been in situations where we’ve had to ship less than optimal solutions (probably the status quo). This shouldn’t be confused with implementing unused functionality. I hope you don’t take these comments the wrong way. I just thought… Read more »
Hi, Bob, Thanks for your comments. I assure you that inside my own head, it was a much more persuasive example. 🙂 What I neglected to point out was that during the development of the original feature within v1, there were discussions about how to approach the feature–whether to flesh out a richer interface, or just do the bare minimum. I believe we could have done the richer interface within the sprint, but the YAGNI argument plus the less perceived schedule risk dictated the solution we ended up implementing. That also bit us during v2 development because when we not… Read more »
All things being equal, I’d probably rather be in the extreme-YAGNI ditch than the waterfall one. 🙂 I’m with you, though. It feels weird to post any nuance on this because I’ve always had kind of a reactionary favoritism for avoiding gold-plating since it seems to be so prevalent in the industry and it’s so maddening when people do it. I think my stance has been softened to the point of me saying, “I’m very skeptical, but I’m listening” when someone starts to explain why we need to prepare now with code or other work product for something that might… Read more »
I agree that YAGNI can cause oversimplification, what I call “Simplistic Design”: http://effectivesoftwaredesign.com/2013/08/05/simplicity-in-software-design-kiss-yagni-and-occams-razor/
Reading through that link, I realize that I didn’t really address one of the core components of the YAGNI philosophy, which is the idea that you want to defer deciding things until later when you have more knowledge. I don’t think it detracts from my point, but I wish I had mentioned it. Thanks for the link — that was a good read.
YAGNI connects to common sense using the open/closed principle, IME. YMMV.
I’m intrigued. So is YAGNI Open for Extension/Closed for Modification via common sense or or vice-versa?
Common sense nudges us toward adding things we ‘know’ are going to be needed; YAGNI tells us not to do that. Flexible designs, which are what the Open-Closed principle encourages us to use, allow us to implement the hooks for future additions without actually doing anything we don’t need right now. It worked for me…