There are two ways to test-drive your code.

Either you write your test, you write your code and you do a little bit of refactoring. You spend less time on the refactoring than you do writing the test and the code. Then you restart the red-green-refactor loop. When you're done with the whole feature your code is a bit messy, so you do some bigger refactorings, spending enough time for the code to be satisfactory.

Or you write your test, you write your code and you do quite a lot of refactoring. You actually do enough refactoring to make the code look satisfactory, which means you probably spend more time refactoring than you do writing the test and the code. Then you restart the red-green-refactor loop. When you're done with the whole feature you're done. No more refactorings are necessary!

One way is better than the other, for several reasons.


Let's say you write a test. Then you write enough code to make the test pass. Your look at the solution and it looks horrible. But you say to yourself: "I might as well leave that mess, because that has to change when I write test X32".

Sounds like a good plan, right? Let's not waste our time doing work up-front.

What you didn't think about was that up until the time you write test X32 you will have to cope with the mess. It will slow you down since it's probably harder to understand than a cleaned up version. This will be even more apparent once you get around to writing test X32, because you must understand the code in order to change it.

Code that is difficult to understand is also difficult to compare with other parts of the code base. Without the mess you might find ways to simplify the design in ways that are later obfuscated due to fact that more code has been added. You'll end up with something that is no longer the simplest possible design.

Also, what happens if you never get around to test X32? What will happen then with the mess?

What if you run out of time just as you were about to clean up the mess? Will you be able to justify for the man with the money that you should spend some time next iteration cleaning up last iteration's mess? He'd probably prefer some new fancy features.

Will you be able to motivate yourself to clean up the mess? When the next feature is awaiting you around the corner, are you really going to put on the gloves and bring out the broom?


The above are all small things compared to the real problem: By postponing the refactoring you get a false sense of progress. A finished red-green-refactor loop is one notch on the ladder towards a completed feature. How do you measure progress while refactoring? Will you even remember to include the big final refactoring in your estimations?


So the better way is to do your homework directly. Always keep the code in a close to perfect shape.