Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
twitch
live-coding-fr
Commits
4b3fc568
Commit
4b3fc568
authored
Mar 22, 2021
by
Matthieu SAUBOUA-BENELUZ
Browse files
feat(kata-tennis): added tennis refactoring kata
parent
2e17243e
Changes
12
Hide whitespace changes
Inline
Side-by-side
.gitlab-ci.yml
View file @
4b3fc568
...
...
@@ -29,4 +29,5 @@ include:
-
local
:
"
/leap-years/.gitlab-ci.yml"
-
local
:
"
/employee-report/.gitlab-ci.yml"
-
local
:
"
/java-concurrence/.gitlab-ci.yml"
-
local
:
"
/tennis/refactoring/.gitlab-ci.yml"
-
local
:
"
/bowling-game/.gitlab-ci.yml"
README.md
View file @
4b3fc568
...
...
@@ -59,3 +59,4 @@ Ce dépôt Git a pour but de partager les différents ateliers pouvant être ré
|
[
Retour sur les 3 jours de conférences de DDD Europe
](
https://youtu.be/sDUuDpnLWXs
)
| Discussion | |
|
[
Concurrence en Java
](
/java-concurrence
)
| Code&coffee | Enervé |
|
[
Bowling Game
](
/bowling-game
)
| Kata | Moyen |
|
[
Tennis Refactoring kata
](
/tennis/refactoring
)
| Kata | Moyenne |
tennis/README.md
0 → 100644
View file @
4b3fc568
# Tennis coding and refactoring katas
This katas is inspired and uses starting code
from
[
this great github repository
](
https://github.com/emilybache/Tennis-Refactoring-Kata
)
from Emily Bache
## Tennis Coding Kata
Tennis has a rather quirky scoring system, and to newcomers it can be a little difficult to keep track of. The tennis
society has contracted you to build a scoreboard to display the current score during tennis games.
Your task is to write a “TennisGame” class containing the logic which outputs the correct score as a string for display
on the scoreboard. When a player scores a point, it triggers a method to be called on your class letting you know who
scored the point. Later, you will get a call “score()” from the scoreboard asking what it should display. This method
should return a string with the current score.
You can read more about Tennis scores
[
here
](
http://en.wikipedia.org/wiki/Tennis#Scoring
)
which is summarized below:
1.
A game is won by the first player to have scored at least four points in total and at least two points more than the
opponent.
2.
The running score of each game is described in a manner peculiar to tennis: scores from zero to three points are
described as "Love", "Fifteen", "Thirty", and "Forty" respectively.
3.
If at least three points have been scored by each player, and the scores are equal, the score is "Deuce".
4.
If at least three points have been scored by each side and a player has one more point than his opponent, the score
of the game is "Advantage" for the player in the lead.
You need only report the score for the current game. Sets and Matches are out of scope.
## Tennis Refactoring Kata
Imagine you work for a consultancy company, and one of your colleagues has been doing some work for the Tennis Society.
The contract is for 10 hours billable work, and your colleague has spent 8.5 hours working on it. Unfortunately he has
now fallen ill. He says he has completed the work, and the tests all pass. Your boss has asked you to take over from
him. She wants you to spend an hour or so on the code so she can bill the client for the full 10 hours. She instructs
you to tidy up the code a little and perhaps make some notes so you can give your colleague some feedback on his chosen
design. You should also prepare to talk to your boss about the value of this refactoring work, over and above the extra
billable hours.
There are three versions of this refactoring kata, each with their own design smells and challenges. I suggest you start
with the first one, with the class "TennisGame1". The test suite provided is fairly comprehensive, and fast to run. You
should not need to change the tests, only run them often as you refactor.
If you like this Kata, you may be interested in my
book,
[
"The Coding Dojo Handbook"
](
https://leanpub.com/codingdojohandbook
)
## Questions to discuss afterwards
*
How did it feel to work with such fast, comprehensive tests?
*
Did you make mistakes while refactoring that were caught by the tests?
*
If you used a tool to record your test runs, review it. Could you have taken smaller steps? Made fewer refactoring
mistakes?
*
Did you ever make any refactoring mistakes and then back out your changes? How did it feel to throw away code?
*
What would you say to your colleague if they had written this code?
*
What would you say to your boss about the value of this refactoring work? Was there more reason to do it over and
above the extra billable hour or so?
tennis/refactoring/.gitignore
0 → 100644
View file @
4b3fc568
.idea
*.iml
target/
.classpath
.project
.settings/
tennis/refactoring/.gitlab-ci.yml
0 → 100644
View file @
4b3fc568
package-tennis-refactoring
:
variables
:
PROJECT_FOLDER
:
"
tennis/refactoring"
extends
:
.java
only
:
refs
:
-
master
-
merge_requests
changes
:
-
"
.gitlab-common-ci.yml"
-
"
tennis/refactoring/**/*"
tennis/refactoring/pom.xml
0 → 100644
View file @
4b3fc568
<?xml version="1.0" encoding="UTF-8"?>
<project
xmlns=
"http://maven.apache.org/POM/4.0.0"
xmlns:xsi=
"http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=
"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
>
<modelVersion>
4.0.0
</modelVersion>
<parent>
<version>
1.0.0
</version>
<groupId>
fr.ippon.kata
</groupId>
<artifactId>
java-parent
</artifactId>
<relativePath>
../../java-parent
</relativePath>
</parent>
<version>
1.0.0-SNAPSHOT
</version>
<artifactId>
kata-refactoring-tennis
</artifactId>
<developers>
<developer>
<email>
msauboua@ippon.fr
</email>
<name>
Matthieu SAUBOUA-BENELUZ
</name>
</developer>
<developer>
<email>
arey@ippon.fr
</email>
<name>
Anthony REY
</name>
</developer>
</developers>
<properties>
</properties>
<dependencies>
<dependency>
<groupId>
org.junit.jupiter
</groupId>
<artifactId>
junit-jupiter-params
</artifactId>
<version>
5.7.0
</version>
<scope>
test
</scope>
</dependency>
</dependencies>
</project>
tennis/refactoring/src/main/java/fr/ippon/kata/TennisGame.java
0 → 100644
View file @
4b3fc568
package
fr.ippon.kata
;
public
interface
TennisGame
{
void
wonPoint
(
String
playerName
);
String
score
();
}
tennis/refactoring/src/main/java/fr/ippon/kata/TennisGame1.java
0 → 100644
View file @
4b3fc568
package
fr.ippon.kata
;
import
java.util.Map
;
public
class
TennisGame1
implements
TennisGame
{
private
static
final
String
LOVE
=
"Love"
;
private
static
final
String
FIFTEEN
=
"Fifteen"
;
private
static
final
String
THIRTY
=
"Thirty"
;
private
static
final
String
FORTY
=
"Forty"
;
private
static
final
String
ALL
=
"All"
;
private
static
final
String
DEUCE
=
"Deuce"
;
private
static
final
String
SCORE_SEPARATOR
=
"-"
;
private
static
final
Map
<
Integer
,
String
>
SCORES
=
Map
.
of
(
0
,
LOVE
,
1
,
FIFTEEN
,
2
,
THIRTY
,
3
,
FORTY
);
private
static
final
String
WIN_FOR
=
"Win for "
;
private
static
final
String
ADVANTAGE
=
"Advantage "
;
private
int
player1Score
=
0
;
private
int
player2Score
=
0
;
private
final
String
player1Name
;
private
final
String
player2Name
;
public
TennisGame1
(
String
player1Name
,
String
player2Name
)
{
this
.
player1Name
=
player1Name
;
this
.
player2Name
=
player2Name
;
}
public
void
wonPoint
(
String
playerName
)
{
if
(
player1Name
.
equals
(
playerName
))
player1Score
+=
1
;
else
player2Score
+=
1
;
}
public
String
score
()
{
if
(
player1Score
==
player2Score
)
{
return
equalityScore
();
}
if
(
player1Score
>=
4
||
player2Score
>=
4
)
{
return
endGameScore
();
}
return
middleGameScore
();
}
private
String
middleGameScore
()
{
return
SCORES
.
get
(
player1Score
)
+
SCORE_SEPARATOR
+
SCORES
.
get
(
player2Score
);
}
private
String
endGameScore
()
{
int
player1AdvantageValue
=
player1Score
-
player2Score
;
if
(
Math
.
abs
(
player1AdvantageValue
)
==
1
)
{
return
ADVANTAGE
+
advantagedPlayer
();
}
return
WIN_FOR
+
advantagedPlayer
();
}
private
String
advantagedPlayer
()
{
return
player1Score
>
player2Score
?
player1Name
:
player2Name
;
}
private
String
equalityScore
()
{
if
(
player1Score
>=
3
)
{
return
DEUCE
;
}
return
SCORES
.
get
(
player1Score
)
+
SCORE_SEPARATOR
+
ALL
;
}
}
tennis/refactoring/src/main/java/fr/ippon/kata/TennisGame2.java
0 → 100644
View file @
4b3fc568
package
fr.ippon.kata
;
public
class
TennisGame2
implements
TennisGame
{
public
int
P1point
=
0
;
public
int
P2point
=
0
;
public
String
P1res
=
""
;
public
String
P2res
=
""
;
private
String
player1Name
;
private
String
player2Name
;
public
TennisGame2
(
String
player1Name
,
String
player2Name
)
{
this
.
player1Name
=
player1Name
;
this
.
player2Name
=
player2Name
;
}
public
String
score
()
{
String
score
=
""
;
if
(
P1point
==
P2point
&&
P1point
<
4
)
{
if
(
P1point
==
0
)
score
=
"Love"
;
if
(
P1point
==
1
)
score
=
"Fifteen"
;
if
(
P1point
==
2
)
score
=
"Thirty"
;
score
+=
"-All"
;
}
if
(
P1point
==
P2point
&&
P1point
>=
3
)
score
=
"Deuce"
;
if
(
P1point
>
0
&&
P2point
==
0
)
{
if
(
P1point
==
1
)
P1res
=
"Fifteen"
;
if
(
P1point
==
2
)
P1res
=
"Thirty"
;
if
(
P1point
==
3
)
P1res
=
"Forty"
;
P2res
=
"Love"
;
score
=
P1res
+
"-"
+
P2res
;
}
if
(
P2point
>
0
&&
P1point
==
0
)
{
if
(
P2point
==
1
)
P2res
=
"Fifteen"
;
if
(
P2point
==
2
)
P2res
=
"Thirty"
;
if
(
P2point
==
3
)
P2res
=
"Forty"
;
P1res
=
"Love"
;
score
=
P1res
+
"-"
+
P2res
;
}
if
(
P1point
>
P2point
&&
P1point
<
4
)
{
if
(
P1point
==
2
)
P1res
=
"Thirty"
;
if
(
P1point
==
3
)
P1res
=
"Forty"
;
if
(
P2point
==
1
)
P2res
=
"Fifteen"
;
if
(
P2point
==
2
)
P2res
=
"Thirty"
;
score
=
P1res
+
"-"
+
P2res
;
}
if
(
P2point
>
P1point
&&
P2point
<
4
)
{
if
(
P2point
==
2
)
P2res
=
"Thirty"
;
if
(
P2point
==
3
)
P2res
=
"Forty"
;
if
(
P1point
==
1
)
P1res
=
"Fifteen"
;
if
(
P1point
==
2
)
P1res
=
"Thirty"
;
score
=
P1res
+
"-"
+
P2res
;
}
if
(
P1point
>
P2point
&&
P2point
>=
3
)
{
score
=
"Advantage player1"
;
}
if
(
P2point
>
P1point
&&
P1point
>=
3
)
{
score
=
"Advantage player2"
;
}
if
(
P1point
>=
4
&&
P2point
>=
0
&&
(
P1point
-
P2point
)
>=
2
)
{
score
=
"Win for player1"
;
}
if
(
P2point
>=
4
&&
P1point
>=
0
&&
(
P2point
-
P1point
)
>=
2
)
{
score
=
"Win for player2"
;
}
return
score
;
}
public
void
SetP1Score
(
int
number
)
{
for
(
int
i
=
0
;
i
<
number
;
i
++)
{
P1Score
();
}
}
public
void
SetP2Score
(
int
number
)
{
for
(
int
i
=
0
;
i
<
number
;
i
++)
{
P2Score
();
}
}
public
void
P1Score
()
{
P1point
++;
}
public
void
P2Score
()
{
P2point
++;
}
public
void
wonPoint
(
String
player
)
{
if
(
player
==
"player1"
)
P1Score
();
else
P2Score
();
}
}
tennis/refactoring/src/main/java/fr/ippon/kata/TennisGame3.java
0 → 100644
View file @
4b3fc568
package
fr.ippon.kata
;
public
class
TennisGame3
implements
TennisGame
{
private
int
p2
;
private
int
p1
;
private
String
p1N
;
private
String
p2N
;
public
TennisGame3
(
String
p1N
,
String
p2N
)
{
this
.
p1N
=
p1N
;
this
.
p2N
=
p2N
;
}
public
String
score
()
{
String
s
;
if
(
p1
<
4
&&
p2
<
4
&&
!(
p1
+
p2
==
6
))
{
String
[]
p
=
new
String
[]{
"Love"
,
"Fifteen"
,
"Thirty"
,
"Forty"
};
s
=
p
[
p1
];
return
(
p1
==
p2
)
?
s
+
"-All"
:
s
+
"-"
+
p
[
p2
];
}
else
{
if
(
p1
==
p2
)
return
"Deuce"
;
s
=
p1
>
p2
?
p1N
:
p2N
;
return
((
p1
-
p2
)
*
(
p1
-
p2
)
==
1
)
?
"Advantage "
+
s
:
"Win for "
+
s
;
}
}
public
void
wonPoint
(
String
playerName
)
{
if
(
playerName
==
"player1"
)
this
.
p1
+=
1
;
else
this
.
p2
+=
1
;
}
}
tennis/refactoring/src/test/java/fr/ippon/kata/TennisGameUnitTest.java
0 → 100644
View file @
4b3fc568
package
fr.ippon.kata
;
import
org.junit.jupiter.api.Test
;
import
org.junit.jupiter.params.ParameterizedTest
;
import
org.junit.jupiter.params.provider.CsvFileSource
;
import
static
org
.
assertj
.
core
.
api
.
AssertionsForClassTypes
.
assertThat
;
public
class
TennisGameUnitTest
{
@ParameterizedTest
@CsvFileSource
(
delimiter
=
','
,
numLinesToSkip
=
1
,
resources
=
"/param-test-data.csv"
)
void
checkAllScoresTennisGame1
(
Integer
player1Score
,
Integer
player2Score
,
String
expectedScore
)
{
TennisGame1
game
=
new
TennisGame1
(
"player1"
,
"player2"
);
checkAllScores
(
player1Score
,
player2Score
,
expectedScore
,
game
);
}
@Test
void
checkForRealPlayerNames
()
{
String
benoit_paire
=
"Benoit Paire"
;
String
roger_federer
=
"Roger Federer"
;
TennisGame1
game
=
new
TennisGame1
(
benoit_paire
,
roger_federer
);
game
.
wonPoint
(
benoit_paire
);
game
.
wonPoint
(
benoit_paire
);
game
.
wonPoint
(
benoit_paire
);
game
.
wonPoint
(
roger_federer
);
game
.
wonPoint
(
roger_federer
);
game
.
wonPoint
(
roger_federer
);
game
.
wonPoint
(
roger_federer
);
game
.
wonPoint
(
benoit_paire
);
game
.
wonPoint
(
benoit_paire
);
assertThat
(
game
.
score
()).
isEqualTo
(
"Advantage Benoit Paire"
);
}
@ParameterizedTest
@CsvFileSource
(
delimiter
=
','
,
numLinesToSkip
=
1
,
resources
=
"/param-test-data.csv"
)
void
checkAllScoresTennisGame2
(
Integer
player1Score
,
Integer
player2Score
,
String
expectedScore
)
{
TennisGame2
game
=
new
TennisGame2
(
"player1"
,
"player2"
);
checkAllScores
(
player1Score
,
player2Score
,
expectedScore
,
game
);
}
@ParameterizedTest
@CsvFileSource
(
delimiter
=
','
,
numLinesToSkip
=
1
,
resources
=
"/param-test-data.csv"
)
void
checkAllScoresTennisGame3
(
Integer
player1Score
,
Integer
player2Score
,
String
expectedScore
)
{
TennisGame3
game
=
new
TennisGame3
(
"player1"
,
"player2"
);
checkAllScores
(
player1Score
,
player2Score
,
expectedScore
,
game
);
}
private
void
checkAllScores
(
Integer
player1Score
,
Integer
player2Score
,
String
expectedScore
,
TennisGame
game
)
{
int
highestScore
=
Math
.
max
(
player1Score
,
player2Score
);
for
(
int
i
=
0
;
i
<
highestScore
;
i
++)
{
if
(
i
<
player1Score
)
game
.
wonPoint
(
"player1"
);
if
(
i
<
player2Score
)
game
.
wonPoint
(
"player2"
);
}
assertThat
(
game
.
score
()).
isEqualTo
(
expectedScore
);
}
}
tennis/refactoring/src/test/resources/param-test-data.csv
0 → 100644
View file @
4b3fc568
player1Score,player2Score,ExpectedResult
0,0,Love-All
1,1,Fifteen-All
2,2,Thirty-All
3,3,Deuce
4,4,Deuce
1,0,Fifteen-Love
0,1,Love-Fifteen
2,0,Thirty-Love
0,2,Love-Thirty
3,0,Forty-Love
0,3,Love-Forty
4,0,Win for player1
0,4,Win for player2
2,1,Thirty-Fifteen
1,2,Fifteen-Thirty
3,1,Forty-Fifteen
1,3,Fifteen-Forty
4,1,Win for player1
1,4,Win for player2
3,2,Forty-Thirty
2,3,Thirty-Forty
4,2,Win for player1
2,4,Win for player2
4,3,Advantage player1
3,4,Advantage player2
5,4,Advantage player1
4,5,Advantage player2
15,14,Advantage player1
14,15,Advantage player2
6,4,Win for player1
4,6,Win for player2
16,14,Win for player1
14,16,Win for player2
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment