SlideShare une entreprise Scribd logo
1  sur  49
Bowling Game KataAdapted for C# and nUnit By Dan Stewart (with modifications by Mike Clement) dan@stewshack.com mike@softwareontheside.com
Scoring Bowling. The game consists of 10 frames as shown above.  In each frame the player has two opportunities to knock down 10 pins.  The score for the frame is the total number of pins knocked down, plus bonuses for strikes and spares. A spare is when the player knocks down all 10 pins in two tries.  The bonus for that frame is the number of pins knocked down by the next roll.  So in frame 3 above, the score is 10 (the total number knocked down) plus a bonus of 5 (the number of pins knocked down on the next roll.) A strike is when the player knocks down all 10 pins on his first try.  The bonus for that frame is the value of the next two balls rolled. In the tenth frame a player who rolls a spare or strike is allowed to roll the extra balls to complete the frame.  However no more than three balls can be rolled in tenth frame.
A quick design session Clearly we need the Game class.
A quick design session A game has 10 frames.
A quick design session A frame has 1 or two rolls.
A quick design session The tenth frame has two or three rolls. It is different from all the other frames.
A quick design session The score function must include all the frames,  and calculate all their scores.
A quick design session The score for a spare or a strike depends on the frame’s successor
Begin. Create a class library named BowlingGameKata
Begin. Add a test fixture named BowlingGameTests to the project usingNUnit.Framework; namespaceBowlingGameKata { [TestFixture] publicclassBowlingGameTests {         [Test] publicvoidGutterGameTest()         {         }     } }
The first test. [Test] publicvoidGutterGameTest()  {      Game g = new Game(); }
The first test. namespaceBowlingGameKata { publicclassGame     {     } } [Test] publicvoidGutterGameTest() {      Game g = new Game(); }
The first test. [Test] publicvoidGutterGameTest() {      Game g = new Game(); } publicclassGame { }
The first test. [Test] publicvoidGutterGameTest() {     Gameg = newGame(); for(int i = 0; i < 20; i++)  { g.Roll(0);  } } publicclassGame { }
The first test. public class Game {    publicvoid Roll(int p) {    thrownewSystem.NotImplementedException(); } } [Test] publicvoidGutterGameTest() {     Gameg = newGame(); for(int i = 0; i < 20; i++)  { g.Roll(0);  } }
The first test. [Test] publicvoidGutterGameTest() {    Gameg = newGame(); for(int i = 0; i < 20; i++) { g.Roll(0); } Assert.That(g.Score(), Is.EqualTo(0)); } public class Game {    publicvoid Roll(int p) {    thrownewSystem.NotImplementedException();    } }
The first test. [Test] publicvoidGutterGameTest() {    Gameg = newGame(); for(int i = 0; i < 20; i++) { g.Roll(0); } Assert.That(g.Score(), Is.EqualTo(0)); } publicclassGame {    publicvoid Roll(int p)    { thrownew System.NotImplementedException();    } publicobject Score() { thrownew System.NotImplementedException();    } } Failed GutterGameTestthrew exception
The first test. [Test] publicvoidGutterGameTest() {     Gameg = newGame(); for(int i = 0; i < 20; i++)  { g.Roll(0);    } Assert.That(g.Score(), Is.EqualTo(0)); } publicclassGame { privateint score; publicvoid Roll(int pins)  {  } publicintScore()  { returnscore;  } }
The Second test. [Test] publicvoidAllOnesTest() {     Gameg = newGame();     for(int i = 0; i < 20; i++)  { g.Roll(1);  } Assert.That(g.Score(), Is.EqualTo(20)); } publicclassGame { privateint score; publicvoid Roll(int pins)  {  } publicintScore()  { returnscore;  } }
The Second test. - Game creation is duplicated - roll loop is duplicated [Test] publicvoidAllOnesTest() {     Gameg = newGame();     for(int i = 0; i < 20; i++)  { g.Roll(1);  } Assert.That(g.Score(), Is.EqualTo(20)); } publicclassGame { privateint score; publicvoid Roll(int pins)  {  } publicintScore()  { returnscore;  } }
The Second test. - Game creation is duplicated - roll loop is duplicated [Test] publicvoidAllOnesTest() {     Gameg = newGame();     for(int i = 0; i < 20; i++)  { g.Roll(1);  } Assert.That(g.Score(), Is.EqualTo(20)); } publicclassGame { privateint score; publicvoid Roll(int pins) { } publicintScore() { return score;    } } Assert.AreEqual failed. Expected:<20>. Actual:<0>.
The Second test. - roll loop is duplicated privateGame g; [SetUp] publicvoidSetup()  {     g = newGame(); } [Test] publicvoidGutterGameTest() { for(int i = 0; i < 20; i++)  { g.Roll(0);  } Assert.That(g.Score(), Is.EqualTo(0)); } [Test] publicvoidAllOnesTest() { for(int i = 0; i < 20; i++)  { g.Roll(1);  } Assert.That(g.Score(), Is.EqualTo(20)); } publicclassGame { privateint score; publicvoid Roll(int pins) { score += pins; } publicint Score() { return score;     } }
The Second test. - roll loop is duplicated [Test] publicvoidGutterGameTest() { int rolls = 20; intpins = 0; for(int i = 0; i < rolls; i++) { g.Roll(pins); } Assert.That(g.Score(), Is.EqualTo(0)); } publicclassGame { privateint score; publicvoid Roll(int pins) { score += pins; } publicint Score() { return score;     } }
The Second test. - roll loop is duplicated [Test] publicvoidGutterGameTest() { int rolls = 20; intpins = 0; RollMany(rolls, pins); for(int i = 0; i < rolls; i++)   { g.Roll(pins);  } Assert.That(g.Score(), Is.EqualTo(0)); } publicclassGame { privateint score; publicvoid Roll(int pins) { score += pins; } publicint Score() { return score;     } }
The Second test. publicclassGame { privateint score; publicvoid Roll(int pins) { score += pins; } publicint Score() { return score;     } } [Test] publicvoidGutterGameTest() { RollMany(20, 0); Assert.That(g.Score(), Is.EqualTo(0)); } privatevoidRollMany(introlls, int pins) {     for(int i = 0; i < rolls; i++)  { g.Roll(pins);  } }
The Second test. [Test] publicvoidGutterGameTest() { RollMany(20, 0); Assert.That(g.Score(), Is.EqualTo(0)); } [Test] publicvoidAllOnesTest() { RollMany(20, 1); Assert.That(g.Score(), Is.EqualTo(20)); } privatevoidRollMany(int rolls, int pins) {     for(int i = 0; i < rolls; i++)  { g.Roll(pins);  } } publicclassGame { privateint score; publicvoid Roll(int pins) { score += pins; } publicint Score() { return score;     } }
The Third test. - ugly comment in test. [Test] publicvoidOneSpareTest() { g.Roll(5); g.Roll(5); // spare g.Roll(3); RollMany(17, 0); Assert.That(g.Score(), Is.EqualTo(16)); } publicclassGame { privateint score; publicvoid Roll(int pins) { score += pins; } publicint Score() { return score;     } } Failed Assert.AreEqual Expected:<16>. Actual:<13>
The Third test. - ugly comment in test. publicclassGame { privateint score; publicvoid Roll(int pins) { score += pins; } publicint Score() { return score;     } } [Test] publicvoidOneSpareTest() { g.Roll(5); g.Roll(5); // spare g.Roll(3); RollMany(17, 0); Assert.That(g.Score(), Is.EqualTo(16)); } tempted to use flag to remember previous roll.  So design must be wrong. Failed Assert.AreEqual Expected:<16>. Actual:<13>
The Third test. - ugly comment in test. Roll() calculates score, but name does not imply that. publicclassGame { privateint score; publicvoid Roll(int pins) { score += pins; } publicint Score() { return score;     } } [Test] publicvoidOneSpareTest() { g.Roll(5); g.Roll(5); // spare g.Roll(3); RollMany(17, 0); Assert.AreEqual(16, g.Score); } Score() does not calculate score, but name implies that it does. Design is wrong.  Responsibilities are misplaced. Failed Assert.AreEqual Expected:<16>. Actual:<13>
The Third test. - ugly comment in test. [Test] publicvoidOneSpareTest() { g.Roll(5); g.Roll(5); // spare g.Roll(3); RollMany(17, 0); //Assert.That(g.Score(), Is.EqualTo(16)); } publicclassGame { privateint score; publicvoid Roll(int pins) { score += pins; } publicint Score() { return score;     } }
The Third test. - ugly comment in test. publicclassGame { privateint score; privateint[] rolls = newint[21]; privateint currentRoll; publicvoid Roll(int pins) { rolls[currentRoll++] = pins; score += pins; } publicint Score() { return score;     } } [Test] publicvoidOneSpareTest() { g.Roll(5); g.Roll(5); // spare g.Roll(3); RollMany(17, 0); //Assert.That(g.Score(), Is.EqualTo(16)); }
The Third test. - ugly comment in test. publicclassGame {         privateint[] rolls = newint[21]; privateint currentRoll; publicvoid Roll(int pins) { rolls[currentRoll++] = pins; } publicint Score() { int score = 0; for (int i = 0; i < rolls.Length; i++) { score += rolls[i]; } return score;     } } [Test] publicvoidOneSpareTest() { g.Roll(5); g.Roll(5); // spare g.Roll(3); RollMany(17, 0); //Assert.That(g.Score(), Is.EqualTo(16)); }
The Third test. - ugly comment in test. [Test] publicvoidOneSpareTest() { g.Roll(5); g.Roll(5); // spare g.Roll(3); RollMany(17, 0); Assert.That(g.Score(), Is.EqualTo(16)); } publicclassGame {         privateint[] rolls = newint[21]; privateint currentRoll; publicvoid Roll(int pins) { rolls[currentRoll++] = pins; } publicint Score() { int score = 0; for (int i = 0; i < rolls.Length; i++) { score += rolls[i]; } return score;     } } Failed Assert.AreEqual Expected:<16>. Actual:<13>
The Third test. - ugly comment in test. publicint Score() { int score = 0; for (int i = 0; i < rolls.Length; i++)     {         // spare         if(rolls[i] + rolls[i+1] == 10) { score += ... } score += rolls[i]; } return score; } [Test] publicvoidOneSpareTest() { g.Roll(5); g.Roll(5); // spare g.Roll(3); RollMany(17, 0); Assert.That(g.Score(), Is.EqualTo(16)); } This isn’t going to work because i might not refer to the first ball of the frame. Design is still wrong. Need to walk through array two balls (one frame) at a time. Failed Assert.AreEqual Expected:<16>. Actual:<13>
The Third test. - ugly comment in test. publicclassGame {         privateint[] rolls = newint[21]; privateint currentRoll; publicvoid Roll(int pins) { rolls[currentRoll++] = pins; } publicint Score() { int score = 0; for (int i = 0; i < rolls.Length; i++) { score += rolls[i]; } return score;     } } [Test] publicvoidOneSpareTest() { g.Roll(5); g.Roll(5); // spare g.Roll(3); RollMany(17, 0); //Assert.That(g.Score(), Is.EqualTo(16)); Assert.Inconclusive(); }
The Third test. - ugly comment in test. publicint Score() { int score = 0; inti = 0; for (int frame = 0; frame < 10; frame++) {         score += rolls[i] + rolls[i + 1];         i+= 2; } returnscore; } [Test] publicvoidOneSpareTest() { g.Roll(5); g.Roll(5); // spare g.Roll(3); RollMany(17, 0); //Assert.That(g.Score(), Is.EqualTo(16)); Assert.Inconclusive(); }
The Third test. - ugly comment in test. [Test] publicvoidOneSpareTest() { g.Roll(5); g.Roll(5); // spare g.Roll(3); RollMany(17, 0); Assert.That(g.Score(), Is.EqualTo(16)); } publicint Score() { int score = 0; int i = 0; for (int frame = 0; frame < 10; frame++)     {         score += rolls[i] + rolls[i + 1];         i += 2;     } return score; } Failed Assert.AreEqual Expected:<16>. Actual:<13>
The Third test. - ugly comment in test. publicint Score() { int score = 0; inti = 0; for (int frame = 0; frame < 10; frame++) { // spare if (rolls[i] + rolls[i + 1] == 10) { score += 10 + rolls[i + 2]; i += 2; } else {             score += rolls[i] + rolls[i + 1];       i += 2;        }     } return score; } [Test] publicvoidOneSpareTest() { g.Roll(5); g.Roll(5); // spare g.Roll(3); RollMany(17, 0); Assert.That(g.Score(), Is.EqualTo(16)); }
The Third test. ,[object Object]
ugly comment in conditional.publicint Score() { int score = 0; int roll = 0; for (int frame = 0; frame < 10; frame++) { // spare if (rolls[roll] + rolls[roll + 1] == 10) { score += 10 + rolls[roll + 2]; roll += 2; } else {             score += rolls[roll] + rolls[roll + 1];                   roll += 2;         }    } return score; } [Test] publicvoidOneSpareTest() { g.Roll(5); g.Roll(5); // spare g.Roll(3); RollMany(17, 0); Assert.That(g.Score(), Is.EqualTo(16)); }
The Third test. - ugly comment in test. publicint Score() { int score = 0; int roll = 0; for (int frame = 0; frame < 10; frame++) {         if(IsSpare(roll))         {            score += 10 + rolls[roll + 2];             roll += 2;         } else         {             score += rolls[roll] + rolls[roll + 1];                   roll += 2; }    } returnscore; } privateboolIsSpare(int roll) {     returnrolls[roll] +     rolls[roll + 1] == 10; } [Test] publicvoidOneSpareTest() { g.Roll(5); g.Roll(5); // spare g.Roll(3); RollMany(17, 0); Assert.That(g.Score(), Is.EqualTo(16)); }
The Third test. [Test] publicvoidOneSpareTest() { RollSpare(); g.Roll(3); RollMany(17, 0); Assert.That(g.Score(), Is.EqualTo(16)); } privatevoidRollSpare() { g.Roll(5); g.Roll(5); } publicint Score() { int score = 0; int roll = 0; for (int frame = 0; frame < 10; frame++) {         if(IsSpare(roll))         {             score += 10 + rolls[roll + 2];             roll += 2;         } else         {             score += rolls[roll] + rolls[roll + 1];                   roll += 2;         } } returnscore; } privateboolIsSpare(int roll) {     returnrolls[roll] +     rolls[roll + 1] == 10; }
The Fourth test. - ugly comment in OneStrikeTest. [Test] publicvoidOneStrikeTest() { g.Roll(10); // strike g.Roll(3); g.Roll(4); RollMany(16, 0); Assert.That(g.Score(), Is.EqualTo(24)); } publicint Score() { int score = 0; int roll = 0; for (int frame = 0; frame < 10; frame++) {         if(IsSpare(roll)) {     score += 10 + rolls[roll + 2]; } else {             score += rolls[roll] + rolls[roll + 1]; } roll += 2; } returnscore; } privatebool IsSpare(int roll) {     returnrolls[roll] +     rolls[roll + 1] == 10; } Failed Assert.AreEqual Expected:<24>. Actual:<17>
The Fourth test. ,[object Object]
ugly comment in conditional.
ugly expressions.publicint Score() {     intscore = 0; introll = 0; for(int frame = 0; frame < 10; frame++) { if(rolls[roll] == 10) // strike {     score += 10 + rolls[roll + 1]     + rolls[roll + 2]; roll++; } elseif (IsSpare(roll)) {     score += 10 + rolls[roll + 2]; roll += 2; } else {     score += rolls[roll] + rolls[roll + 1]; roll += 2; }     }     returnscore; } [Test] publicvoidOneStrikeTest() { g.Roll(10); // strike g.Roll(3); g.Roll(4); RollMany(16, 0); Assert.That(g.Score(), Is.EqualTo(24)); }
The Fourth test. ,[object Object]
ugly comment in conditional.publicint Score() {     intscore = 0; introll = 0; for(int frame = 0; frame < 10; frame++) { if(rolls[roll] == 10) // strike {     score += 10 + StrikeBonus(roll); roll++; } elseif (IsSpare(roll)) {     score += 10 + SpareBonus(roll); roll += 2; } else {            score += SumOfBallsInFrame(roll); roll += 2; } } returnscore; } privateint SumOfBallsInFrame(int roll) {     returnrolls[roll] + rolls[roll + 1]; } privateint SpareBonus(int roll) {     returnrolls[roll + 2]; } privateint StrikeBonus(int roll) {     returnrolls[roll + 1] + rolls[roll + 2]; } [Test] publicvoidOneStrikeTest() { g.Roll(10); // strike g.Roll(3); g.Roll(4); RollMany(16, 0); Assert.That(g.Score(), Is.EqualTo(24)); }
The Fourth test. - ugly comment in OneStrikeTest. publicint Score() { int score = 0; int roll = 0; for (int frame = 0; frame < 10; frame++) { if(IsStrike(roll)) {     score += 10     + StrikeBonus(roll); roll++; } elseif (IsSpare(roll)) { score += 10 + SpareBonus(roll); roll += 2; } else {             score += SumOfBallsInFrame(roll); roll += 2; } } returnscore; } privatebool IsStrike(int roll) {     returnrolls[roll] == 10; } [Test] publicvoidOneStrikeTest() { g.Roll(10); // strike g.Roll(3); g.Roll(4); RollMany(16, 0); Assert.That(g.Score(), Is.EqualTo(24)); }

Contenu connexe

Tendances

Tendances (20)

Labs Jogos Java
Labs Jogos JavaLabs Jogos Java
Labs Jogos Java
 
Java 8 Lambda Built-in Functional Interfaces
Java 8 Lambda Built-in Functional InterfacesJava 8 Lambda Built-in Functional Interfaces
Java 8 Lambda Built-in Functional Interfaces
 
Java Foundations: Maps, Lambda and Stream API
Java Foundations: Maps, Lambda and Stream APIJava Foundations: Maps, Lambda and Stream API
Java Foundations: Maps, Lambda and Stream API
 
JMockit Framework Overview
JMockit Framework OverviewJMockit Framework Overview
JMockit Framework Overview
 
Java loops
Java loopsJava loops
Java loops
 
Methods in java
Methods in javaMethods in java
Methods in java
 
javathreads
javathreadsjavathreads
javathreads
 
Deep dive into Coroutines on JVM @ KotlinConf 2017
Deep dive into Coroutines on JVM @ KotlinConf 2017Deep dive into Coroutines on JVM @ KotlinConf 2017
Deep dive into Coroutines on JVM @ KotlinConf 2017
 
Java Foundations: Basic Syntax, Conditions, Loops
Java Foundations: Basic Syntax, Conditions, LoopsJava Foundations: Basic Syntax, Conditions, Loops
Java Foundations: Basic Syntax, Conditions, Loops
 
Java Swing JFC
Java Swing JFCJava Swing JFC
Java Swing JFC
 
Java Foundations: Methods
Java Foundations: MethodsJava Foundations: Methods
Java Foundations: Methods
 
Generics in java
Generics in javaGenerics in java
Generics in java
 
An introduction to Google test framework
An introduction to Google test frameworkAn introduction to Google test framework
An introduction to Google test framework
 
Kotlin scope functions
Kotlin scope functionsKotlin scope functions
Kotlin scope functions
 
Inheritance ppt
Inheritance pptInheritance ppt
Inheritance ppt
 
jQuery - Chapter 3 - Effects
jQuery - Chapter 3 - Effects  jQuery - Chapter 3 - Effects
jQuery - Chapter 3 - Effects
 
2. Classes | Object Oriented Programming in JavaScript | ES6 | JavaScript
2. Classes | Object Oriented Programming in JavaScript | ES6 | JavaScript2. Classes | Object Oriented Programming in JavaScript | ES6 | JavaScript
2. Classes | Object Oriented Programming in JavaScript | ES6 | JavaScript
 
JUnit 4
JUnit 4JUnit 4
JUnit 4
 
Domain Modeling with FP (DDD Europe 2020)
Domain Modeling with FP (DDD Europe 2020)Domain Modeling with FP (DDD Europe 2020)
Domain Modeling with FP (DDD Europe 2020)
 
Python Deserialization Attacks
Python Deserialization AttacksPython Deserialization Attacks
Python Deserialization Attacks
 

Similaire à Bowling Game Kata in C# Adapted

Bowling game kata
Bowling game kataBowling game kata
Bowling game kata
Carol Bruno
 
Bowling game kata
Bowling game kataBowling game kata
Bowling game kata
Joe McCall
 
Bowling game kata
Bowling game kataBowling game kata
Bowling game kata
Rahman Ash
 
Test-Driven Development Fundamentals on Force.com
Test-Driven Development Fundamentals on Force.comTest-Driven Development Fundamentals on Force.com
Test-Driven Development Fundamentals on Force.com
Salesforce Developers
 
I dont know what is wrong with this roulette program I cant seem.pdf
I dont know what is wrong with this roulette program I cant seem.pdfI dont know what is wrong with this roulette program I cant seem.pdf
I dont know what is wrong with this roulette program I cant seem.pdf
archanaemporium
 
The main class of the tictoe game looks like.public class Main {.pdf
The main class of the tictoe game looks like.public class Main {.pdfThe main class of the tictoe game looks like.public class Main {.pdf
The main class of the tictoe game looks like.public class Main {.pdf
asif1401
 
You will write a multi-interface version of the well-known concentra.pdf
You will write a multi-interface version of the well-known concentra.pdfYou will write a multi-interface version of the well-known concentra.pdf
You will write a multi-interface version of the well-known concentra.pdf
FashionColZone
 
package com.tictactoe; public class Main {public void play() {.pdf
package com.tictactoe; public class Main {public void play() {.pdfpackage com.tictactoe; public class Main {public void play() {.pdf
package com.tictactoe; public class Main {public void play() {.pdf
info430661
 
In Java using Eclipse, Im suppose to write a class that encapsulat.pdf
In Java using Eclipse, Im suppose to write a class that encapsulat.pdfIn Java using Eclipse, Im suppose to write a class that encapsulat.pdf
In Java using Eclipse, Im suppose to write a class that encapsulat.pdf
anjandavid
 
Working with Layout Managers. Notes 1. In part 2, note that the Gam.pdf
Working with Layout Managers. Notes 1. In part 2, note that the Gam.pdfWorking with Layout Managers. Notes 1. In part 2, note that the Gam.pdf
Working with Layout Managers. Notes 1. In part 2, note that the Gam.pdf
udit652068
 
Ifgqueue.h#ifndef LFGQUEUE_H #define LFGQUEUE_H#include pl.pdf
Ifgqueue.h#ifndef LFGQUEUE_H #define LFGQUEUE_H#include pl.pdfIfgqueue.h#ifndef LFGQUEUE_H #define LFGQUEUE_H#include pl.pdf
Ifgqueue.h#ifndef LFGQUEUE_H #define LFGQUEUE_H#include pl.pdf
fazilfootsteps
 
Write a class (BasketballTeam) encapsulating the concept of a tea.pdf
Write a class (BasketballTeam) encapsulating the concept of a tea.pdfWrite a class (BasketballTeam) encapsulating the concept of a tea.pdf
Write a class (BasketballTeam) encapsulating the concept of a tea.pdf
rozakashif85
 
This is Java,I am currently stumped on how to add a scoreboard for.pdf
This is Java,I am currently stumped on how to add a scoreboard for.pdfThis is Java,I am currently stumped on how to add a scoreboard for.pdf
This is Java,I am currently stumped on how to add a scoreboard for.pdf
anjandavid
 

Similaire à Bowling Game Kata in C# Adapted (20)

Bowling game kata
Bowling game kataBowling game kata
Bowling game kata
 
Bowling game kata
Bowling game kataBowling game kata
Bowling game kata
 
Bowling game kata
Bowling game kataBowling game kata
Bowling game kata
 
Test-Driven Development Fundamentals on Force.com
Test-Driven Development Fundamentals on Force.comTest-Driven Development Fundamentals on Force.com
Test-Driven Development Fundamentals on Force.com
 
I dont know what is wrong with this roulette program I cant seem.pdf
I dont know what is wrong with this roulette program I cant seem.pdfI dont know what is wrong with this roulette program I cant seem.pdf
I dont know what is wrong with this roulette program I cant seem.pdf
 
The main class of the tictoe game looks like.public class Main {.pdf
The main class of the tictoe game looks like.public class Main {.pdfThe main class of the tictoe game looks like.public class Main {.pdf
The main class of the tictoe game looks like.public class Main {.pdf
 
New Tools for a More Functional C++
New Tools for a More Functional C++New Tools for a More Functional C++
New Tools for a More Functional C++
 
You will write a multi-interface version of the well-known concentra.pdf
You will write a multi-interface version of the well-known concentra.pdfYou will write a multi-interface version of the well-known concentra.pdf
You will write a multi-interface version of the well-known concentra.pdf
 
package com.tictactoe; public class Main {public void play() {.pdf
package com.tictactoe; public class Main {public void play() {.pdfpackage com.tictactoe; public class Main {public void play() {.pdf
package com.tictactoe; public class Main {public void play() {.pdf
 
In Java using Eclipse, Im suppose to write a class that encapsulat.pdf
In Java using Eclipse, Im suppose to write a class that encapsulat.pdfIn Java using Eclipse, Im suppose to write a class that encapsulat.pdf
In Java using Eclipse, Im suppose to write a class that encapsulat.pdf
 
Working with Layout Managers. Notes 1. In part 2, note that the Gam.pdf
Working with Layout Managers. Notes 1. In part 2, note that the Gam.pdfWorking with Layout Managers. Notes 1. In part 2, note that the Gam.pdf
Working with Layout Managers. Notes 1. In part 2, note that the Gam.pdf
 
Driver class
Driver classDriver class
Driver class
 
The Ring programming language version 1.5 book - Part 9 of 31
The Ring programming language version 1.5 book - Part 9 of 31The Ring programming language version 1.5 book - Part 9 of 31
The Ring programming language version 1.5 book - Part 9 of 31
 
Tic tac toe on c++ project
Tic tac toe on c++ projectTic tac toe on c++ project
Tic tac toe on c++ project
 
Ifgqueue.h#ifndef LFGQUEUE_H #define LFGQUEUE_H#include pl.pdf
Ifgqueue.h#ifndef LFGQUEUE_H #define LFGQUEUE_H#include pl.pdfIfgqueue.h#ifndef LFGQUEUE_H #define LFGQUEUE_H#include pl.pdf
Ifgqueue.h#ifndef LFGQUEUE_H #define LFGQUEUE_H#include pl.pdf
 
The Ring programming language version 1.6 book - Part 55 of 189
The Ring programming language version 1.6 book - Part 55 of 189The Ring programming language version 1.6 book - Part 55 of 189
The Ring programming language version 1.6 book - Part 55 of 189
 
The Ring programming language version 1.3 book - Part 43 of 88
The Ring programming language version 1.3 book - Part 43 of 88The Ring programming language version 1.3 book - Part 43 of 88
The Ring programming language version 1.3 book - Part 43 of 88
 
Testing a 2D Platformer with Spock
Testing a 2D Platformer with SpockTesting a 2D Platformer with Spock
Testing a 2D Platformer with Spock
 
Write a class (BasketballTeam) encapsulating the concept of a tea.pdf
Write a class (BasketballTeam) encapsulating the concept of a tea.pdfWrite a class (BasketballTeam) encapsulating the concept of a tea.pdf
Write a class (BasketballTeam) encapsulating the concept of a tea.pdf
 
This is Java,I am currently stumped on how to add a scoreboard for.pdf
This is Java,I am currently stumped on how to add a scoreboard for.pdfThis is Java,I am currently stumped on how to add a scoreboard for.pdf
This is Java,I am currently stumped on how to add a scoreboard for.pdf
 

Plus de Mike Clement

Code Katas Spring 2012
Code Katas Spring 2012Code Katas Spring 2012
Code Katas Spring 2012
Mike Clement
 
FizzBuzz Guided Kata
FizzBuzz Guided KataFizzBuzz Guided Kata
FizzBuzz Guided Kata
Mike Clement
 
Software Craftsmanship
Software CraftsmanshipSoftware Craftsmanship
Software Craftsmanship
Mike Clement
 
Using Rhino Mocks for Effective Unit Testing
Using Rhino Mocks for Effective Unit TestingUsing Rhino Mocks for Effective Unit Testing
Using Rhino Mocks for Effective Unit Testing
Mike Clement
 

Plus de Mike Clement (20)

Collaboration Principles from Mob Programming
Collaboration Principles from Mob ProgrammingCollaboration Principles from Mob Programming
Collaboration Principles from Mob Programming
 
Focus on Flow: Lean Principles in Action
Focus on Flow: Lean Principles in ActionFocus on Flow: Lean Principles in Action
Focus on Flow: Lean Principles in Action
 
Taming scary production code that nobody wants to touch
Taming scary production code that nobody wants to touchTaming scary production code that nobody wants to touch
Taming scary production code that nobody wants to touch
 
Develop your sense of code smell
Develop your sense of code smellDevelop your sense of code smell
Develop your sense of code smell
 
Maps over Backlogs: User Story Mapping to Share the Big Picture
Maps over Backlogs: User Story Mapping to Share the Big PictureMaps over Backlogs: User Story Mapping to Share the Big Picture
Maps over Backlogs: User Story Mapping to Share the Big Picture
 
Escaping the Pitfalls of Software Product Development
Escaping the Pitfalls of Software Product DevelopmentEscaping the Pitfalls of Software Product Development
Escaping the Pitfalls of Software Product Development
 
Put the Tests Before the Code
Put the Tests Before the CodePut the Tests Before the Code
Put the Tests Before the Code
 
Mob Programming for Continuous Learning
Mob Programming for Continuous LearningMob Programming for Continuous Learning
Mob Programming for Continuous Learning
 
Play to Learn: Agile Games with Cards and Dice
Play to Learn: Agile Games with Cards and DicePlay to Learn: Agile Games with Cards and Dice
Play to Learn: Agile Games with Cards and Dice
 
The Quest for Continuous Delivery at Pluralsight
The Quest for Continuous Delivery at PluralsightThe Quest for Continuous Delivery at Pluralsight
The Quest for Continuous Delivery at Pluralsight
 
Software Craftsmanship and Agile Code Games
Software Craftsmanship and Agile Code GamesSoftware Craftsmanship and Agile Code Games
Software Craftsmanship and Agile Code Games
 
Thinking in F#
Thinking in F#Thinking in F#
Thinking in F#
 
Transformation Priority Premise: TDD Test Order Matters
Transformation Priority Premise: TDD Test Order MattersTransformation Priority Premise: TDD Test Order Matters
Transformation Priority Premise: TDD Test Order Matters
 
Power of Patterns: Refactoring to (or away from) Patterns
Power of Patterns: Refactoring to (or away from) PatternsPower of Patterns: Refactoring to (or away from) Patterns
Power of Patterns: Refactoring to (or away from) Patterns
 
Code Katas Spring 2012
Code Katas Spring 2012Code Katas Spring 2012
Code Katas Spring 2012
 
FizzBuzz Guided Kata
FizzBuzz Guided KataFizzBuzz Guided Kata
FizzBuzz Guided Kata
 
Linq (from the inside)
Linq (from the inside)Linq (from the inside)
Linq (from the inside)
 
Code Katas: Practicing Your Craft
Code Katas: Practicing Your CraftCode Katas: Practicing Your Craft
Code Katas: Practicing Your Craft
 
Software Craftsmanship
Software CraftsmanshipSoftware Craftsmanship
Software Craftsmanship
 
Using Rhino Mocks for Effective Unit Testing
Using Rhino Mocks for Effective Unit TestingUsing Rhino Mocks for Effective Unit Testing
Using Rhino Mocks for Effective Unit Testing
 

Dernier

Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
Joaquim Jorge
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
Earley Information Science
 

Dernier (20)

The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdf
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
 
Evaluating the top large language models.pdf
Evaluating the top large language models.pdfEvaluating the top large language models.pdf
Evaluating the top large language models.pdf
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 

Bowling Game Kata in C# Adapted

  • 1. Bowling Game KataAdapted for C# and nUnit By Dan Stewart (with modifications by Mike Clement) dan@stewshack.com mike@softwareontheside.com
  • 2. Scoring Bowling. The game consists of 10 frames as shown above. In each frame the player has two opportunities to knock down 10 pins. The score for the frame is the total number of pins knocked down, plus bonuses for strikes and spares. A spare is when the player knocks down all 10 pins in two tries. The bonus for that frame is the number of pins knocked down by the next roll. So in frame 3 above, the score is 10 (the total number knocked down) plus a bonus of 5 (the number of pins knocked down on the next roll.) A strike is when the player knocks down all 10 pins on his first try. The bonus for that frame is the value of the next two balls rolled. In the tenth frame a player who rolls a spare or strike is allowed to roll the extra balls to complete the frame. However no more than three balls can be rolled in tenth frame.
  • 3. A quick design session Clearly we need the Game class.
  • 4. A quick design session A game has 10 frames.
  • 5. A quick design session A frame has 1 or two rolls.
  • 6. A quick design session The tenth frame has two or three rolls. It is different from all the other frames.
  • 7. A quick design session The score function must include all the frames, and calculate all their scores.
  • 8. A quick design session The score for a spare or a strike depends on the frame’s successor
  • 9. Begin. Create a class library named BowlingGameKata
  • 10. Begin. Add a test fixture named BowlingGameTests to the project usingNUnit.Framework; namespaceBowlingGameKata { [TestFixture] publicclassBowlingGameTests { [Test] publicvoidGutterGameTest() { } } }
  • 11. The first test. [Test] publicvoidGutterGameTest() { Game g = new Game(); }
  • 12. The first test. namespaceBowlingGameKata { publicclassGame { } } [Test] publicvoidGutterGameTest() { Game g = new Game(); }
  • 13. The first test. [Test] publicvoidGutterGameTest() { Game g = new Game(); } publicclassGame { }
  • 14. The first test. [Test] publicvoidGutterGameTest() { Gameg = newGame(); for(int i = 0; i < 20; i++) { g.Roll(0); } } publicclassGame { }
  • 15. The first test. public class Game { publicvoid Roll(int p) { thrownewSystem.NotImplementedException(); } } [Test] publicvoidGutterGameTest() { Gameg = newGame(); for(int i = 0; i < 20; i++) { g.Roll(0); } }
  • 16. The first test. [Test] publicvoidGutterGameTest() { Gameg = newGame(); for(int i = 0; i < 20; i++) { g.Roll(0); } Assert.That(g.Score(), Is.EqualTo(0)); } public class Game { publicvoid Roll(int p) { thrownewSystem.NotImplementedException(); } }
  • 17. The first test. [Test] publicvoidGutterGameTest() { Gameg = newGame(); for(int i = 0; i < 20; i++) { g.Roll(0); } Assert.That(g.Score(), Is.EqualTo(0)); } publicclassGame { publicvoid Roll(int p) { thrownew System.NotImplementedException(); } publicobject Score() { thrownew System.NotImplementedException(); } } Failed GutterGameTestthrew exception
  • 18. The first test. [Test] publicvoidGutterGameTest() { Gameg = newGame(); for(int i = 0; i < 20; i++) { g.Roll(0); } Assert.That(g.Score(), Is.EqualTo(0)); } publicclassGame { privateint score; publicvoid Roll(int pins) { } publicintScore() { returnscore; } }
  • 19. The Second test. [Test] publicvoidAllOnesTest() { Gameg = newGame(); for(int i = 0; i < 20; i++) { g.Roll(1); } Assert.That(g.Score(), Is.EqualTo(20)); } publicclassGame { privateint score; publicvoid Roll(int pins) { } publicintScore() { returnscore; } }
  • 20. The Second test. - Game creation is duplicated - roll loop is duplicated [Test] publicvoidAllOnesTest() { Gameg = newGame(); for(int i = 0; i < 20; i++) { g.Roll(1); } Assert.That(g.Score(), Is.EqualTo(20)); } publicclassGame { privateint score; publicvoid Roll(int pins) { } publicintScore() { returnscore; } }
  • 21. The Second test. - Game creation is duplicated - roll loop is duplicated [Test] publicvoidAllOnesTest() { Gameg = newGame(); for(int i = 0; i < 20; i++) { g.Roll(1); } Assert.That(g.Score(), Is.EqualTo(20)); } publicclassGame { privateint score; publicvoid Roll(int pins) { } publicintScore() { return score; } } Assert.AreEqual failed. Expected:<20>. Actual:<0>.
  • 22. The Second test. - roll loop is duplicated privateGame g; [SetUp] publicvoidSetup() { g = newGame(); } [Test] publicvoidGutterGameTest() { for(int i = 0; i < 20; i++) { g.Roll(0); } Assert.That(g.Score(), Is.EqualTo(0)); } [Test] publicvoidAllOnesTest() { for(int i = 0; i < 20; i++) { g.Roll(1); } Assert.That(g.Score(), Is.EqualTo(20)); } publicclassGame { privateint score; publicvoid Roll(int pins) { score += pins; } publicint Score() { return score; } }
  • 23. The Second test. - roll loop is duplicated [Test] publicvoidGutterGameTest() { int rolls = 20; intpins = 0; for(int i = 0; i < rolls; i++) { g.Roll(pins); } Assert.That(g.Score(), Is.EqualTo(0)); } publicclassGame { privateint score; publicvoid Roll(int pins) { score += pins; } publicint Score() { return score; } }
  • 24. The Second test. - roll loop is duplicated [Test] publicvoidGutterGameTest() { int rolls = 20; intpins = 0; RollMany(rolls, pins); for(int i = 0; i < rolls; i++) { g.Roll(pins); } Assert.That(g.Score(), Is.EqualTo(0)); } publicclassGame { privateint score; publicvoid Roll(int pins) { score += pins; } publicint Score() { return score; } }
  • 25. The Second test. publicclassGame { privateint score; publicvoid Roll(int pins) { score += pins; } publicint Score() { return score; } } [Test] publicvoidGutterGameTest() { RollMany(20, 0); Assert.That(g.Score(), Is.EqualTo(0)); } privatevoidRollMany(introlls, int pins) { for(int i = 0; i < rolls; i++) { g.Roll(pins); } }
  • 26. The Second test. [Test] publicvoidGutterGameTest() { RollMany(20, 0); Assert.That(g.Score(), Is.EqualTo(0)); } [Test] publicvoidAllOnesTest() { RollMany(20, 1); Assert.That(g.Score(), Is.EqualTo(20)); } privatevoidRollMany(int rolls, int pins) { for(int i = 0; i < rolls; i++) { g.Roll(pins); } } publicclassGame { privateint score; publicvoid Roll(int pins) { score += pins; } publicint Score() { return score; } }
  • 27. The Third test. - ugly comment in test. [Test] publicvoidOneSpareTest() { g.Roll(5); g.Roll(5); // spare g.Roll(3); RollMany(17, 0); Assert.That(g.Score(), Is.EqualTo(16)); } publicclassGame { privateint score; publicvoid Roll(int pins) { score += pins; } publicint Score() { return score; } } Failed Assert.AreEqual Expected:<16>. Actual:<13>
  • 28. The Third test. - ugly comment in test. publicclassGame { privateint score; publicvoid Roll(int pins) { score += pins; } publicint Score() { return score; } } [Test] publicvoidOneSpareTest() { g.Roll(5); g.Roll(5); // spare g.Roll(3); RollMany(17, 0); Assert.That(g.Score(), Is.EqualTo(16)); } tempted to use flag to remember previous roll. So design must be wrong. Failed Assert.AreEqual Expected:<16>. Actual:<13>
  • 29. The Third test. - ugly comment in test. Roll() calculates score, but name does not imply that. publicclassGame { privateint score; publicvoid Roll(int pins) { score += pins; } publicint Score() { return score; } } [Test] publicvoidOneSpareTest() { g.Roll(5); g.Roll(5); // spare g.Roll(3); RollMany(17, 0); Assert.AreEqual(16, g.Score); } Score() does not calculate score, but name implies that it does. Design is wrong. Responsibilities are misplaced. Failed Assert.AreEqual Expected:<16>. Actual:<13>
  • 30. The Third test. - ugly comment in test. [Test] publicvoidOneSpareTest() { g.Roll(5); g.Roll(5); // spare g.Roll(3); RollMany(17, 0); //Assert.That(g.Score(), Is.EqualTo(16)); } publicclassGame { privateint score; publicvoid Roll(int pins) { score += pins; } publicint Score() { return score; } }
  • 31. The Third test. - ugly comment in test. publicclassGame { privateint score; privateint[] rolls = newint[21]; privateint currentRoll; publicvoid Roll(int pins) { rolls[currentRoll++] = pins; score += pins; } publicint Score() { return score; } } [Test] publicvoidOneSpareTest() { g.Roll(5); g.Roll(5); // spare g.Roll(3); RollMany(17, 0); //Assert.That(g.Score(), Is.EqualTo(16)); }
  • 32. The Third test. - ugly comment in test. publicclassGame { privateint[] rolls = newint[21]; privateint currentRoll; publicvoid Roll(int pins) { rolls[currentRoll++] = pins; } publicint Score() { int score = 0; for (int i = 0; i < rolls.Length; i++) { score += rolls[i]; } return score; } } [Test] publicvoidOneSpareTest() { g.Roll(5); g.Roll(5); // spare g.Roll(3); RollMany(17, 0); //Assert.That(g.Score(), Is.EqualTo(16)); }
  • 33. The Third test. - ugly comment in test. [Test] publicvoidOneSpareTest() { g.Roll(5); g.Roll(5); // spare g.Roll(3); RollMany(17, 0); Assert.That(g.Score(), Is.EqualTo(16)); } publicclassGame { privateint[] rolls = newint[21]; privateint currentRoll; publicvoid Roll(int pins) { rolls[currentRoll++] = pins; } publicint Score() { int score = 0; for (int i = 0; i < rolls.Length; i++) { score += rolls[i]; } return score; } } Failed Assert.AreEqual Expected:<16>. Actual:<13>
  • 34. The Third test. - ugly comment in test. publicint Score() { int score = 0; for (int i = 0; i < rolls.Length; i++) { // spare if(rolls[i] + rolls[i+1] == 10) { score += ... } score += rolls[i]; } return score; } [Test] publicvoidOneSpareTest() { g.Roll(5); g.Roll(5); // spare g.Roll(3); RollMany(17, 0); Assert.That(g.Score(), Is.EqualTo(16)); } This isn’t going to work because i might not refer to the first ball of the frame. Design is still wrong. Need to walk through array two balls (one frame) at a time. Failed Assert.AreEqual Expected:<16>. Actual:<13>
  • 35. The Third test. - ugly comment in test. publicclassGame { privateint[] rolls = newint[21]; privateint currentRoll; publicvoid Roll(int pins) { rolls[currentRoll++] = pins; } publicint Score() { int score = 0; for (int i = 0; i < rolls.Length; i++) { score += rolls[i]; } return score; } } [Test] publicvoidOneSpareTest() { g.Roll(5); g.Roll(5); // spare g.Roll(3); RollMany(17, 0); //Assert.That(g.Score(), Is.EqualTo(16)); Assert.Inconclusive(); }
  • 36. The Third test. - ugly comment in test. publicint Score() { int score = 0; inti = 0; for (int frame = 0; frame < 10; frame++) { score += rolls[i] + rolls[i + 1]; i+= 2; } returnscore; } [Test] publicvoidOneSpareTest() { g.Roll(5); g.Roll(5); // spare g.Roll(3); RollMany(17, 0); //Assert.That(g.Score(), Is.EqualTo(16)); Assert.Inconclusive(); }
  • 37. The Third test. - ugly comment in test. [Test] publicvoidOneSpareTest() { g.Roll(5); g.Roll(5); // spare g.Roll(3); RollMany(17, 0); Assert.That(g.Score(), Is.EqualTo(16)); } publicint Score() { int score = 0; int i = 0; for (int frame = 0; frame < 10; frame++) { score += rolls[i] + rolls[i + 1]; i += 2; } return score; } Failed Assert.AreEqual Expected:<16>. Actual:<13>
  • 38. The Third test. - ugly comment in test. publicint Score() { int score = 0; inti = 0; for (int frame = 0; frame < 10; frame++) { // spare if (rolls[i] + rolls[i + 1] == 10) { score += 10 + rolls[i + 2]; i += 2; } else { score += rolls[i] + rolls[i + 1]; i += 2; } } return score; } [Test] publicvoidOneSpareTest() { g.Roll(5); g.Roll(5); // spare g.Roll(3); RollMany(17, 0); Assert.That(g.Score(), Is.EqualTo(16)); }
  • 39.
  • 40. ugly comment in conditional.publicint Score() { int score = 0; int roll = 0; for (int frame = 0; frame < 10; frame++) { // spare if (rolls[roll] + rolls[roll + 1] == 10) { score += 10 + rolls[roll + 2]; roll += 2; } else { score += rolls[roll] + rolls[roll + 1]; roll += 2; } } return score; } [Test] publicvoidOneSpareTest() { g.Roll(5); g.Roll(5); // spare g.Roll(3); RollMany(17, 0); Assert.That(g.Score(), Is.EqualTo(16)); }
  • 41. The Third test. - ugly comment in test. publicint Score() { int score = 0; int roll = 0; for (int frame = 0; frame < 10; frame++) { if(IsSpare(roll)) { score += 10 + rolls[roll + 2]; roll += 2; } else { score += rolls[roll] + rolls[roll + 1]; roll += 2; } } returnscore; } privateboolIsSpare(int roll) { returnrolls[roll] + rolls[roll + 1] == 10; } [Test] publicvoidOneSpareTest() { g.Roll(5); g.Roll(5); // spare g.Roll(3); RollMany(17, 0); Assert.That(g.Score(), Is.EqualTo(16)); }
  • 42. The Third test. [Test] publicvoidOneSpareTest() { RollSpare(); g.Roll(3); RollMany(17, 0); Assert.That(g.Score(), Is.EqualTo(16)); } privatevoidRollSpare() { g.Roll(5); g.Roll(5); } publicint Score() { int score = 0; int roll = 0; for (int frame = 0; frame < 10; frame++) { if(IsSpare(roll)) { score += 10 + rolls[roll + 2]; roll += 2; } else { score += rolls[roll] + rolls[roll + 1]; roll += 2; } } returnscore; } privateboolIsSpare(int roll) { returnrolls[roll] + rolls[roll + 1] == 10; }
  • 43. The Fourth test. - ugly comment in OneStrikeTest. [Test] publicvoidOneStrikeTest() { g.Roll(10); // strike g.Roll(3); g.Roll(4); RollMany(16, 0); Assert.That(g.Score(), Is.EqualTo(24)); } publicint Score() { int score = 0; int roll = 0; for (int frame = 0; frame < 10; frame++) { if(IsSpare(roll)) { score += 10 + rolls[roll + 2]; } else { score += rolls[roll] + rolls[roll + 1]; } roll += 2; } returnscore; } privatebool IsSpare(int roll) { returnrolls[roll] + rolls[roll + 1] == 10; } Failed Assert.AreEqual Expected:<24>. Actual:<17>
  • 44.
  • 45. ugly comment in conditional.
  • 46. ugly expressions.publicint Score() { intscore = 0; introll = 0; for(int frame = 0; frame < 10; frame++) { if(rolls[roll] == 10) // strike { score += 10 + rolls[roll + 1] + rolls[roll + 2]; roll++; } elseif (IsSpare(roll)) { score += 10 + rolls[roll + 2]; roll += 2; } else { score += rolls[roll] + rolls[roll + 1]; roll += 2; } } returnscore; } [Test] publicvoidOneStrikeTest() { g.Roll(10); // strike g.Roll(3); g.Roll(4); RollMany(16, 0); Assert.That(g.Score(), Is.EqualTo(24)); }
  • 47.
  • 48. ugly comment in conditional.publicint Score() { intscore = 0; introll = 0; for(int frame = 0; frame < 10; frame++) { if(rolls[roll] == 10) // strike { score += 10 + StrikeBonus(roll); roll++; } elseif (IsSpare(roll)) { score += 10 + SpareBonus(roll); roll += 2; } else { score += SumOfBallsInFrame(roll); roll += 2; } } returnscore; } privateint SumOfBallsInFrame(int roll) { returnrolls[roll] + rolls[roll + 1]; } privateint SpareBonus(int roll) { returnrolls[roll + 2]; } privateint StrikeBonus(int roll) { returnrolls[roll + 1] + rolls[roll + 2]; } [Test] publicvoidOneStrikeTest() { g.Roll(10); // strike g.Roll(3); g.Roll(4); RollMany(16, 0); Assert.That(g.Score(), Is.EqualTo(24)); }
  • 49. The Fourth test. - ugly comment in OneStrikeTest. publicint Score() { int score = 0; int roll = 0; for (int frame = 0; frame < 10; frame++) { if(IsStrike(roll)) { score += 10 + StrikeBonus(roll); roll++; } elseif (IsSpare(roll)) { score += 10 + SpareBonus(roll); roll += 2; } else { score += SumOfBallsInFrame(roll); roll += 2; } } returnscore; } privatebool IsStrike(int roll) { returnrolls[roll] == 10; } [Test] publicvoidOneStrikeTest() { g.Roll(10); // strike g.Roll(3); g.Roll(4); RollMany(16, 0); Assert.That(g.Score(), Is.EqualTo(24)); }
  • 50. The Fourth test. [Test] publicvoidOneStrikeTest() { RollStrike(); g.Roll(3); g.Roll(4); RollMany(16, 0); Assert.That(g.Score(), Is.EqualTo(24)); } privatevoidRollStrike() { g.Roll(10); } publicint Score() { int score = 0; int roll = 0; for (int frame = 0; frame < 10; frame++) { if(IsStrike(roll)) { score += 10 + StrikeBonus(roll); roll++; } elseif (IsSpare(roll)) { score += 10 + SpareBonus(roll); roll += 2; } else { score += SumOfBallsInFrame(roll); roll += 2; } } returnscore; }
  • 51. The Fifth test. [Test] publicvoidPerfectGameTest() { RollMany(12, 10); Assert.That(g.Score(), Is.EqualTo(300)); } publicint Score() { int score = 0; int roll = 0; for (int frame = 0; frame < 10; frame++) { if(IsStrike(roll)) { score += 10 + StrikeBonus(roll); roll++; } elseif (IsSpare(roll)) { score += 10 + SpareBonus(roll); roll += 2; } else { score += SumOfBallsInFrame(roll); roll += 2; } } returnscore; }

Notes de l'éditeur

  1. I would like to thank Uncle Bob Martin and Object Mentor for the bowling game kata.