Refactoring: Creating an abstract parent

I have been implementing MiniMax in Java for my TicTacToe game. Once I had this up and running, I wanted to add Alpha Beta pruning, which makes the MiniMax algorithm more efficient. Whilst I will try to summarise the details of how I implemented Alpha Beta pruning and why its faster in a future post, today I wanted to run through how I refactored my two concrete classes into two abstract classes.

Because Alpha Beta Pruning is an optimisation of MiniMax rather than a new algorithm, I started by copying my MiniMax class to a new AlphaBeta class and then adding the optimisation to it. Once completed, I then had two different classes which shared a similar structure but had some different implementations. There was clear code duplication, which is a code smell, so I decided to refactor both classes to use the same parent class, which could hold all the shared properties and methods. Because this parent class could not work alone, I knew it needed to be an abstract class.

Here’s how I did it:

Step 1: Renamed MiniMax to SimpleMiniMax (as I wanted the Abstract parent class to be called MiniMax, which is the name of both concrete implementations underlying algorithm).

Step 2: With my cursor in the AlphaBeta class, I selected Refactor > Extract > SuperClass.

Step 3: In the dialogue box, I selected all the properties and methods I wanted to pull up from AlphaBeta to the MiniMax abstract class: which were all the properties and methods directly replicated in AlphaBeta and SimpleMiniMax. I then selected all methods which had the same signature in the two concrete sub-classes but had different implementations and made them abstract methods.

Step 4: Ran the tests and checked that AlphaBeta was still working, which it was.

Step 5: Made SimpleMiniMax inherit from MiniMax as well, then deleted out all methods from SimpleMiniMax already implemented in MiniMax, and add ed @Override annotations to the methods which were implementing abstract methods.

Step 6: Re-ran the tests, which showed that I needed to change some of the methods from private to protected (so that methods in the super-class could be called from the sub-class), which solved the problem.

Step 7: Reviewed the two concrete classes and notices further duplication between the two classes, so used Refactor > Pull members up to move the shared functionality up into MiniMax.

Step 8: Final re-run of the tests to make sure everything is working.

And that’s it. There were a few quirks, such as IntelliJ changing the order of the arguments to the class constructor. There were also some optimisations that I couldn’t work out how to do: in particular how to refer to the current sub-class to create a new instance of it in the parent class (which would avoid some code duplication). Overall though, I think this shows the power of IntelliJ in helping make refactoring easier.

Like what you read? Give Matthew Glover a round of applause.

From a quick cheer to a standing ovation, clap to show how much you enjoyed this story.