Ever since high school, I have always been suspicious when it comes to the switch statement in programming. It is quite intuitive if you think about it, but in my opinion it has various limitations in some scenarios:
- it’s error-prone by missing a break; clause here and there
- chaining cases isn’t always intuitive to read, in addition to the break; thing
- different languages have different rules for switch – such as the allowed switch types for input variables (Java used to disallow strings at all), objects, and especially what could be put in each case
There are a few more, but that’s the gist of the issue.
Nikolay Bachiyski had a great talk at WordCamp San Francisco last year covering analogies for development to writing and thinking, where he mentioned the following:
if clauses are real evil
He explained ifs as a feature not being standard to the brain while people think in practice, and due to the fact that the brain understands pattern matching and can’t handle branching that well. Switch statements are pretty handy with simple data, such as numbers and enumerations. I would normally avoid them when it comes to strings, arrays and objects (not that arrays are supported in a switch statement) and go for the “if“.
Getting back to the first three issues I have with switch, let’s see how wp-admin/comment.php looks like in WordPress 3.7. The $action switch takes more than 250 lines of code to process different use cases for the comments screen in the admin page. It expects a certain amount of actions, predefined in core.
When I need to support another action on that screen (in a plugin), I start asking various questions:
- Where should I add that action support?
- Can I filter it somehow?
- Can I reuse any of the code for the other actions?
- Can I abstract anything or reuse it anywhere else?
I could definitely relate to other code related concerns as the lack of abstraction of the code in each case, but being in a switch statement makes it even harder for me to suggest or expect a pre/post filter/action for that. And even if I had one, it would be a completely separate switch that has nothing to do with our first pattern, implemented originally.
Even when it comes to numbers, a sample from suggest.js:
[javascript]
switch(e.keyCode) {
case 38: // up
prevResult();
break;
case 40: // down
nextResult();
break;
case 9: // tab
selectCurrentResult();
$results.hide();
break;
case 27: // escape
$results.hide();
break;
}
[/javascript]
The snippet takes care of executing different actions based on a pressed key. What if we need to manage other actions too, or change these? They couldn’t be extracted in the functions themselves, because the functions are not related to a given case (they are decoupled in the best possible way). Cases are not filterable again, and any possible filter of the key would be in another switch too.
One might argue that using “if” would lead to similar issues. I suppose that is a subjective matter, but my personal experience is that switch is often overused for branching where it has no place for building extendable applications. I would go with switch for sample cases such as days of week or fixed number of colors, and pick if-else based conditionals for the rest.