Monday, November 09, 2009

Why I don't like the Bowling Game kata

I am a big fan of Uncle Bob and I think he is a master of object-oriented programming and architecture. However, in my opinion his Bowling Game kata (solution for the bowling game scoring problem) it's not the right example to explain design via Test-Driven Development.
The kata consists in showing how to TDD a Game class which calculates the score for a bowling game basing on the pins rolled by the balls. It is a pure TDD exercise, accomplished by writing one test at the time, making it pass and refactor the Game class before adding a new one. This kata has circulated for long in the blogosphere.
Although it is indeed useful to see a perfect and practical example of testing-first for the naive programmer, I didn't enjoy reading the various slides.

For instance, these are the scoring rules for 10-pin bowling games, extracted from the Kata:
The game consists of 10 frames as shown above. In each frame the player has two opportunities to knock down 10 pins. The score for the frame is the total number of pins knocked down, plus bonuses for strikes and spares.A spare is when the player knocks down all 10 pins in two tries. The bonus for that frame is the number of pins knocked down by the next roll. So in frame 3 above, the score is 10 (the total number knocked down) plus a bonus of 5 (the number of pins knocked down on the next roll). A strike is when the player knocks down all 10 pins on his first try. The bonus for that frame is the value of the next two balls rolled [...].
These are fixed business rules. Once the last test in is place, there is nothing to add to the class since the bowling rules are considered standard. It is perfect now and forever. How many times did you write a class that never changed?
A design is considered good if it accomodates change to the business requirements, and I would have tried to implement different bowling scoring systems to see how the Game class can be modified to pass the new acceptance tests without breaking the existing ones. There is a total of five requirements expressed by the tests and while they are added the code is refined accordingly, but it is more an academic example than a real world situation.
When you propose TDD to fellow programmers it seems reasonable, but the first question that they ask you is How do I test my database application?, not in what order should I put my test helper methods? There are different priorities in learning TDD.

This kata is interesting in the sense that it implements a scientific method by changing one factor at the time in the TDD equation and analyzing the result. You find people that execute the same kata in different languages; with different frameworks; different programming paradigms; and so on.
When the majority of frameworks out there are still using static methods, executing katas sometimes crosses the border of overdesign/gold plating/endless polishing. I learned something from the kata, but it's not rocket science. Why not write a patch to some open source project that you use every day instead of investing time in doing the same thing again and again?

There are many math problems which are perfect for learning a new language: consider for instance writing a function which finds perfect numbers. If I were a computer science professor I would assign these problems to C beginners as they are very handy in having no external dependencies and in being easily solvable.
The limit in such learning methodolody is that only structured programming capabilities are exercised and there are many development patterns which are not necessary for solving math problems, and which will not be implemented by a beginner if not forced. Doing the simplest thing that could possibly work leads a beginner to create a function for calculating perfect numbers, not a class so well-tested in different scenarios. The same is true for calculating a bowling game score.
The kata is a very narrow case, recalled when you test a class with no dependencies, no lifecycle problems and with the smallest Api you will never encounter.
Before reading the kata I was excited because I was going to learn how Uncle Bob works. But the demonstration is in fact very basic. I would have preferred to see how he deals with interfaces design, legacy code refactoring, collaborators extraction when classes grow.


Anonymous said...

i have to wholeheartedly agree, the TDD folks out there push the idea so hard, but then only give candyland examples of how to get started. the whole TDD thing strikes me as another rather "religious" kind of debate, and instead of providing any kind of rigorous defense of their position, they effectively toss out the example equivalent of "trust us, because we say we're right"

uncle bob's example isn't even complete. there is absolutely no validation to check that rolls are in the range 0..10 inclusive, nor is there a check to ensure that there aren't extra frames bowled (e.g. a perfect game requires 12 strikes, and bob's api allows rolls to continue until the 22nd where you'd index outside the array)

now you could argue that as a programmer, validation should be so ingrained in your mind, that for example purposes it's ok to skip over them in a kata, but isn't it exactly to point of unit-testing to have tests to demonstrate the correctness of the code under test? also isn't that the exact point of doing katas..? to practice doing something small and easy to repeat exactly correctly so that when it comes time to write real production code, those practices come out as wrote, instead of having to think/plan/design them in?

either way, i agree, and echo your disappointment in the example.

Giorgio said...

I don't see the point of doing katas more than one time. :)

rkulla said...

You should watch the 2nd TDD episode on by Uncle Bob. He does the bowling game kata and the main enlightening point of it is that TDD often steers your design in a totally different direction.

Instead of designing things up front, with UML or something, and then trying to write classes that match it, you instead just start writing one small test at a time, getting your brain out of the way of over engineering and suddenly you write the entire algorithm in only 12 lines of code!

As for the commenter who said he doesn't like to do a kata more than once, well, that doesn't make sense. The point of kata is that you repeat the same thing many times until it's drilled into your head. From there you use it as a warm up or refresher of the basics so that you can get in the proper mindset to do other harder things.

Giorgio said...

notice this post is from more than an year and a half ago. In the meantime, I picked up katas as controlled experiments where you change one variable at a time (programming language, methodology, test harness...). So I'm definitely not abandoning katas after one run. :)