3 ms·
As someone who has migrated between heavy use of these patterns in the past (object -> switch), I'd like to provide a few counterpoints. First, and this is mor
by ricardobeat 8y ago
As someone who has migrated between heavy use of these patterns in the past (object -> switch), I'd like to provide a few counterpoints.
First, and this is more of a general observation for any kind of programming content, these pompous-sounding abstract value judgements need to stop:
1. Is more structured.
2. Scales better.
3. Is easier to maintain.
4. Is easier to test.
5. Is safer, has less side effects and risks.
Regarding `switch`, only the last is a fact and that's because of the `break` statement peril. Still there aren't really side effects or other 'risks' involved. Everything else is completely subjective and not supported by the examples above - I, for example, find switch easier to maintain as you don't need to juggle variables defined outside the object to keep it clean.
Second, these articles use innocuous examples that don't reflect real use cases, and hence fail to demonstrate their utility. You'll find a ton of switch statements in any kind of parser since it's the perfect construct for the occasion where each branch can wildly differ in content and complexity, and might embed flow control that would complicate the object-based version:
switch (node.type) {
case "Identifier":
case "ObjectPattern":
case "ArrayPattern":
break
case "ObjectExpression":
node.type = "ObjectPattern";
for (var i = 0; i < node.properties.length; i++) {
...
}
break
case "ArrayExpression":
...
}
Finally, `switch` is wonderful when paired with `return`, since it eliminates point 5 above. Sample taken from a project I have lying around:
switch (unit) {
case 's': return value * 1000;
case 'm': return value * 1000 * 60;
case 'h': return value * 1000 * 60 * 60;
case 'd': return value * 1000 * 60 * 60 * 24;
default : return null;
}
With the key lookup, you'd also end up precomputing all of those values (imagine that's a slightly more expensive operation than simple math), or turning each one into a function. Another good example is the state reducer pattern:
switch (action.type) {
case 'ADD':
return state.concat(action.payload);
case 'REMOVE':
return state.filter(item => item.id !== action.payload.id);
default:
return state;
}
The key lookup pattern can hold its own in the simple cases, but it's hard to justify it with anything more than stylistic preference.
- kaizendad 8y agoThis is exactly correct. The cost of holding the entire object in memory, for any significantly complex statement, is going to add up quick if you're dealing with large numbers of users/pageviews/etc. The cost of pre-calculating everything in the object for any complex math similarly gets large when you're dealing with something large-scale. Early returns matter a lot with scale, and make [code line of sight](https://medium.com/@matryer/line-of-sight-in-code-186dd7cdea88 https://medium.com/@matryer/line-of-sight-in-code-186dd7cdea...) much clearer -- which matters a lot of if your team scale is larger, as in many companies that might have multiple teams working on one shared codebase.