I feel uncomfortable when I see large switch statements. I appreciate how they break the Open Closed Principle. I have enough experience to know that they seem to attract extra conditions & additional logic during maintenance, and quickly become bug hotspots.
A refactoring I use frequently to deal with this is Replace Conditional with Polymorphism; but for simple switches, its always seemed like a rather large hammer.
Take the following simple example that performs slightly different processing logic based on the credit card type:
Its highly likely that the number of credit card types will increase; and that the complexity of processing logic for each will also increase over time. The traditional application of the Replace Conditional with Polymorphism refactoring gives the following:
This explosion of classes containing almost zero logic has always bothered me as quite a lot of boilerplate overhead for a relatively small reduction in complexity.
Consider however, the functional approach to the same refactoring:
Here we have obtained the same simplification of the switch statement; but avoided the explosion of simple classes. Whilst strictly speaking we are still violating the Open Closed Principle; we do have a collection of simple methods that are easy to comprehend and test. It’s worth noting that when our logic becomes very complex; converting to the OO Strategy pattern becomes a more compelling option. Consider the case when we include a collection of validation logic for each credit card:
In this case the whole file starts to feel too complex to me; and having the logic partitioned into separate strategy classes / files seems more maintainable to me.
To conclude then, the fact that languages treat functions as first class constructs, gives us the flexibility to use them in a “polymorphic” way; where our “interface” is the function signature.
And for some problems, like a refactoring a simple switch statement; I feel this gives us a more elegant solution.