Refactoring Switches to Classes
I’ve talked about refactoring switch statements several times before.
- Switch is Just a Fancy If Else
- Pulling out the Switch: It’s Time for a Whooping
- Refactoring Switches Advanced
I’ve even created a defaultable dictionary for refactoring a switch statement into a dictionary of actions.
This time, I am going to talk about refactoring switches when you have switch statements operating on the same set of data, but have different actions in different circumstances.
First let’s recap
When I talked about refactoring switches before, we were mainly dealing with a single switch statement somewhere in code.
In the case where you have only a single switch statement, or multiple switch statements that do the same thing based on the data, using a dictionary is still a great way to go.
However, there are going to be circumstances where you are going to be switching on the same data, but in different contexts. In these cases, you will want to perform different actions.
Let’s look at an example.
In this example, we are switching on the same enumeration, but we are doing it in different locations of the code.
Using a dictionary would not work well here because we would need multiple dictionaries.
We still don’t want to leave this as it is though, because the code is pretty messy and fragile.
Separation of concerns
The problem is the code that contains these switch statements has too much responsibility. It is being asked to handle logic for each one of our character class types.
What we need to do to improve this code is refactor the enumerations into their own classes. Each switch statement will become a method that will be implemented by our enumeration based class.
If we are using Java, we can use Java’s enumeration implementation that allows for methods on an enumeration. If we are using a language like C#, we still have to map the enumeration value to each class.
Let’s start by making our classes.
First we need a base class, or interface.
Now we can create classes that implement this interface, that contain the logic that was in each switch statement.
Next we can map our enumeration to our class.
We could also get rid of the enumeration if we wanted, and just create the appropriate class. It will depend on what your existing code looks like.
No more switches!
Now let’s take a look at what we end up with in the two locations where we had switches.
If we want to add a new character class type, we just add a new class that implements the CharacterClass interface and put a mapping in our dictionary, or in our character initialization code.
If we end up having other places in our logic where different character class types should have different behavior, we just add a method to our CharacterClass interface and implement it in any classes that implement CharacterClass.
Our code is much more maintainable, and easier to understand.