Think about your last huge unrequited crush.
A real one, I’m talking. A crush so big you go to sleep thinking of your future together, and wake up, ummm, guilty. The kind of crush that great romantic stories are made from, and for. The wobbly-knee’d kind.
And a complete non-starter: when I say unrequited, I’m being clinical in an effort to minimize the likelihood of breaking out into laughter, as doctors and nurses in every ER around the world do.
Now, in that kind of crush, you have a vision, and that vision is glorious beyond compare. It captures entirely your ideal notions of successful love. I’m not going to ask you to describe it. In fact, please don’t describe it. I have sensitive comment readers here. But picture that imagined future, just for yourself.
Was it magnificent? Brilliant? A tale for the ages?
I’d bet it was all this and more.
In fact, there’s really only a single flaw in that entire vision.
That Future Romance Is In Your Head
That tremendous romantic vision is just that, a vision. And when it came time for that blueprint-for-love to hit the shredder we call real life, it just wasn’t up to the challenge.
Thus with your design.
You see, your design lives in your mind, like your romantic vision. Oh, it may have slightly more contact with reality, because, after all, I still can’t believe you thought that — never mind.
And, notice, I’m not suggesting you’re not the greatest software designer in known space. My point in no way depends on you being a sub-par designer. Surely, you’re not a sub-par designer of romantic visions for you, are you? Far from it.
Codeless Designs Are Relatively Worthless
A design in your head elides all messy details, tricky complications, and inevitable exceptions.
A problem your company wants to solve never does.
So how do you cope with this divergence?
You code up your design, and as the working code begins to implement the design in your head, you keep an eagle-like watch out for its inevitable infelicities, and you change the code — and your design — until it is still working and no longer has its problems.
That’s what TDD does. A sketch of a design leads to rolling some microtested working code which is re-designed in microsteps. Red. Green. Refactor. Commit.
Design-In-Head Vs. Design-In-Working-Code
When your starting design meets the emerging design that comes from repeatedly applying the TDD process, there will be clashes. Thankfully, most of them aren’t as bad as that great unrequited love. But, on the record, some of them are.
When it happens, which design is right?
The one in the working refactored microtested code is right.
Your Design Is Broken
That’s hard, but you have to let it go.
Use a mental design to work your way into the code using TDD, and your broken design will become a masterwork of productivity. Ignoring the code’s design in favor of the mind’s, and you will pay a great price, starting tomorrow and lasting until your company inevitably goes out of business.
People rail against TDD.
A great many of them are refusing to confront this basic clash of designs, and they just can’t let go of their mental construct in favor of their silicon one. (The most recent such, from the famous @DHH, reeks to me of this.)
And that explains for me a large amount of TDD criticism, and an even larger number of failed TDD adoption efforts.
If you think TDD is supposed to work w/o changing the shape of your designs, you have missed the point. It is not surprising to me that you find yourself hating TDD.
I see a lot of “TDD and my design clash, therefore TDD doesn’t work”. I’ve seen even more of it lately.