22 May 2017

TDD, Refactoring Tests

So we are all familiar with the cycle Red-Green-Refactor as a critical behavior when applying TDD in practice. Over the years that I've been practicing TDD I've developed a habit of delaying my refactors. So I often do something more like 5xRed-Green, then refactor. This of course depends upon what I'm building and how well I have envisioned my end-state. 

Previously I'd mentioned a two step technique for practicing TDD in which your goal is to not have a vision of the results, but in practice, I often do have some sense of what the resultant code might look like; at least from a public interface perspective. With that in mind, I often find my self tempted to refactor code immediately to make it conform with my expectations, and I resist this temptation. 

I'm more likely to write four or five test cycles (test + code) and then refactor what little I might have. I also try to keep those refactors small. I might tweak a name or dry out a bit of setup, but I don't go whole hog crazy time and change the API without careful consideration. I might let a situation with too many arguments fester for a few iterations.

I do this because experience has shown me that if I start doing the more serious refactors too soon I will often undo those refactors later; either directly or indirectly. Typically, when I find myself backtracking a refactor, especially a large refactor, its because I don't know what I'm doing. That is, I have not thought the situation through completely. Other times it is because I've misremembered some aspect of the system and realize that my change is going to cause a design problem. 

So, while I fully support refactoring during the test cycle, I recommend some prudence with respect to when you start the refactoring step and how far you go with it. In most cases you can always apply the big refactor steps later, but once they are done, you've potentially doubled the labor if you were wrong. So don't speculate to wildly about the refactors, keep them small and simple. 

* On a related note, check out Daedtech's great post on Refactoring as a Development Technique from earlier today.