The test-driven development mantra is "red, green, refactor," but we far too often let other things creep into the process. One of these things is domain knowledge.
Back in February, Gojko Adzik described
his experience with
Keith Braithwaite's "
TDD as if you meant it" exercise. He was to TDD whether a stone in the game of Go could be taken, or not. In the game of Go, each piece is placed on a grid and can be taken if it is surrounded by only one liberty (i.e. free space) in any of the four cardinal directions.
His first test was to identify stones with two corners covered as having two liberties. Yet, despite that, and armed with additional domain knowledge, his test started out like this:
GoGrid grid=new GoGrid(3,3);
See it? Yeah, the first and only line. It's a domain leak. And it's not just Gojko -- I do it all the time, inadvertently of course. Rather than starting off with
the simplest thing that could possibly work, we have a tendency to inject domain knowledge into our code. Suddenly we find that we must create a few classes rather than a few short lines of code. We've made our job harder and started forcing a design that didn't exist nor evolve from the code. Our leaky domain knowledge introduces untested design,
BDUF, but on a smaller, slightly less turgid scale.
With TDD, the design is supposed to evolve, yet I often find myself saying, "this is easy to code, but...." And the but kills me, it's usually something describing a design or architecture problem that I don't know how I'm going to solve, so I sit there thinking, and thinking, and thinking.
"Stop! Don't architect, refactor," I must tell myself. That is, I need to implement what I know, worrying very little about the design. Writing the initial code isn't about having the best, most-pure design the first time. The refactoring step is about cleaning up the design. It's also been said this way, "
Make it work. Make it right. Make it fast."