YAGNI strikes out again. Perhaps I have a psychic ability to predict things that will be needed at the end of a cycle. I doubt it. Psychotic, perhaps...

Today, within the last two weeks prior to shipping our latest product, I got a new requirement. The change was actually simple, considering how late in the cycle it is (normally, stuff coming at this point is complex - that's not a psychic prediction, that's historical). It involved outputting a space somewhere if the value that should be there was blank. If this were shell, that would be completely trivial: ${SomeVar:- } But this isn't shell. It's perl interpreting some data.

Thankfully, I didn't know about YAGNI 15 months ago when I wrote the code that handled variable interpolation (posted here). I thought it would be fun, though hopefully useless, to have a syntax that was like shell. If I did "(SomeVar:- )", it would do the same as shell. I also added "(SomeVar:+blah)" and even "(SomeVar:/regexp/replace)" which was kinda like shell, but with a perl twist. (Shell can do glob-replacement with # and %, but you can't use regexp's with that.) I freely admit it: I was wrong. It was needed. Just not then.

About 3 or 4 months ago, about the time when we were supposed to be finishing the code (so we could test relatively stable code), we started using the regexp version. Today, I used the :- version. At neither point did we have the time available to do this - the schedules were/are too tight with late requirements. Alternative solutions would not have been so clean, easy, and fast (both on developer time and computing time, although only the former really counts for us). They would have involved code changes since we didn't need this ability yet, and those would have been way more error-prone.

