I had a discussion at lunch yesterday about the right way to do design.

Waaaaaay back when I was in school - when Van Halen's "Jump" was at the top of the charts - we were introduced to the Waterfall Model of software development. (aside - it Royce's model was iterative, but it was rarely discussed that way - the typical discussion broke the whole project down into phases).

Anyway, the waterfall model (and some other models as well) have distinct phases. In waterfall, you first collect requirements, then you design, then you implement, etc.

I've never found that to be very workable. As Field Marshal Helmuth von Moltke said, "No plan survives contact with the enemy" (actually, what he said was, "No operation plan extends with any certainty beyond the first encounter with the main body of the enemy" (though he likely said something like "Kein Betrieb Plan verlängert mit jeder möglicher Sicherheit über dem ersten Treffen mit dem Hauptkörper des Feindes hinaus" (or at least that's what he would have said if he spoke English and used Babelfish...)))

That doesn't mean that you should have a design, it just means that you should expect your design to change along the way as you learn more. But without spending time on design, you are likely to make some errors of architecture that will be difficult or costly to fix.

And just going off and starting coding would not have been tolerated by Tony Jongejan, my high school programming teacher.

At least that's what I used to think. These days, I'm not so sure, for most applications (see caveats later).

The problem is that, unless you've already built such a program (some of which is codified in the prototyping and "build one to throw away" schools of thought), you rarely have enough information to make informed choices, and you won't have that data until you actually write the code.

I think that you're far better off if you focus on building clean and well-architected (at the class level) code that has good unit tests, so that you'll have the ability to adapt as you learn more. It's all about the resiliency of the source to the change that is going to come, and letting the code evolve to do what it needs to do.

Caveats? Well, there are a few.

If you're in the library business, you will at some point have to put a stake in the ground and ship the thing, which will severely constrain further modifications. Your library may also be used in ways you didn't imagine.

I think the right way to solve that is with a little design up front, a lot of prototype use, and then a good review process before you ship it.

So what do you think? What amount of design is right before coding?