At the recent meeting of Hamburg’s Softwerkskammer – the German Software Craftsmanship movement – we worked through a Coding Dojo on the Roman Numeral Kata. Michael Norton wrote today about one piece that worried me as well. I think Michael did a fantastic job on tackling a different approach. But he reminded me that I wanted to put up some of the thoughts from the Coding Dojo.
We had about 12 participants in the dojo. After explaining some pieces about the format and the kata, we started the dojo. As the kata started, we had one participant asking questions up to the degree that the pair in front of the keyboard stopped doing anything.
Eventually we got the team back up to continue working on the problem. The claim of the interrupter was that we didn’t yet understand the problem well enough to design the solution. Another claim was that TDD was not a design technique. Let’s take a closer look at both of these.
We have to understand the problem before using TDD
You could argue that the Roman Numerals kata is not very complex. Yet it seems that it’s possible to not grasp the domain of the future code model. Let’s take a look on the problem.
The romans counted differently than we do now. They had letters for different numbers. “I” is 1, “V” is 5, “X” is 10. You combine two “I”s to yield a 2: “II”. You combine two tens to yield a twenty: “XX”. You combine five and three to yield an eight: “VIII”. There are two exceptions to this concatenation. The four and the nine are generated by subtracting one from five, respectively ten: “IV” and “IX”.
We started the kata with a test for one, then for two, then we were heading for three. The question was whether we should go for a test for four or five at that point. I recalled Kent Beck’s exercise at his advanced TDD course in November 2010. He had us performing a kata. Then he asked us performing the same kata, but working the tests in a different than the usual order. The thing is that once you have a final design in mind, you work towards it. Now, the situation in the dojo was differently, as we didn’t discuss a design.
Now, we were stuck at implementing a large construct of guard clauses. When we introduced the test for the five, then the test for the four, we finally made some progress. We had three instances of guard clauses that returned some value. All looked similar. We tried to see a different design when we were facing the situation with two similar blocks. The design we worked towards at that point seemed to get in our way once we introduced the four.
The case when we had three distinct blocks was easier, and led to a better design. Now, the question is, if I do not have a particular design in mind, can I still explore possible designs?
I think so. The thing is, that I have to stop thinking while refactoring. I have to start thinking again when I stop refactoring to see whether the design I’m heading towards is any good at all. Using continuous integration, I can then revert back to the old design, and go a little bit further.
TDD is not a design technique
This insight is mostly triggered by the realization that Exploratory Testing is not a test technique, but a test approach. This means that you can combine Exploratory Testing with any testing technique. It’s orthogonal to testing techniques.
Similarly, TDD is not a design technique. It does not solve the problem of designing the source code for you. It helps you to think about the design though. You can combine TDD with any other design technique like UML, prototyping, and whatever you can think of. TDD is an approach to design. It helps you finding a design in your source code, rather than designing it. It’s you that designs the source code.
I’d be interested in your thoughts on it in the comments.