views:

448

answers:

15

I find myself breaking this pattern all the time.

YAGNI - You Ain't Gonna Need It

I am only a Junior Developer, but I find even Senior level developers doing the same thing.

"Well, this system might use it, and this one, so let's design for it."

Sometimes, I catch myself, but most times I run wild. Does anyone have any tips for sticking to YAGNI, or anything I can do to better enforce this design pattern while I am designing and coding?

A: 

It is good to design your applications in a way that will make future features easier to implement -- but don't actually implement the features until you need to. How to go about doing this is entirely dependent on the project you're working on.

Justin R.
A: 

I find peer reviews and peer programming help with this. Another set of eyes questioning your reasoning will quickly identify things you think you need, but don't really.

Ryan Michela
what's peer reviews and peer programming?
Beatles1692
My interpretation would be that peer reviews are where your other developers look over your code and give feedback on how it rocks, sucks, or could be improved. Peer programming is simply having 2 or more developers work together on some piece of functionality as there times where I've seen a pair of programmers add in one more to the mix.
JB King
A: 

If you are following Agile then you can work on the important stuff until you get to the stuff you aren't going to need. By the time you get to the YAGNI stuff you should have a pretty much finished product. It would then be up to the business to tell you to stop developing stuff.

Xetius
+18  A: 

Designing FOR something

...is completely different than

Designing something.

Designing for something means you're architecting your application for future expansion in case the need arises to write the code (which is good...it means you're making your software extendable and easy to maintain).

Designing something means you're writing the whole piece now...whether you think anybody is actually going to use it or not. That isn't necessarily a bad thing, but it can be a huge waste of time.

Be careful about which one you're doing.

Justin Niessner
Justin - had to upvote and push you past the 10k mark. :-)
Eric King
+1  A: 

YAGNI is really more of a question to ask. We, as senior developers, violate YAGNI all the time. It is really a question of "need". Do you need it? Define "need". I have seen awful balls of mud developed using the YAGNI dogma.

Not that I think YAGNI isn't useful... it is always worth asking "Do I need this".

Brian Genisio
+8  A: 

This has something to do with perfectionism. let's make it perfect, let's make it ready for all possible future scenarios.

It helps to be pragmatic and sober when deciding on the chances it will be needed: make then answer either "Yes" or "No". Maybe is a no.

Unless there is a clear evidence it will be needed (it's on the agenda, it's been asked for by a customer) and you see it is better to account for that future functionality in your current design, leave it out for now.

Developer Art
It also depends on the cost. Sometimes it's very cheap to make allowance at an initial stage, and it would be expensive to add the feature later. For instance security, internationalisation, scalability.
MarkJ
Agree. It all very much situation-dependent.
Developer Art
Also sometimes it is cheap to add something but then takes an extraordinary amount of effort to remove it when it becomes clear it will never be needed.
Developer Art
A: 

YAGNI is often a hindsight thing. Just make sure you're agile enough to remove the "I" when "YAGNI" becomes obvious.

BenB
The I stands for it. Did you mean the A?
jcdyer
Nope, I meant "agile enough to remove the It when You Aint Gonna Need It becomes obvious". In other words, as soon as you realise YAGNI, don't be afraid to pull code.
BenB
Do you mean "remove it when you _didn't_ apparently need it", but stated in a very difficult phrasing?
xtofl
+5  A: 

Just use TDD !!!

rarely you wil find yourself writing a test for a feature that you don't need...

naaka
That's an interesting comment. Coding is kind of 'the fun part' and a lot of YAGNI is that programmers go have fun writing extra code. If test aren't as much fun...it counterbalances.
Alex Feinman
Interesting indeed, but hard to believe. When I find a personal rationale for writing YAGNI code and have a raitonale to write tests for my code, what stops me from writing tests for YAGNI code? And if features are capped because writing tests is boring, what protects the necessary features? But then, IMO TDD tries to solve the problems of writing code by writing more code.
peterchen
actually i found much more interesting and funny writing test code.that's because tdd is not just a mean to write tests, but a design tecnique.obviously it is hard to achieve, but there's no free lunch: if you wanna good code, you have to learn a lot.tdd is just one od the ebst way to learn.
naaka
That's exactly where I distrust TDD - I've always understood design as a tradeoff between competing requirements, whereas TDD seems to optimize for testability. (Rather, different requirements that go a long way together, then split up into very different directions).
peterchen
here i disagree.usually testability is at least orthogonal to other requirements such as performance or flexibility.if we really want to find a link,we can say that when the code is testable, it is usually also fast and easy to change.when the code is untestable, it is usually also slow and difficult to read and change.there is no trade off to do between readable code and unreadable code, between refactorable code and unrefactorable one.obviously if you want a lot of features and flexibility, the code gets more complicated.yet it must not become unreadable or even worst a mess !
naaka
+1  A: 

If you are building a library/toolkit/platform/framework, YAGNI takes on a different meaning.

You can't be sure how other developers are going to use your tool, and sometimes it makes a lot more sense to design with flexibility, so that your product can be used in a wider variety of scenarios. Forward compatibility is also a huge consideration.

YAGNI still applies, but the "it" tends to be at a meta-feature level, rather than a feature level.

system PAUSE
A: 

We have a rule of thumb in our company : When we are discussing designing a new feature the first question to be answered is "Who really want this?" if a customer is behind it then we try to understand what he really wants and if there are another ways to solve his problem (rather than adding a new feature).If a member of team is asking for this new feature he should have good reasons for that. Performance issues and marketing concerns are among them and again we try to fully understand the request and discuss all possible alternatives before we add some new features to our code base.

Beatles1692
+3  A: 

"Back to basics" and "Simple is good" are a couple of phrases that pop up to remind me to just stay on the task at hand and realize why am I building this feature or enhancement and not get into overengineering or planning for a million things that probably won't happen. Where I work my name is often used as a way to describe something overengineered or overly complex,e.g. "You JBed how to build that page." I am attempting to keep this in check more as sometimes it is useful but not often enough for it to become my common practice.

Having a requirement written out in non-technical terms can sometimes help too. This lets me know what I have to show at the end and not worry about the finer details, e.g. the users of the system aren't likely to read over my source code and mock my use of whatever naming convention we use. They care that it works and does what they need and want it to do.

Another question to ask is, "Did they really ask for this?" and try to minimize assumptions one makes about functionality. If it isn't in the list, then leave it out, though ask if they want it.

JB King
+4  A: 

It's so hard to enforce YAGNI because I think most of us have been bitten by the opposite problem, of finding a system that is too complex or brittle to refactor to do what we want, but which could have allowed for it with a little more forethought. Finding the middle ground can be tough.

Generally speaking, if you find yourself thinking, "it might need [xyz]", then that should explicitly play a part in what you code. Even if you don't code in support for xyz then you should be coding in such a way that refactoring to add xyz support is as practical as can be. Sometimes however that may mean making something more generic than it strictly needs to be. Knowing where to stop along that path is probably something that only domain specific information coupled with experience can tell you.

Kylotan
"... that refactoring to add xyz support is as practical as can be". I like that! Choose the path that disallows as few things possible.
xtofl
+5  A: 

Because YAGNI is a principle, not a panacea
Software Development is always about balancing many requirements. It's not about getting one thing right, rather getting none of many wrong. YAGNII alone won't save your ass.

In that sense, YAGNI is there to avoid the following pitfalls:

  • When you need a compiler, create a compiler - not a self-compiling compiler framework (Our strength - solving the general problem - is also our weakness)
  • Don't underestimate implementation effort.
  • Don't overestimate lifetime of your application and stability of requirements

Balancing competing requirements is hard. But that's why - as McConnell poignantly stated - software development is engineering.

Because other principles are people, too
Other principles principle - more fundamental IMO - is the principle of least surprise and the encapsulation of complexity: the public interface / contract of an entity should be simpler than it's implementation - otherwise, to call a function correctly I would have to know more than I needed to do it myself. sometimes, that means your implementation needs to be complete.

One example (maybe not a very good one):

/// Estimates the time required to comlete the batch.
/// If the time cannot be estimated reliably, the return value is -1
/// \returns [double] estimated time in seconds
double EstimateDuration(Batch & batch);

is a simple contract. OTOH,

/// Estimates the time required to comlete the batch.
/// If the time cannot be estimated reliably, the return value is -1.
/// This function does not support looping batches (right now, looping
/// batches only run under a servicve account with no UI, so it's not needed).
/// Also, when the moon is full, the return value is -1, but an estimate 
/// is found in batch.JeffsEstimate. This value is used only by Jeff's core 
/// build script which runs roughly once a month.
/// \returns [double] estimated time in seconds
double EstimateDuration(Batch & batch);

Is not a contract, it's a description of the imlementation. (One could argue if the problems are a result of overzealous YAGNI or simply bad design - but maybe that's because you YAGNI'd design altogether)

Design doesn't hurt
Will the advent of agile, the "design phase" got something of a bad name. However, to be worse than no planning at all, your plans must be catastrophic indeed. The biggest danger is not genuinely bad plans, but trying to anticipate every problem and change request. YAGNI is invaluable here.


They are senior, after all I don't know them - Their tendency may be due to old-school waterfall indoctrination and fear of change. Or maybe they are seniors because they know their job - they've learnt what parts you rather do now than later, and what parts can be sacrificed to the uncertanities of the future.

peterchen
+1  A: 

Remind yourself what you are trying to implement, and don't do more. You can do this with

  • clearly written user stories/requirements. If the "acceptance criteria" for your work is clearly outlined, it's easier to judge whether something is in or out.
  • someone (maybe yourself) who expects you to complete things rapidly. This forces you to make sure you're not going off track.
  • TDD
  • pair programming, or something close to it
  • daily stand-ups (or more frequent), to make sure you're not going off into the weeds
ndp
+1  A: 

Well, I ran into the same thing yesterday and had a big fight with one of the senior developers. I always try to design with "what if SOMEONE calls this, what if this changes tomm etc etc..?" and he is the other extreme. "Just make it work and FAST!"

The answer is somewhere in between his approach and mine. How do we come to the middle ground? Between trying to make a "perfect" design which people would appreciate or HATE if they have to change something in future.

IMHO, the answer, at least while designing a module, boils down to basic principles of Object Oriented Programming, things like defining clear interfaces. Interfaces should match with the requirement from customer. The main interfaces for module should not have anything which "solves" anything except whats there in the requirement. At-least some level of "frills" added due to "what if this changes, they need this tomorrow etc" can be removed.

Anything that you are planning to put because you think this MIGHT be used tomorrow by someone else etc has to be debated for hours! You should have good reasons for adding a "freebie" for SOMEONE who currently doesn't even have a name!

I still need a definitive answer for this question. Maybe from some architect here who has designed big applications and faced this situation 100 times :)

Tequila Guy