Tennis-Refactoring-Kata through OOP I was trying to solve Tennis-Refactoring-Kata. This seems quite hard at startup but, through use os OOP it can be deeply refactoring using just a single if. 

My first understanding was about the fact that TennisGame (the main class) has a Score. Or at least should have one.

Furthermore score possibilities are just twenty (Love-All, Fifteen-All and so on...) and each one leads further Scores based on who is the last player who scores a point (e.g.: Love-All leads to Fifteen-Love if last point has been scored by first player, Love-Fifteen otherwise). From this observation I wrote 20 classes like this:

public class LoveAll implements IScore {

    public IScore Player1Scored() {
        return new FifteenLove();
    }

    public IScore Player2Scored() {
        return new LoveFifteen();
    }

    public String Label() {
        return "Love-All";
    }
}


This should seems a loss of time but this is not bad as it seems since each class is simple and concise. This give me the possibilities to write a TennisGame4 like this:

public class TennisGame4 implements TennisGame {    
    private IScore score = null; // Composition here - TennisGame has a Score
    private String player1Name;
    private String player2Name;

    public TennisGame4(String player1Name, String player2Name) {
        this.player1Name = player1Name;
        this.player2Name = player2Name;
        score = new LoveAll();
    }

    public void wonPoint(String playerName) {
        if (playerName.equals("player1"))
            score = score.Player1Scored();
        else 
            score = score.Player2Scored();
    }

    public String getScore() {
        return score.Label();
    }
}


Just a single if to distinguish who is the last player who score a point.
What do you think about this solution? Does this solution respect the kata constraint? 

Consider that:


Code surely can be enhanced (Player should be an object too);
To stay in the Kata I have do everything in 90 minutes or so;
As you say, there are only a limited possibilities for a Score, which I would call GameScore to be more precise. This calls for an enum.

public enum GameScore {
    S0000(0, 0), S1500(15, 0), S3000(30, 0), ...;

    private static final GameScore[] SWIN = { S1500, ... };
    private static final GameScore[] RWIN = { S0015, ... };
    private static final String[] NAME = { "Love-All", ... };

    ...

    public GameScore serverWins() {
        return SWIN[ordinal()];
    }

    public GameScore returnerWins() {
        return RWIN[ordinal()];
    }

    public String getDisplayText() {
        return NAME[ordinal()];
    }
}


That's all. All in one class, ready for testing.

By the way, in Java all method names start with a lowercase letter, not an uppercase. (That would be C# or Ada.)

Using an enum and predefined string literals has the benefit of generating zero memory allocations at runtime.