(something I posted on our internal agile alias, in response to a question about how design works in TDD…)
There’s an underlying assumption in software engineering that “more design == better design”, despite that fact that the vast majority of us have worked with baroque systems that answer a bunch of questions that nobody ever asked.
The traditional theory is that if you don’t do the up front design, your code will be poorly architected, inflexible, and you’ll be in trouble when you try to maintain it. Which is true. But it’s also true that up-front design – especially the “spend a milestone” type of up-front design – often leads to the same result.
The ideal architecture is a minimalist one. It provides all the features that are needed and no features that aren’t needed (I mean “features” in the class method sense, not the user-visible sense)
The up-front approach attempts to do that without the data around which features are needed and which ones aren’t needed, which always changes along the way.
TDD says, “We’re going to figure out what we need and how to put it together along the way. We know we’re not going to get it exactly right the first time, but with our tests we can refactor as necessary“