Skip to main content

Switch Statement Smell

The Switch Statement Smell is type-code branching duplicated across the code, where each new kind forces edits everywhere. Replace it with polymorphism or strategy objects so each kind owns its behavior and extension means adding a class.

The Switch Statement Smell is the recurring use of switch (or long if/else if chains) that branch on a type code or kind field — and, crucially, the same branching logic appearing in many places. Each time a new kind is added, every one of those switches must be updated, and any that is missed becomes a bug.

Why It Happens

Branching on a type field is the most direct procedural way to vary behavior: 'if it's a circle do this, if a square do that.' It works fine for one switch. Trouble starts when behavior for the same set of kinds is needed elsewhere (area, perimeter, draw, serialize), so the switch is copied and adapted. The kinds and their behaviors are now spread across the code instead of grouped by kind.

Why It Hurts

Adding a new kind requires editing every duplicated switch — classic shotgun surgery — and missing one produces silent wrong behavior or a fallthrough into a default case. The behavior for a single kind is scattered across many switches rather than living in one place, so understanding 'what a circle does' means searching the whole codebase. The design violates the open/closed principle: you cannot extend behavior without modifying existing code in many spots.

Warning Signs

  • The same switch on a type/kind field appearing in several files.
  • Adding a new case means editing many locations.
  • default cases used to catch 'forgot to handle this.'
  • Behavior for one kind scattered across multiple switches.

Better Alternatives

Replace conditional branching with polymorphism: give each kind its own class and let each implement the varying methods, so the runtime dispatches automatically and there is no switch. The Strategy Pattern does the same for pluggable behaviors. This satisfies the Open/Closed Principle — adding a kind means adding one class, not editing many switches. (Note: a single, localized switch — for example mapping input to the right polymorphic type at a boundary — is fine; the smell is duplication of type-code branching.)

How to Refactor Out of It

Apply Replace Conditional with Polymorphism. Introduce a common interface for the kinds, create one class per kind, and move each switch branch's body into the corresponding class's method. Replace each duplicated switch with a polymorphic call. Concentrate any remaining 'which kind is this' decision into a single factory at the boundary. With the cases gone, adding a kind becomes a single new class. Add tests per kind to confirm behavior moved correctly and that no scattered switch remains.