"scoring a game of bowling" is probably the most common application used when demoing TDD. It's so commonly known among the JUnit crowd that I chose one of Bob Martin's efforts as a demo for JUnit Factory.
The topic comes up about once a year on the TDD mailing list and it just came up again. By an odd coincidence, we just celebrated the completion of a new release of AgitarOne with a trip to Homestead Lanes, so I am all fired up about bowling despite my dismal performance (there was beer involved).
Last time around, there was a general muttering that the bowling example is so trivial that it's not worth doing an object-oriented solution. The procedural solution is cleaner and simpler. This time, someone suggested taking the application further so that, maybe, the additional complexity will merit an object-oriented solution.
I volunteered to provide the stories and, as I often do when I TDD any game, I decided to start with the official rules. I'll post them here as a first draft of my stories and refine them after discussion on the mailing list if necessary.
So here goes, from the World Tenpin Bowling Association Statutes and Playing Rules...
[skipping a bunch of rules about lane size and official languages]2.1.1 A game of tenpins consists of ten frames. A player delivers two balls in each of the first nine frames unless a strike is scored. In the tenth frame, a player delivers three balls if a strike or spare is scored. Every frame must be completed by each player bowling in regular order.
That seems straightforward. It introduces the idea of a spare and a strike but doesn't say what they are. Let's assume they are not important at this stage.
We'll need to define a way for the lane machinery to report the pin scores. Let's go with a simple method void bowl(int pins)
(or the equivalent in your language). I suspect that the real thing might use a stream of bytes or something suitably low-level. I'll put a call into the lane manufacturers and introduce a new story when I find out the answer.
Glancing forward, I see that rule 2.1.8 talks about individual pins and 2.2.1 talks about multiple lanes but, for now, let's assume a single lane that will send us the pin count.
2.1.2 Except when a strike is scored, the number of pins knocked down by the player’s first delivery is to be marked in the small square in the upper left-hand corner of that frame, and the number of pins knocked down by the player’s second delivery is to be marked in the upper right-hand corner. If none of the standing pins are knocked down by the second delivery in the frame, the score sheet shall be marked with a (-). The count for the two deliveries in the frame shall be recorded immediately.
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | |||||||||||
X | X | X | 7 | 2 | (8) | / | F | 9 | X | 7 | / | 9 | - | X | X | X | ||||
30 | 57 | 76 | 85 | 95 | 104 | 124 | 143 | 152 | 180 |
This rule introduces the idea of a UI. We'll leave the technology of the UI to the individual solution providers. Whether you use Swing, SWT, HTML, Windows.Forms, Ruby on Rails, Etoys, CURSES, printf or something else altogether is up to you - as long as you meet the requirements about showing pins and cumulative scores and such. If past is prologue, I'll expect a hugely diverse set of technologies. Perhaps we'll finally see a Humble Dialog versus TFUI bake-off?
2.1.3 A strike is made when a full setup of pins is knocked down with the first delivery in a frame. It is marked by an (X) in the small square in the upper left-hand corner of the frame where it was made. The count for one strike is 10 plus the number of pins knocked down on the player’s next two deliveries.
Now we have a definition for a strike, so those rules about the last frame containing three balls in 2.1.1 become actionable.
2.1.4 Two consecutive strikes is a double. The count for the first strike is 20 plus the number of pins knocked down with the first delivery following the second strike.
That rule doesn't seem to introduce a new requirement. Let's just call it an additional acceptance test for story 2.1.3.
2.1.5 Three successive strikes is a triple. The count for the first strike is 30. To bowl the maximum score of 300, the player must bowl 12 strikes in succession.
Another acceptance test for 2.1.3.
2.1.6 A spare is scored when pins left standing after the first delivery are knocked down with the second delivery in that frame. It is marked by a (/) in the small square in the upper righthand corner of the frame. The count for a spare is 10 plus the number of pins knocked down by the player’s next delivery.
Those six rules take care of the basic rules. I am going to get to work on my acceptance tests for those and, once we have a few implementations, I'll add some new stories about how the lane machinery works and about running a multi-lane tournament.
This exercise started out on the TDD list so if you want to just TDD your way through that's fine. It's also posted to the XP list and presumably, they'll want to estimate stories and write acceptance tests too. I know I will. Hey! Maybe the agile-testing people will join in and provide their unique perspective? It would be cool to see Brian Marick's fancy new graphical specification technology applied to bowling.
Posted by Kevin Lawrence at March 9, 2007 11:15 AM
TrackBack URL for this entry:
http://www.developertesting.com/mt/mt-tb.cgi/242