How to Refactor Long If or Switch blocks with Double Dispatch In Javascript

I’m starting this blog so I thought about picking a small and easy topic to write about in the first blog post!

Something to break the ice 🙂

Let’s see…

Have you ever had code with huge logic embedded in if’s and switches? code like this?

class Board {



    drawFigure(aFigure) {
        if (aFigure.type == 'triangle') {
            this.drawTriangle(aFigure)
        } else if (aFigure.type == 'square') {
            this.drawSquare(aFigure)
        } else if (aFigure.type == 'circle') {
            this.drawCircle(aFigure)
        } else if (aFigure.type == 'dodecahedron') {
            this.drawDodecaehedron(aFigure)
        }
        // even more ifs
        // ...
        // ...
        // ...
    }
    drawTriangle(aTriangle) {
        // ...
    }
    drawSquare(aSquare) {
        // ...
    }
    drawCircle(aCircle) {
        // ...
    }
    drawDodecaehedron(aDodecahedron) {
        // ...
    }
}

This is a simplified example so you might consider it ok.
However suppose that apart from drawing the figure on the board we also have other methods that
depend on the figure “type”; let’s say fillWithColor(‘black’,aFigure){…}
Will we really need to repeat the same if logic a second time to account for each figure type?

That can get messy pretty quickly…

Well, there is a pattern (some people don’t consider it a pattern) for these cases that you can choose.

It’s called double dispatch.

It goes this way

class Board {

    drawFigure(aFigure) {
        aFigure.getDrawnOn(this)
    }
    drawTriangle(aTriangle) {
        // ...
    }
    drawSquare(aSquare) {
        // ...
    }
    drawCircle(aCircle) {
        // ...
    }
    drawDodecaehedron(aDodecahedron) {
        // ...
    }
}

class Triangle extends Figure {

    getDrawnOn(aDrawableSurface) {
        aDrawableSurface.drawTriangle(this)
    }
}

class Square extends Figure {

    getDrawnOn(aDrawableSurface) {
        aDrawableSurface.drawSquare(this)
    }
}

class Circle extends Figure {

    getDrawnOn(aDrawableSurface) {
        aDrawableSurface.drawCircle(this)
    }
}

class Dodecahedron extends Figure {

    getDrawnOn(aDrawableSurface) {
        aDrawableSurface.drawDodecahedron(this)
    }
}

The magic is on the getDrawnOn method.

That function call corresponds to the first of the two dispatches in double dispatch.
The second one is the corresponding drawCircle(this) or drawTriangle(this) or drawWhatever(this).

By using double dispatch we can then replace all our if logic with only one function call and some reification of our figures in classes.

In particular, this reification of our figures in classes also leaves us with better code. More suited for testing purposes, clarity and legibility.

Double dispatch is one of the advantages that you get with polymorphism.
In our case Circle, Triangle, Square, etc… are polymorphic with respect to getDrawnOn

Beware, double dispatch must be implemented with care since it quickly leads to a big amount of indirections in the code which can also get messy.

In conclusion, have this pattern in mind and consider if it’s worth using it. As we all know, there is no silver bullet.

Leave a Comment

Your email address will not be published. Required fields are marked *