As regular readers might recall, I began to use test-driven development for my private projects a couple of months ago. At my new job, I finally get the chance to use it on larger codebases, and there is one particularly useful technique I learned so far: In the absence of a better name, I’ll call it the shipyard.
In TDD, before you write any code, you write a test case for it. The test doesn’t have to compile, you can go ahead and build your dream world of how classes, methods or functions should interact with each other in order to achieve your goal. In the second step, you create stub implementations to make the test compile. The nice thing about this is that you get to design an API that cleanly communicates its purpose. However, you still have to think upfront about where to put the code, and who should get access to it. If you’re, like me, trying to keep the scope of everything reasonably small, you’ll have to put some serious thought into this. So you’re stuck where it hurts most; writing your first test case.
This is where the shipyard comes into play: Instead of putting the code you are about to write in its final place, you deliberately keep all of it in the same file as your test case. That way you don’t have to think about whether it will become a utility or part of the code that needs it, and you don’t have to jump around in your codebase all the time during development. As soon as the code does everything you wanted it to, it can become part of the bigger picture, just like a completed ship leaves the shipyard to fulfil its purpose.
If you put the code into place upfront, not only do you have to put in some extra effort, you will also have to move it somewhere else if your initial choice was a poor one. Another benefit is that in the shipyard you can commit your progress into version control without exposing not yet finished code to the rest of the application.
However, I see one potential problem of this approach: You could write nicely tested code that does exactly what you want, but when you are about to integrate it, you notice that it isn’t really needed, or not in that form. That hasn’t happened to me so far though.