Code Kata
Any seasoned programmer who has tried doing Test-Driven Development (TDD) knows that it is a completely different paradigm of development from traditional methods. So for most of us, it takes a lot of practice to become proficient at TDD. This kata provides a simple exercise to practice the 3 basic laws of Test-Driven Development.
A bowling game is comprised of ten frames and gives each player two balls (two chances) during each frame to knock down as many of the ten pins as they can. Expand the section below to learn how to score a game of bowling.
In this example, as we begin the game in the first frame, a particular player (we’ll call him Bob) rolls his first ball and knocks down 1 pin. Then on his second ball, he knocks down 4 more pins, which give him a score of 5 for the first frame (1 pin for the first ball + 4 pins for the second ball). Then in the second frame, Bob knocks down 4 pins with his first ball, then 5 more pins with his second ball. We add 4 + 5, which gives him a score of 9 for the second frame. For a cumulative game score, we simply add the scores for all the frames bowled so far. In this case, the score for frame #1 was 5 and the score for frame #2 was 9, so 5 + 9 = 14. The score written at the bottom of each frame is a cumulative game score.
Continuing in the third frame, Bob knocks down 6 pins with his first ball, then he knocks down the remaining 4 pins with his second ball. When a player knocks down all 10 pins with two balls, this is called a spare and this example (above) shows how we draw a spare. A spare is scored as 10 plus the next ball rolled. In this case, Bob’s next ball (in the fourth frame) knocked down 5 pins, so his score for the third frame is 15. Therefore, his cumulative game score is 14 + 15, which equals 29.
Bob scored another spare in the fourth frame, but then in the fifth frame, he knocked down all ten pins on his first roll. This is called a strike. A strike is scored as 10 plus the next two balls. In this case, Bob did not knock down any pins with his first ball of the sixth frame and knocked down only 1 pin with his second ball. This gives him a score of 11 for the fifth frame with a cumulative game score of 60.
This continues until the tenth frame where Bob knocked down 2 pins on his first ball, then he rolled a spare with his second ball. Therefore, Bob gets to roll another ball in order to score the spare — which he ended up knocking down 6 pins, giving him a final game score of 133.
Following is a suggested high-level design for this application. However, as you apply the laws of TDD, don't get hung up on following this design. Let this serve as a starting point and provide some basic vocabulary for your application. It's okay if your code takes you down a separate path from this design. That often happens with TDD, which is exactly how good architectures evolve.
Start with a Game class, which has two methods: Roll and Score. The Roll method take the number of pins knocked down for a given game. The Score method is called at the end of the game and returns the score of the game. Next is the Frame class — and a Game has 10 frames. The Frame class has one function, Score, which returns the score for a given frame. However, in the case of a spare or strike, the Score function will need to look ahead to the next frame to score the current frame — we therefore have the reference for the frame object back onto itself, indicating that dependency. Next is the Roll class, and a Frame has 1 or 2 Rolls, except in the tenth frame, where it will have 2 or 3 rolls — as indicated by the sub-type Tenth Frame, which has one additional role (as indicated). The Roll class has a private attribute of pins which holds the number of pins knocked down on a given roll.
- Write no production code except to pass a failing test.
- Write only enough of a test to demonstrate a failure.
- Write only enough production code to pass the test.
This is a kata that is borrowed from Bob Martin, who often uses this example to teach the practice of Test-Driven Development.