When I read Mark Seemann’s blog post stating “TDD is not a design technique” I agreed. Now I don’t anymore. Let me tell you why.
During Christmas I was writing some code with TDD. (Yeah I know I should socialize with my friends and family, but they were just like most other people still asleep around 6 am.) The codebase basically tracks my finances. I can import my bank transactions and categorize them. I wrote the first version of this program some years ago until I found that paying for a working solution is a lot easier. Since then I use the program for experimenting with new techniques, tools and programming languages.
This time I was trying to find out how the new IntelliJ IDEA worked for me while using TDD. To get a real life example I decided to (re)write the import functionality for my finances application. The banks import format is basically a text-file containing fixed length records with my transaction information. The real difficult herein lies in the fact that a transaction is splitted in 2, 3 or 4 lines in the input file. This depends on the length of the description associated with it.
Two sample transactions in file:
0123456789EUR99999999992000 0 9876543210relationinfo 00000000005006D101216101216000099999000200333201000 99
0123456789EUR99999999993 BETALINGSKENM. 000000000000000 Description 1
0123456789EUR99999999992000 0 Relation2 00000000001011D101219101217000099999 99
0123456789EUR99999999993 Description 0
The old code used a single class with a 200 line method, which extracts every variable needed to construct a list of transactions. This worked and there was a test available to validate the results. But I couldn’t understand the code anymore. Using some mysterious/magical constructions I managed to get it done. A particularly good example of this so called magic was that I actually fast forwarded a few lines within the loop that was iterating over all the lines.
I decided to rewrite the code using TDD. Since I wrote the first version of the parser some years ago, I did not have a clue about the import format. However I did have a sample file and the file specification. Hence it was relatively easy to write some tests. I started to write tests which determined whether the variables were parsed correctly. So the first tested whether I could retrieve the account number correctly. Then I created the code to make the test pass. The next test checked retrieving the amount and so on. All the information could be found in the first line of a single transaction in the file.
Finally I came to the difficult part of the file. In the best case the description can be found in the second line of a single transaction. In the worst case it is splitted across line 2,3 and 4. To make it more difficult the description is at different positions in the line depending on the type of the line. There were three line types: Line 1 is always of type 1, line two is of type 2, and line 3 and 4 are type 3. Writing some tests per type made it a lot easier for me to eventually retrieve the complete description of the transaction. Along the way I created three classes resembling the line type and encapsulating the problems per line. The new code design was much better than the old code design was.
TDD-ing through the code made it possible for me to do everything step by step. With each step I understood more of the actual problem domain. Together with the ability to refactor the code quite easily without being afraid that the code correctness was going to be compromised, I was able to get a better design. This design resembled the problem domain much closer than my old code did. For me this is all related to TDD. So I’m sorry I have to disagree with Mark Seemann. TDD is a design technique, maybe not directly but it does enable you to create better designs.
P.S. This is my first blog post in English. This is because it was a reaction to an English blog. As I’m not a native English speaker it is possible that there are some grammar/spelling mistakes. Please leave a reaction with the correct spelling if you find a mistake.