Object Mentor Bowling Game

In order to demonstrate XP (ExtremeProgramming) practices, Bob Koss (RSK) and Bob Martin (RCM) will pair program a simple application while you watch like a fly on the wall. We will use test first design and a lot of refactoring to create our application. What follows is a faithful re-enactment of a programming episode that the two Bob's actually did.

Martin & Koss wrote the program to illustrate PairProgramming. I decided to repeat their work only this time as a programming spike. A spike is written for the experience. A spike doesn't produce production code and is therefore exempt from ExtremeProgramming's PairProgramming requirement. I spiked the bowling score calculator to see how it would code up as a series of transformations applied to all the data at once.

Wiki'ers who can't read the description without implementing it can post their solutions on BowlingGameSpikes.

SALEM, Ore. (AP) - A 28-year-old construction worker from Keizer, Ore., has been credited with bowling just the fifth perfect 900 series in the 106-year history of the sport's national governing body.

After Bob and Bob paired the bowling game, Koss showed me the write-up. I was a bit "thrown" (no pun intended) by the fact that there wasn't anything resembling a frame class in the code. So, I set to work using their test cases to see if I would end up in the same place. I didn't. But, I'm not sure whose solution I like better. In mine, I aimed towards small communicative objects, so I refactored the hell out of it, but it might be over-engineered Here's the story of the system..

Whenever you throw a ball, you give the score (ball) to the game. It takes that ball and add it to the current frame, creating a new frame as needed. To calculate the score, you sum all of the frames. Each frame knows how to calculate its score. If you are a spare frame, you need the first ball after you to calculate your score. If you are a strike frame, you need the first and second ball after you to calculate your score. Frames can ask the Game for those balls. If they don't exist yet, the game serves up an object which returns zero for those balls.

Here is the code for SpareFrame:

 public class SpareFrame extends Frame 
	public SpareFrame(int frameNumber, Game game, int firstBall)  
		super(frameNumber, game);

this.firstBall = firstBall; }

public int getScore() { return 10 + afterFrame().getFirstBall(); }

public int getFirstBall() { return firstBall; }

public int getSecondBall() { return 10 - firstBall; }

private int firstBall = 0; }

afterFrame is a method in Frame which allows you to get the first and second ball after this frame. It returns a frame. The odd contortion is that you get balls one at a time, so on the first ball of a frame, you may add a regular frame to the list of frames, only to yank it and replace it with a spare frame if the second ball makes a spare.

Doing this was kind of fun. I spend a good deal of time telling people that you don't have to use domain objects when you code, but sometimes they are the best way to communicate everything you want to communicate.

-- MichaelFeathers

The "selling point" for our solution is the algorithm for scoring a game is just so sweet and clear. That trumped the domain objects. -- YoungBob?

That's fascinating. Bowling, and the scoring thereof is a mystery to me, but the point is clear: one solution does not represent a well-known domain entity, another, that passes the same tests, does represent that entity. Are you talking about just functional tests here? Or unit tests as well? Are your unit tests strictly a super-set of the Bobs'? -- KeithBraithwaite

They are the same tests. I just uncommented them one at a time. I think the Bobs' version has one test case class covering two classes, one extracted from the other. I used that same test case class (against a class named Game) and ended up with several more classes. I should have applied RefactorIntoTest. -- MichaelFeathers


Bowling might be an interesting domain in which to compare paradigms and languages; however, some of us don't bowl well enough to know some of the more advanced rules where prior turns are factored into the current turn if one hits enough pins. Thus, perhaps the rules of bowling should be clarified somewhere that developers can relate to. I would also note that the rules are static so that it may be difficult to explore ChangePatterns to designs, which is usually where the "good fights" are. --top

It's not as complicated as it sounds, especially if you look at a scorecard.

http://www.bowling2u.com/trivia/game/scoring.asp has a short tutorial.

Some of the things that make doing it programmatically interesting are allowing for the extra balls at the end of a game, and the fact that you can't calculate the score of a strike or spare frame until the balls after it are thrown.

BowlingGameInManyProgrammingLanguages?, anyone?

View edit of December 26, 2011 or FindPage with title or text search