The greatest obstruction to grokking Test-Driven Development is the assertion that a developer makes to himself about how right his plans are for a solution.
The essence of TDD is a suspension of our belief that we know what we’re doing, and a submission to a structured process of exploration and elaboration of ideas.
No matter how certain I am that a conception of a design is right, I test the assumption against reality through TDD. I inevitably find that the higher level of my design ideas withstand TDD scrutiny, but the fine-grained atomic design assumptions don’t pass muster with any great regularity.
Because of this, I rarely even try to conceive of low level design ideas up front. I know that by fleshing them out though a process of specification with code that I end up with a good result in good time, and the result is frequently better than what I had assumed, and often in surprising ways that open me up to new avenues of learning and understanding in programming and design.
Most good developers refute TDD’s viability, and yet many excellent developers practice it diligently, and claim that they went from being good to excellent because of what they learned with TDD.
I think that the difference between a good developer and an excellent developer is the excellent developer’s willingness to not know, an openness to explore, and faith in skills that guide solutions to good ends even when the end is not known at the outset.