Based on a consistant history (I've been in the same team for about 9 years), I can predict with annoyingly high certainty that we will continue to need highly flexible code that can do things at the end of a cycle that we don't need earlier. What that will precisely be, I don't know. But by ignoring the principle of YAGNI, I know that I'm getting my job done in a timely and reliable manner at the times where it matters. The features requested go in, with a lower cost of change, higher reliability, better self-documentation, and all other good software engineering principles followed. Just not YAGNI.

Part of the claim that YAGNI makes is that you won't necessarily know what the best way is to approach the problem until you actually have the problem. In these cases, I think I actually did have the best way to solve the problem coded well in advance, but I can buy the argument that this could have been fluke. However, the fact that I had written code to handle some generalised substitutions means that I had specific areas of the code (well, one area) to change should I need something a bit different. Slightly different syntax to get what I wanted, with a minimal impact to other code, and actually fairly small impact to that code, too. But the architecture was written and tested long ago, meaning only minor changes, if any, would be required now.

Does this mean I think YAGNI is a bad idea? Not necessarily. I just think it needs to be taken with a bit of salt. A bit more than the rule against goto's - which also should be ignored when appropriate. Sometimes, the prepatory work that goes into a feature that YAGNI would apply to will actually provide the flexibility or architecture to do what you really need to do when the time comes, with a much smaller investment in time at a point in the cycle where you can't afford large investments.

To be clear, when I wrote the features that I just started using, back in February of last year, my goal was to make the variable interpolation more flexible, and I chose what I thought was a cool way to test it: emulate some of the shell capabilities. I just didn't see a need to remove the test code since it was useful while I also hoped it wouldn't be needed (thus useless?). Even the flexibility itself wasn't needed at the time.

Sometimes, it's just good to have a tool in your toolkit, even though it's not needed. A screwdriver isn't needed if you have a hammer. Especially if you don't do any construction-type of work. But having them is probably still a good idea, just in case.

Replies are listed 'Best First'.
Re: Well, maybe you ARE gonna need it?
by dragonchild (Archbishop) on May 09, 2006 at 00:06 UTC
    YAGNI isn't about writing the smallest amount of code to implement the most minimally-designed solution that will work for the most minimal set of requirements you can get away with. It's about writing your code in such a way that you only implement what you need, but you design for what you think you might need. Maybe this means you have a bunch of stub parent classes. Maybe this means you pass in sub{1} instead of a complex callback. Maybe this means you choose the shell variable syntax because it's very flexible. But, you don't implement . . . yet. You give yourself room to implement.

    Why do you want to do that? Because you don't know what the late requirement will be. If you start implementing now, you have already started to carve the statue. You might remove marble that needs to be there later on. It's really really hard to glue marble back and it never looks right. Much better to give yourself lots of marble to work with and carve only when necessary.


    My criteria for good software:
    1. Does it work?
    2. Can someone else come in, make a change, and be reasonably certain no bugs were introduced?
Re: Well, maybe you ARE gonna need it?
by chromatic (Archbishop) on May 08, 2006 at 22:22 UTC

    You decided to expand the scope of your project several months ago and now your stakeholder thinks a little bit more that he or she can expand the scope of the project at no cost?

    I'm not sure this is an occasion for pride. The lesson I've always learned from doing things like this is instead "Hiding the cost of development makes everyone's job more difficult."

Re: Well, maybe you ARE gonna need it?
by spiritway (Vicar) on May 09, 2006 at 11:18 UTC

    I see YAGNI as a sort of defense against creeping featurism, where programmers add all sorts of bells, whistles, and symphony orchestras because they're almost "free". Just a few more lines of code, and you can have it sing "Yankee Doodle" in Urdu. Or whatever. The temptation is to make it just a little better, just one more little drinky-winky, until the whole thing gets to be so encrusted with features it collapses under its own weight.

    What you're doing, though, seems more like defensive programming, taking into account your previous experience. For some things, chances are you *ARE* gonna need it, and so you might as well put it in where it takes the least amount of reworking.

    I think a lesson here is that rules have their uses, but blindly following them may not be a good idea. I think it would be a good idea to follow YAGNI in the sense that you try not to make the program do absolutely everything; but you also include a few items that are likely to become needed in the future. It's a matter of experience and personal taste, I'd guess, but it seems to work for you.

Re: Well, maybe you ARE gonna need it?
by TedPride (Priest) on May 09, 2006 at 01:18 UTC
    Preparation is a gamble - you're gambling that the small amount of extra (possibly unpaid) time you're putting in now will save you a large amount of (paid) time later. The odds are always heavily in your favor, since 99% of clients won't figure out all of what they want until the last second. Plus, having to rewrite your entire application every week will drive you insane rather quickly, and even if you aren't getting paid for anything except your hours, it's best to prepare purely for the sake of your mental health.
      If you have to rewrite your application every week, you're probably doing too much preparation, rather than not enough. Rewriting usually means you made assumptions that turned out to be untrue. If you write clean code that is easy to add to, but don't try to guess what might need to be added now, that's YAGNI. In this specific case, writing code where a text formatter can be added is YAGNI, while guessing what kind of formatter might be needed and adding it ahead of time is not.
Re: Well, maybe you ARE gonna need it?
by QM (Parson) on May 09, 2006 at 04:24 UTC
    I'll echo dragonchild here.

    "What if" about features that could come in late, and think of several ways to implement them. Maybe tinker with a few ideas, try them on toy problems, etc. Also put your happy hat on and think of things they'll never ask for, and how you might implement those too. (Trust me, some of those "nevers" will surprise you.)

    There's no need to implement anything, as some choices will preclude others.

    Think of Ender's Game, where Ender tells Bean to come up with wacky ideas for Battle Room. Near the end, they never know what to expect, and Ender and Bean always turn the scenario to their advantage.

    -QM
    --
    Quantum Mechanics: The dreams stuff is made of

Re: Well, maybe you ARE gonna need it?
by TedPride (Priest) on May 09, 2006 at 06:41 UTC
    Ender and Bean were given totally new scenarios each time, though, and all their techniques were for attack, not defense. They won because they could adapt to the current circumstances faster and better than the enemy could. This is not the same thing at all as prepping your code so it can be modified easily later. Code preparation requires that you have some idea of what's coming, whereas Ender and Bean had no idea. That's what made Ender so special. He could beat scenarios that had no previous frame of reference.