Dariusz Mydlarz

Dariusz Mydlarz

Software Craftsmanship, Project Management & Productivity

QR code

Switch Case Should Be Banned

  • I believe that switch-case construction is overused.
  • Every time you branch execution depending on switch-case you’re doing something wrong.
  • Instead of that you should move the logic into classes and rely on polymorphism.
July 15, Chełmek, Wedding Party
July 15, Chełmek, Wedding Party

I believe that Switch-Case construction is overused. I would call it a goto of nowadays. The truth is that it is convenient to control code execution on switch-case. But they same history was about goto. It was convenient in those days when it was not considered harmful. But it was convenient rather because of our lack of better code structure than the powerfulness of instruction instead.

Why the goto instruction was dumped so much? Cause it was unmaintainable in the long run. And I believe the same story is behind switch-case. It is unmaintainable when codebase grows.

Every time you control execution with switch-case construction it’s an indicator you’re doing something wrong. Most probably logic you’re trying to perform can be moved into specific classes instead.

The most important advantage that comes with OOP & static-typed languages is that in the case of mistakes it fails at compile time. For instance, you cannot pass a String to a method that accepts Integer. And by that, you don’t have to check what has been passed - which makes you more productive. But at the same time when you use switch-case, you just throw that advantage away. Consider following code.

public Painting draw(Child child) {
  switch(child.name()) {
    case "Anna":
      return new HorsesPainting();
    case "John":
      return new CarPainting();
    case "Susanne":
      return new FamilyPainting();
    default:
      throw new IllegallArgumentException(
        "Painting not found for: " + child
      );
  }
}

What happens when the method will receive a child with a different name than provided? It will crash with an exception. It is very likely that it will happen into user’s face cause you will forget to add a new switch branch when providing a new child into the system.

And now you have two options. Either let it go - and make users anger - or just write tests for every option. But it’s the same case as in JavaScript. Instead of focusing on delivering new features, you have to write a lot of specs to make it doesn’t break on corner cases (like passing a name into a method that expects a number). It is highly counterproductive.

Instead of that the drawing feature should be a part of a child class. And you should not allow getting into a scenario where you have to throw an IllegalArgumentException.

The worst scenario is when you do that branching in multiple places. So instead of having rich classes with all required methods provided, you create a bunch of factories and there you decide what should happen.

For example, you create an enum AttributeType with instances like DateTime, Number, Text and then you create factories like FilterFactory, SearchFactory which builds a part of a system for you based on AttributeType.

class FilterFactory {
  Filter filter(Attribute attribute) {
    switch(attribute.type()) {
      case DateTime:
        return new DateTimeFilter();
      case Number:
        return new NumberFilter();
      // ...
      default:
        throw new IllegalArgumentException("Filter not supported");
    }
  }
}

Consider following code as a counter-example:

interface Attribute {
  Filter filter();
}

The class itself should be responsible for filtering. This way you make your code more cohesive. With switch-case logic, you throw code related to specific types into multiple places. Good luck in maintaining it in a long run.

Making a long story short: I consider switch-case as a smell code. It’s an indicator that your code design is flawed. Try to invert the responsibilities you’re packing into switch-cases and factories. Doesn’t it even sound like an Inversion of Control? Does it? :)