Immutability

Most objects that are created in an OO program are modelled on real life. I recently changed the human player class so that it is not initialised with a board. This is because if a player starts a game they do not need a board to begin with. They only need a board in order to make a move and so now a board is just passed to the markPlayer() method.

Once it has been created in the Game constructor, the board object that is passed to markPlayer() is also the same one that is used throughout the game. All that changes is the List of Symbols that is contained within the board.


public List<Symbol> markPlayer(int indexPosition, Symbol player) {
board.set(indexPosition, player);
return board;
}

Making an object immutable is a logical approach if the object is modelled on a real life object, but can cause problems when you try to implement concurrent programming. It is also useful if you have an identity linked to that object (like a game character in a video game) or have a really complex, large object that would be slow and complicated to initilaize whenever you needed to.

My board in TicTacToe seems to be a good candidate to make immutable, because it does not have a unique identity and is not complex. Infact, I now think the line generation and board size classes that were part of my stories were created for this reason…

In order to make an object immutable the following is necessary:

1. make the class final
 2. make all the member variables final
 3. make all member variables private
 4. make sure no methods change state

So I have changed the board to an immutable board by making this simple change:


public final class Board {
final BoardSize lines;
private final int size;
private final List<Symbol> listOfSymbols;
public Board(int size) {
List<Symbol> listOfSymbols = new ArrayList<>();
for (int i = 0; i < (size * size); i++) {
listOfSymbols.add(E);
}

this.listOfSymbols = listOfSymbols;
this.size = (int) Math.sqrt(listOfSymbols.size());
this.lines = new BoardSize(size);
}
public Board(List<Symbol> listOfSymbols) {
this.listOfSymbols = listOfSymbols;
this.size = (int) Math.sqrt(listOfSymbols.size());
this.lines = new BoardSize(size);
}
boolean checkWins(Symbol symbol) {
return (lines.checkLineWins(contentsOfBoard(), symbol));
}
public Board markPlayer(int indexPosition, Symbol symbol) {
List<Symbol> newBoard = new ArrayList<>(listOfSymbols);
newBoard.set(indexPosition, symbol);
Object board = new Board(newBoard);
return (Board) board;
}

There are more methods that check the content of the board, but the board is not mutated anymore and a new board object is returned everytime a player makes a move. This has also meant that a copy of the board that was being created in minimax is no longer necessary and so I have removed that.

It is important that the the actual clone method in Java is actually a shallow clone. Which means that if the clone method is called on a primitive, a true copy is made as it is the bits that are changed, but a clone of an object means that any instance variables that are cloned along with it are only copied by their reference and still point to the original location address of the object.

Here is an example, when the firstFruit is cloned as the secondFruit , the banana that is within the secondFruit is the same banana, located at the same memory address.


class Fruit {
Banana banana;
   public Fruit() {
banana = new Banana();
}
 }

Banana firstFruit = new Fruit();
Banana secondFruit = firstFruit.clone();

That is why even though my TicTacToe is not particularly complex and threading is not an issue yet, I have made my board immutable so that when it is used within minimax, it is not necessary to explicitly make a clone, but the board will be cloned every time a new mark is placed on it.