Switches are a code smell when used in pure OO code. This doesn't mean they are wrong by definition, just that you need to think twice about using them. Be extra careful.
My definition of switch here also includes if-then-else statements that can easily be rewritten as switch statements.
Switches can be a sign that you are not defining behaviour close to the data on which it operates, and are not taking advantage of subtype polymorphism for example.
When using an OO language, you are not forced to program in an OO way. So if you choose to use a more functional or object-based style of programming (e.g. using DTOs that only contain data but no behaviour, as opposed to richer domain models) there is nothing wrong with using switches.
Finally, when writing OO programs, switches come in very handy at the "edge" of your OO model, when something enters your OO model from the non-OO outside world and you need to convert this external entity into an OO notion. You best do this as early as possible. For example: an int from a database can be converted into an object using a switch.
int dbValue = ...;
switch (dbValue)
{
case 0: return new DogBehaviour();
case 1: return new CatBehaviour();
...
default: throw new IllegalArgumentException("cannot convert into behaviour:" + dbValue);
}
EDIT after reading some of the responses.
Customer.isInvestable
: great, polymorphism. But now you are tying this logic to the customer and you need a subclass for each type of customer just to implement the different behaviour. Last time I checked, this is not how inheritance should be used. You would want the type of customer to be a property of Customer
, or have a function that can decide the type of a customer.
Double dispatch: polymorphism twice. But your visitor class is essentially still a big switch and it has some of the same problems as explained above.
Besides, following the example of the OP, the polymorphism should be on the category of the customer, not on Customer
itself.
Switching on a value is fine: ok, but switch statements are in the majority of cases used to test on a single int
, char
, enum
, ... value, as opposed to if-then-else where ranges and more exotic conditions can be tested. But if we dispatch on this single value, and it is not at the edge of our OO model as explained above, then it seems switches are often used to dispatch on type, and not on a value. Or: if you can not replace the conditional logic of an if-then-else by a switch, then you are probably ok, else you are probably not. Therefore I think switches in OOP are code smells, and the statement
Switching on type is bad OOP style,
switching on a value is fine.
is itself oversimplified.
And to come back to the starting point: a switch
is not bad, it's just not always very OO. You don't have to use OO to solve your problem. If you do use OOP, then switches are something you need to give extra attention.