The Law of Demeter and the 9th Circle of Hell

There are ways to make your code a living nightmare to test. Most of them involve tight coupling. To me, there is nothing worse than trying to mock multiple layers of dependencies in order to test some otherwise simple block of code.

Consider the following code:

func doubleSomethingUseful(does: Does) -> Int {
    return 2 * does.something().useful().eventually()
}

class Does {
    func something() -> Something {
        return Something()
    }
}

class Something {
    func useful() -> Useful {
        return Useful()
    }
}

class Useful {
    func eventually() -> Int {
        return 1
    }
}

If I’m trying to test doubleSomethingUseful(), I have to mock an instance of the Does class so that the something() method can return a mock of the Something class. The mock of the Something class has to return a mock instance of the Useful class when the useful() method is called. And, all this so that the mock instance of the Useful class can return some predetermined test value when the eventually() method is called.

Enter the Law of Demeter (or principle of least knowledge.) The general idea is that a class should not expose its dependencies to its consumers. Instead, it should expose the functionality of its dependencies through wrapper methods. This is a form of information hiding. Click here for an in-depth explanation.

Here is what it might look like for my contrived example:

class Does {    
    func somethingUsefulNow() -> Int {
        return Something().usefulNow()
    }
}

class Something {
    func usefulNow() -> Int {
        return Useful().eventually()
    }
}

class Useful {
    func eventually() -> Int {
        return 1
    }
}

func doubleSomethingUseful(does: Does) -> Int {
    return 2 * does.somethingUsefulNow()
}

Notice that now I only have to mock the somethingUsefulNow() method on the Does class and have it return the predetermined test value. I don’t have to worry about any of its dependencies.

In Dante’s Inferno, the 9th circle of hell is reserved for traitors. Traitors are there because “their acts involve betraying a special relationship of some kind.” See more on the Wikipedia article. Let’s not betray that special relationship between objects, keeping the details where they belong.

UPDATE: This post addresses the Law of Demeter, but there is more to properly decoupling code! Click here to learn about Dependency Inversion.