Refactoring Switches Advanced
KevDog posted a question in response to my post about refactoring switch statements, Pulling out the Switch: It’s Time for a Whooping. I thought it would be good to go ahead and answer it as a post since it is a pretty interesting real world example of a somewhat difficult switch statement to get rid of.
Here is the original code:
Surprisingly simple solution
Try and say that 3 times fast.
I thought about this a bit and at first was having a hard time coming up with a solution. Then I typed the code into an editor and realized how easy it is.
The trick here is that it looks like something other than the simple case of data mapping to logic, but it isn’t.
- The logic in this case is the creation of the Parser.
- The data is the file type.
Once you think of it in those terms you can easily solve it using the pattern I mention in my previous post on refactoring switch statements.
Switch be gone!
That is the quickest solution that preserves the existing code as much as possible.
With the first solution we pushed the object creation into the map.
If we can make the constructor for all the parsers the same, we can use reflection to dynamically create our instances by looking up the type in the dictionary.
In this example, I assume that we have refactored CsvParser to have a constructor that only takes one parameter and internally sets a value of usesHeader to false, and we have created a CsvWithHeaderParser that inherits from the CsvParser and sets usesHeader to true.
Pretty similar solution. I prefer the first though for several reasons:
- The refactor is localized, where the second solution has to touch other classes.
- Reflection makes you lose compile time safety.
- You may create a new parser that you want to have more parameters for the constructor. With the second solution, you will have a hard time doing that.
- The first solution gives you ultimate flexibility in setting up the constructor of the parser. If you wanted to do 5 steps for a particular parser, you could.
Anyway, next time you try refactoring switch statements that are hard to figure out how to refactor, try to break it into a mapping between data and logic. There is always a solution.