DEV Community

Discussion on: I've never become overly convinced that switch statements are that much cleaner than `if else if else if else if else`

Collapse
 
samuraiseoul profile image
Sophie The Lionhart • Edited

Switches as well as conditionals with many branches(else ifs) are generally indicative of a different issue all together.

Switches can be a good choice in the case of a clearly defined unchangeable list of things to check against, like days of the week(I pray to god there will only be seven in the future too). They are also sometimes good in the case that you actually have found a use case for the fall through effect you get when you don't use a break. Switches also are very hard to do in a way that enables defensive programming. It's easy for a switch to have 4 or 5 cases, then someone comes in and adds one, comes in and adds another, then another, until you have a giant mess of cases.

Generally, like @rossholloway94 mentioned, Enums are a much better fit. The way that @0xrumple showed in python can be done in many other languages that don't have real Enums, but is essentially an Enum as well. Alternatively, in certain use cases, something like a rule matcher and handler can be a better fit.

class Foo implements RuleHandler {
    public function canHandle(condition) : bool {
        if(condition === something) { return true; }
   }

   public function handle(thing) : Bar {
        return thing.thing() + thing.otherThing();
   }
}
Enter fullscreen mode Exit fullscreen mode

Using a switch can also be indicative that whatever logic you're doing in the switch, is really something that should be on each class to implement which can be similar to the model above. Basically the Strategy design pattern.

//instead of this
function doThingsThing(thing: Thing) : void {
  switch(thing.val) {
    case 1 { thing.a + thing.b; break; }
    case 2 {thing.a * thing.b; break; }
    // more cases
    default { //this should never happen }
    // NEVER DO THIS TO A DEFAULT IF IT SHOULDN'T HAPPEN THROW AN ERROR
  }
}

//this
function doThingsThing(thing : Thing) {
  thing.doThing();
}

abstract class Thing { abstract function doThing() : Thing; }
class Thingy extends Thing { function doThing() : Thing {this.meh = 2; return this; } }
class OtherThingy extends Thing { function doThing() : Thing { this.meh = this.meh * 2; return this; } } 
Enter fullscreen mode Exit fullscreen mode

The reason a switch never feels better than many else ifs is because they are basically the exact same thing. The kind of feel that gets hammered in a lot of beginner tutorials that explain switches is something like "If you have a lot of conditions, use a switch!" and also the examples show how to convert a thing with a lot of else if statements into a switch.

One more time for clarity:

  • Consider using an if in the case that:
    • There are a TRULY finite number of cases
    • The fall through logic will really help(though there are OOP ways of handling this too that I didn't show)
  • Some switch alternative candidates are:
    • Enums
    • Rule Handler matchers
    • Interfaces in classes
Collapse
 
eerk profile image
eerk • Edited

Excellent point! Sometimes you may need lots of if statements, but more often than not, lots of ifs are a sign that your code is just too procedural. By abstracting away code in functions or classes you can often get rid of them.

Collapse
 
yaser profile image
Yaser Al-Najjar

Enums are also good, but they might not fit in cases where there is no ordinal values.

Don't get offended, but the rule handler matcher / OOP ways to return a value reminds me of this meme:

deep-learning

Collapse
 
samuraiseoul profile image
Sophie The Lionhart • Edited

Haha no offense at all. The rule handler is overkill in A LOT if not most scenarios. That said, it's for sure one of the patterns you would use instead of a switch so I included it. For the trivial example I have though, yeah way overkill. For the slackbot I made a while back I used it and it worked well. github.com/samuraiseoul/starbot/bl... and github.com/samuraiseoul/starbot/bl... are an example where it works well.

Thread Thread
 
yaser profile image
Yaser Al-Najjar

Aha... Heck yeah, this example is pretty solid 👌