Sunday, November 1, 2009

Too much OO as a result of TDD?

I was directed to this interesting article about Object-oriented (OO) creates complexity. The author is building a snakes and ladders game with someone who is new to Test-Driven Development (TDD). The author and his developer came up with 6 objects i.e. Game, Board, Player, Dice, Snake, Ladder. Another developer happened to pass by them and thought they were wasting time on creating those objects. After 15 minutes of discussion, they came up with the following approach (quoted directly from the article):
  • one class called Game (place holder, the class is not really required) with one method called move(int number_on_the_dice)
  • a list to hold the current position of each player on the board (there can be more than 2 players)
  • a hashmap with starting and ending points on the board (represents both the snakes and ladders, how does it matter whether its a snake or a ladder, they are just starting and ending points on the board)
  • a counter to calculate player’s turn
  • and … and what? …that’s it
I could not help wondering what went wrong. Then it strikes me that I may end up with the similar approach if I chose to use TDD. For example, I will use ladder and snake objects to keep track of the starting and ending point for ladder and snake, respectively. There will be more than one snake and ladder on a board. So, I will end up shoveling them into a container, too. What is interesting about the snake and ladder objects is they both have the same attributes i.e. starting and ending point. If I am using the TDD approach, this will be revealed to me right away and I need to question my approach.

TDD is not only about testing and design. TDD suppose to help us to uncover the unexpected so that we can make the necessary trade-off in our design. We should not just focus on creating objects or tests during TDD. We should pay attention to the signs in our code, which we call code smell. For example, if our ladder and snake objects have the same attributes (starting and ending point), we should pause and think a little bit. It seems like we have code duplication in different objects. It is no different than having similar code in two different methods. We should strive to eliminate code duplication. But, before we do that, we need to ask ourselves a few questions:
  1. Will the additional object help to communicate the domain concept better to the next developer?
  2. Will the additional object help to communicate the domain concept better to the business user?
  3. Is the domain concept complex enough to warrant a separate domain object?
  4. Is there a hidden domain concept that can represent both snake and ladder domain concepts?
After we understand the trade-offs, then we refactor our code. So, it is not TDD that introduces object complexity. It is us who often miss the forest for the trees.