Bob Koss 与 Bob Martin展示结对编程。用TDD的开发模式做一个计算保龄球比赛得分程序。
首先,他们创建了一个测试验收用例。画了一个简单的UML图,便从写测试用例开始编程。
一开始的设计是这样的:
分为三个类:
- Game类
- Game类包含Frame类,1:10
- Frame类包含Throw类,1..3
然后,他们发现不需要Throw类,甚至也不需要Frame类。接着,不断的按功能增加单元测试,单元测试不通过则编写业务代码,通过后再重构,直到代码看上去没有坏味道为止。比如补中与全中的计分功能。整个开发过程是互相提出想法,用代码实践想法,提出修改意见,用代码实践修改意见。
最后代码:
Game:
1 public class Game 2 { 3 int currentFrame = 0; 4 bool isFirstThrow = true; 5 Scorer scorer = new Scorer(); 6 7 public int Score { get { return ScoreForFrame(currentFrame); } } 8 9 public void Add(int pins) 10 { 11 scorer.AddThrow(pins); 12 AdjustCurrentFrame(pins); 13 } 14 15 void AdjustCurrentFrame(int pins) 16 { 17 if (LastBallInFrame(pins)) AdvanceFrame(); 18 else isFirstThrow = false; 19 } 20 21 bool LastBallInFrame(int pins) 22 { 23 return Strike(pins) || !isFirstThrow; 24 } 25 26 bool Strike(int pins) 27 { 28 return isFirstThrow && pins == 10; 29 } 30 31 void AdvanceFrame() 32 { 33 currentFrame++; 34 if (currentFrame > 10) currentFrame = 10; 35 } 36 37 public int ScoreForFrame(int theFrame) 38 { 39 return scorer.ScoreForFrame(theFrame); 40 } 41 }
Scorer:
class Scorer { int ball; int[] throws = new int[21]; int currentThrow; int NextBallForSpare { get { return throws[ball + 2]; } } int NextTwoBallsForStrike { get { return throws[ball + 1] + throws[ball + 2]; } } int TwoBallsInFrame { get { return throws[ball] + throws[ball + 1]; } } bool Strike() { return throws[ball] == 10; } bool Spare() { return throws[ball] + throws[ball + 1] == 10; } public void AddThrow(int pins) { throws[currentThrow++] = pins; } public int ScoreForFrame(int theFrame) { ball = 0; int score = 0; for (int currentFrame = 0; currentFrame < theFrame; currentFrame++) { if (Strike()) { score += 10 + NextTwoBallsForStrike; ball++; } else if (Spare()) { score += 10 + NextBallForSpare; ball += 2; } else { score += TwoBallsInFrame; ball += 2; } } return score; } }
GameTest:
public class GameTest { Game game; [SetUp] public void SetUp() { game = new Game(); } [Test] public void TestTwoThrowNoMark() { game.Add(5); game.Add(4); Assert.AreEqual(9, game.Score); } [Test] public void TestFourThrowNoMark() { game.Add(5); game.Add(4); game.Add(7); game.Add(2); Assert.AreEqual(18, game.Score); Assert.AreEqual(9, game.ScoreForFrame(1)); Assert.AreEqual(18, game.ScoreForFrame(2)); } [Test] public void TestSimpleSpare() { game.Add(3); game.Add(7); game.Add(3); Assert.AreEqual(13, game.ScoreForFrame(1)); } [Test] public void TestSimpleFrameAfterSpare() { game.Add(3); game.Add(7); game.Add(3); game.Add(2); Assert.AreEqual(13, game.ScoreForFrame(1)); Assert.AreEqual(18, game.ScoreForFrame(2)); Assert.AreEqual(18, game.Score); } [Test] public void TestSimpleStrike() { game.Add(10); game.Add(3); game.Add(6); Assert.AreEqual(19, game.ScoreForFrame(1)); Assert.AreEqual(28, game.Score); } [Test] public void TestPerfectGame() { for (int i = 0; i < 12; i++) game.Add(10); Assert.AreEqual(300, game.Score); } [Test] public void TestEndOfArray() { for (int i = 0; i < 9; i++) { game.Add(0); game.Add(0); } game.Add(2); game.Add(8); game.Add(10); Assert.AreEqual(20, game.Score); } [Test] public void TestSampleGame() { game.Add(1); game.Add(4); game.Add(4); game.Add(5); game.Add(6); game.Add(4); game.Add(5); game.Add(5); game.Add(10); game.Add(0); game.Add(1); game.Add(7); game.Add(3); game.Add(6); game.Add(4); game.Add(10); game.Add(2); game.Add(8); game.Add(6); Assert.AreEqual(133, game.Score); } [Test] public void TestHeartBreak() { for (int i = 0; i < 11; i++) game.Add(10); game.Add(9); Assert.AreEqual(299, game.Score); } [Test] public void TestTenthFrameSpare() { for (int i = 0; i < 9; i++) game.Add(10); game.Add(9); game.Add(1); game.Add(1); Assert.AreEqual(270, game.Score); }
原文地址:https://www.cnblogs.com/xiaoguanqiu/p/10465948.html
时间: 2024-09-30 01:52:03