Recently I have been experimenting with a Code Kata, and in this post I’d like to share my experiences with it.
Code Kata’s have been around for a while, but it really came into my attention while reading Chapter 6 from the book The Clean Coder by Robert C Martin. This chapter makes an anology that at your work you’re a performer like a musician and outside work you (should be, like a musician) practicing. (Of course, you will learn while at work, but that is not the point).
But what is a Kata?
I have played the piano for around 6 years (followed lessons) and played it much less after that (in fact, I don’t really play at all anymore). In those six years I had to practice etudes as well as more famous pieces. I did not understand why I had to practice Etudes, until much later.
So what has an Etude to do with Kata’s? Lets look at the description of an Etude (at wikipedia):
“an instrumental musical composition, most commonly of considerable difficulty, usually designed to provide practice material for perfecting a particular technical skill”
Without going into detail of a Kata itself, it is used to practice and perfect a set of techniques. Repetition and practice until you’re able to perfectly perform a Kata (or an Etude if you will) will help you further when you need to improvise or apply it in different forms. A lot of Etudes, techniques, are used in real pieces. A lot of Code Kata’s are actually dealing with real world problems.
Its not all about the solution!
So if I practice enough code kata’s I will become good at any problem I might face when writing software?
Code Kata’s are flexible; meaning you must set yourself a goal you want to achieve by doing a kata. When doing an etude you don’t have a lot of options. Your main goal is getting better with your fingers to play a series of notes or transitions. With a Code Kata you could practice your typing. Or perhaps practice all short-cuts of your IDE. Or heck, learn a new IDE while doing one. Perhaps you want to learn a new language. Perhaps you want to get better at TDD. Or you simply want to get to the solution and find the most efficient way to do so.
Atleast, I found doing a code kata much more fun than doing an etude 🙂
Bowling Game Kata
The Bowling Game Kata is a Kata that challanges you to write a class (Game) that simulates a bowling ball game. You can roll balls and give the amount of pins knocked down. At the end you can call the score() method and you should get the correct score. It takes all rules into account, gutter, spares, strikes and the tenth frame where you can have 3 rolls instead of 2. The perfect game has 300 points. The worst game 0.
My initial thought: How hard can this be? I mean come on, I’ve dealt with harder things than a bowling game scoring system. Since I did not do any Code Kata before I set my goal to find the solution to this kata while doing TDD. I also did not want to look too much ahead in Uncle Bob’s (very nice) presentation (with solution). So I stopped when the game interface was given (roll() and score()) and I went ahead. Again, how hard could it be?
I have tried this Bowling Game Kata three times, and for each attempt I have written my experiences. All in all it was a very good experience and I recommend to try it out yourself. I believe if you want to get better, you need to practice. And only if you tried this multiple times, only then you know how it is.
So instead of talk the talk, let me walk the talk…
First attempt – Deception
Goal: Get it working, while doing TDD.
I set up a simple project and started with the GameTest. The first two tests where easy to do (0 pins, and all ones). But as soon as I got into Spares my first thought was to create a Frame class. Because a Frame represents a ‘turn’ where you can only roll 2 balls. The Frame class was born, along with its unit test. And I thought it felt good. I even added more ‘cheating’ detection. So you cannot roll 3 balls in one frame, or you cannot say you rolled 2 pins and then 9 (making 11 in one frame). I felt great and got unit tests working like nothing could stop me. Until the ‘perfect game’ test came around and my model just fell apart.
There was no way I could make it fit, without bending my entire model/solution.
So there I was, totally excited and thinking “just one more test and I’m done”.. and I got this.
Eventually I fixed it, I made my Frame class more flexible so I could set the maximum rolls and added flags. I then could create a TenthFrame class and set its flags so it would score differently. I also had created tests for the TenthFrame and even used an Abstract test class so I did not have duplicate code. Even so, I felt like this was wrong. I was bending my design just to work for one exception in the rules.
When I got all my unit tests passing, even the perfect score game, I just felt a great deception. My design sucked. Also, it took me almost 4 to 6 hours to get it working. Way too long for a code kata right?
– TDD cycles where not strict enough; so…
– TDD cycles where slow, I had to switch mouse/keyboard to rerun the unit test(s)
– I made design decisions too early and later got ‘stuck’ and had to bend the design to make it work completely
– Finding the solution the first time takes time
– I made much more stuff than I had to (over-engineering?)
– Time taken: roughly 6 hours.
– Amount of unit tests: 33
Second attempt – No need to bend the universe
Goal: Get it working, while doing TDD. Take lessons learned from first attempt. Aka: Tighter TDD cycles, get faster at TDD cycles, etc.
I started this kata late in the evening. I spent a fraction of the time compared to the first attempt: ~ 45 minutes(!). The later half hour mainly refactoring and keeping green bars. The actual solution was there within an hour. I did not have to bend my design, I could keep everything within the Game class!
Something little, but practical I learned about the IDE I used (Eclipse) is to short-key the ‘rerun last test’, so my TDD cycles where shorter.
I also noticed I understood the scoring of the bowling game much better. I don’t play this game very much, and when I do, the computer does all the scoring for me. So I guess the first attempt at the Kata took also longer because I had to understand the scoring rules.
Design wise I found that I still use “frames”, but not as a separate class. I do not have any cheating detection (so I can roll 12 pins and it won’t complain), but the scoring will utterly fail in that respect. Building these checks in would not be a problem though, because the spare/strike detection is now so easy.
– Faster TDD cycle by using shortcut for re-running tests
– TDD cycles where stricter, but could be even more tightened
– Commenting out tests when more than one breaks really helps you get focussed on getting one thing to work (so leave one test breaking), instead of fixing all tests at once.
– No cheating detection, no over-engineering
– Of the time consumed, I spent more time refactoring relatively to the first attempt, than thinking / finding the solution.
– I could refactor a lot of code, and make it much more cleaner. And safely due the tests.
– Time taken: roughly 45 minutes (!!)
– Amount of unit tests: 7
Third attempt – The only way to go fast is to go well
Goal: Tighten the TDD cycle. Get it done in 30 minutes or less.
This time I started fresh on a Sunday morning. Since I know the solution and I knew the design choices I made earlier (I know what works, and what does not work) things went very quick. I finished it within 30 minutes. I had the same amount of unit tests and the greatest thing was that the last test (perfect game) worked immediately. I did not had to change anything to make it work.
Once I had the last test working, I checked the code a bit and called it done. This time I also wanted to check my solution against the original presentation Uncle Bob made, to see if I missed anything or not. I figured that some of my tests where faulty:
– If you roll only ones, you can only roll 20 times and not 21 times. (i had a weird if statement to fix this up, but now it seemed that this was flawed).
– The perfect game was in my case 21 strikes, while you can only roll 12 times in that case. When I changed my test, it still worked.
It struck me that I was approaching this technically (21 rolls is maximum), and not from a functional point of view (ie 20 is max when only ones).
I also found that my TDD cycles where still to wide. I could do run the cycles close to each line of code, but I tend to write 2 or 3 lines before re-running my tests. Especially the first tests where suffering from this, later tests went better.
– TDD cycles can be shortened
– Functional point of view caught errors in my tests
– Shortest kata ever (under 30 minutes)
– Latest test worked, design was good. Design was even better after fixing the test for ‘only ones’, so I could remove weird if statements.
– Time taken: < 30 minutes
– Amount of unit tests: 5
So, after 3 attempts, do these Code Kata’s work for me? It surely learned me a few lessons. In short:
– The first time you do a Kata, it is slow. And you’re focussed on the solution. This could throw you off, but you have to persist…
– Later attempts are going much faster, and your focus shifts to other techniques. Mine was mainly speeding up my TDD cycle.
– I have learned a few things to speed up my TDD cycle, which I can apply in real world stuff as well. Which is good!
– Over-engineering will bite you, one way or another. Your design will be toast.
– I have learned that even in my last example I was approaching the solution too technical. As a Developer I still did not approach it entirely functionally. This meant that even though I thought I was done, I wasn’t. I do plan to use Acceptance tests (using JBehave) for this. That will be covered in a next blog.
– Above all, doing a Code Kata is fun!
I would advice to other developers to do Code Kata’s and get better at what they are doing. There are tons of areas where you can improve. In short, yes I do believe in them and I think you should give them a go, if you haven’t already!
Find more about Code Kata’s:
If you really want light-weight warm up exercises, you might want to go to: http://codingbat.com/