TDD by Example Chapter 10 Interesting Times

Summary

This chapter has another example of removing duplication by first increasing duplication. The implementations of times look like this:

// In Franc
      Money times(int multiplier) {
        return Money.franc(amount * multiplier);
      }

      // In Dollar
      Money times(int multiplier) {
        return Money.dollar(amount * multiplier);
      }
              

They are close but not identical and Beck seems to have a rule that duplication can only be removed if it's identical. So the first step in removing duplication is the implementation identical.

He makes them identical by first inlining the implementation of the factory method.

      // In Franc
      Money times(int multiplier) {
        return new Franc(amount * multiplier, currency);
      }

      //In Dollar
      Money times(int multiplier) {
        return new Dollar(amount * multiplier, currency);
      }
    

He realizes that he doesn't have to use the Dollar and Franc classes if he is also sending the currency so both implementation change to:

      Money times(int multiplier) {
         return new Money(amount * multiplier, currency);
      }
    

This causes a failing test in the the equals method because the implementation checks that the classes are the same. He adds a toString method on Money to help debug the failing test. This becomes good motivation to re-implement equals to not check for class but check for currency. Once that is implemented, all the test are green and the implementation of times in Dollar and Franc are exactly the same. This means it can be moved in the super class Money. Now Dollar and Franc are empty and can be deleted.

Commentary

This is a chapter of tactics. It is a chapter of pragmatism over ideals. Beck uses the tactic of increasing duplication in order to remove it. This time by inlining a method. He writes code that is not tested in order to help him debug a failing test. He uses the test to tell him if something will work instead of trying to reason about it. He sees a solution and instead of plowing through he backtracks, makes it easy, and then does the easy thing.

He took pains to point that that you don't always have to write tests for everything. When he wrote the the toString method he took time to point out why he made that exception. The first reason he gives is: "We are about to see the results on the screen.". This signals to me that the most important thing about tests is the feedback they give. He doesn't say this out right and I may be wrong about his thinking. As I've mentioned before I wish Beck was more explicit about the reasons he prefers one thing over another.

At the end of the chapter he writes:

Multiplication in place, we are ready to eliminate the stupid subclasses.

Immediately I thought, "What makes the subclasses stupid?". There are implicit views about what "good code" is that Beck doesn't take the time to explain. It seems that he expects his readers to just know. It's happened a couple of times before and I expect it to continue.

This book had a very specific audience in mind. The audience for people who want to learn TDD today has outgrown that audience. It's still a useful book, but any person reading it now will have to read a couple of other books to get the most value out of it.