Law of Demeter and immutability



In this post, we’ll discuss the Law of Demeter in the context of immutability.

Law of Demeter

The law of Demeter is a guideline saying that objects should talk to their immediate neighbours only. For example, if you want your dog to move, you don’t try to control her legs directly:

dog.Legs[0].MoveForward();

dog.Legs[1].MoveForward();

dog.Legs[2].MoveForward();

dog.Legs[3].MoveForward();

Instead, you send her a command and rely on the dog herself to figure out the details:

dog.Move();

This guideline is very similar to the Tell Don’t Ask one. In fact, I personally think they are synonyms and aim at essentially the same thing.

Following this guideline is what we, programmers working with OOP languages, learn to do pretty early. And there’s a good reason for that. It fosters proper encapsulation practices and better code maintainability overall. The situation where the client code manually operates the dog’s legs is a clear leakage of implementation details: in order to achieve a single goal – making the dog move – the client needs to perform not one but four different actions.

The law of Demeter is sometimes said to be the guideline of a “single dot”. That is, you are not allowed to dive into your objects for more than one level of depth. In the first code sample, we are doing exactly that: we first query a certain leg from the dog and then dive deeper into that object by executing a command on it.

Law of Demeter and immutability

In general, we can say that any code that looks like the following violates the Law of Demeter:

A a = new A();

a.B.C();

Alright, but how about this one?

int positionX = player.Position.X;

Here, the player has a position on a map which is represented by an immutable data structure, and we request the X portion of it. Does this code violate the law of Demeter too? It does because the property X is not an immediate neighbor of the Player class.

At the same time, your intuition most likely tells you that there’s nothing wrong with this particular code sample. It’s definitely better than having all members of Position duplicated in the Player class itself:

int positionX = player.GetPositionX();

int positionY = player.GetPositionY();

/* etc */

So, what is going on here? Is our intuition failing us? Or maybe there’s something wrong with the guideline?

To answer this question, we need to step back and look at the goal the law of Demeter aims at achieving. The main goal here is to assure proper encapsulation. That is, to make sure that the state of the object can only be changed via its public API.

In the example with the dog and her legs, we modify the dog’s state not through an explicit API on its class but via accessing its sub-objects and messing up with them directly. That is a horrible thing to do because such changes can potentially violate the class’s invariants. For example, one of the invariants might state that all four legs should move in the same direction only. However, there’s no way the Dog class can enforce this invariant because it doesn’t have control over how the clients work with its legs.

The key point here is state. That is data that changes over time. We need to make sure that this data is modified correctly and not get corrupted along the way. Basically, all best practices related to encapsulation aim for this exact purpose: to guarantee that any existing state is properly maintained and no invariant is violated during state mutations. When you follow the law of Demeter, it is much easier to accomplish this goal as all changes related to a class go through this class directly and thus can be easily validated.

Now, let’s look at this code sample again:

int positionX = player.Position.X;

Is it somehow different from the example with the dog and her legs? It is. The data structure behind the Position property is immutable, and that means it’s safe to expose it directly as we do in the sample above. The client code is unable to mess up with the position’s internal state because it simply doesn’t have any.

Note that state is not just data that belong to some class, it is subset of that data that changes over time. In that sense, immutable classes don’t contain any state, only mutable classes do.

So, the conclusion here is the following: the law of Demeter is not applicable to the world of purely functional (immutable) data structures. In functional programming, everything can be (and usually is) made public for that exact reason: you don’t need to ever worry about state and its corruption because it’s impossible to corrupt something that cannot be changed in the first place.

Here’s a great quote from Michael Feathers with that regard:

OO makes code understandable by encapsulating moving parts. Functional programming makes code understandable by minimizing moving parts.

Does it mean we can write code like this?

A a = new A();

a.B.C();

Or even this?

a.B.C.D.E.F.G();

If all of the members in this chain are represented by immutable classes then yes, we can definitely do that. That’s the essence of functional programming: as long as all your data is immutable, you can do whatever you want with it, be that making all its members public or querying portions of it in this weird way.

Make sure that you don’t duplicate domain knowledge, though. The Dry principle is applicable regardless of the paradigm you choose to program in. In OOP, this place is usually the class that owns the data. However, it doesn’t have to be that way as you don’t need to enforce any invariants in this case. So you can very well separate the data from the code working on that data.

UPDATE

Just wanted to make a remark regarding coupling. Coupling is another important concept of course, but it can be mitigated by following the DRY principle. That is, if you have only one function that knows about the object’s internal structure (“couples” to it, so to speak), it doesn’t really matter where exactly that function is located – in the class itself or in some other place.

Summary

  • The law of Demeter aims at ensuring that all class’s invariants are honored during its state mutation.
  • The law of Demeter is not applicable in scenarios with immutability because there’s no way the internal state can be corrupted.
  • We can dive as deep into the class’s internals as we want as long as all data we work with is immutable.

Related articles

Share




  • Amir Shitrit

    Immutability prevents state corruption, but what about coupling?

    • http://enterprisecraftsmanship.com/ Vladimir Khorikov

      Good point, indeed, writing a.B.C.D.E.F.G() can lead to high coupling. I don’t think it’s always the case, though, need to examine each case separately.

      • SiGMan

        Lenses could help here. They are composable after all

    • http://programmingideaswithjake.wordpress.com Jacob Zimmerman

      Agreed; the law also helps to prevent coupling.
      It also generally ends up with more readable code. Always be second guessing yourself when including more than one dot.

      • http://sidburn.github.io/ David Raab

        If it really prevents coupling is debatable. In a lot of cases i would say, no. But the fact that it increased readability is a clear “no” to me.

        Consider two classes A and B with three methods each. Now you create a new class C that also have 3 methods and uses A and B. This now means you end up with 9 methods, 6 of them are probably just delegates to A and B.

        Creating such methods that only delegates to another object a cleary code for the idiots. It is boilerplate and the code pretty much has no meaning at all. It is the same stupid code as Getter/Setter that Java developers are still writing. An increase of stupid boilerplate code, that pretty much does nothing is exactly the opposite of “readable” code. You pretty much have more boilerplate code and it gets hard to see which method does not just delegate.

        The fact is even that the amount of delegation method you have to write increases the more code-reuse you have. If you create another class D with 3 methods that uses A, B and C, you end up with 12 methods, 9 of them are just delegates.

        If you ignore the Law-of-Demeter you don’t need to write any delegate method. And i also don’t think we need to debate that:

        obj.Position.X

        is the same readable then:

        obj.PositionX

        • http://programmingideaswithjake.wordpress.com Jacob Zimmerman

          It reduces coupling in scenarios like with the dog. Anyone trying to make the dog walk has to know all about the legs. If, for some reason the dog’s leg implementation changes, all the code that uses the dog’s legs needs to change. By leaving the dog in control of its own legs and simply telling it to walk, you reduce coupling.

          In this same way, it increases readability. Looking at the code that tells each leg to move isn’t as readable as the call to Move().

          I notice that you’re thinking more along the lines of the later example, which is fine. Now I’ll address that. If you have a C that uses A and B, who is to say that anyone else needs to use A and B? C only needs the methods that it needs to work. Generally, you’ll want to limit C to a smaller instruction set than the 9 methods. It may only need the 3, or it may need a few more to emulate parts of A and B, but rarely will EVERYTHING from A and B be needed. By restricting functionality, you may be protecting invariants.

          Plus, again, if C changes to not use A or B, then code that is “using C” needs to be changed. Keep all of that within C, and you’ll have fewer problems.

          As for readability, those methods that DO delegate can often be renamed to something more specific and meaningful. For example, if you’re making a Stack class that uses a List on the inside, instead of just using Add() on the List, you can rename it to Push().

          In many cases where an outside class wants to directly access internal data, it’s the wrong thing to do. That use that needs access should be a method on the outside class. See Michael Martz’s comment below.

          Now, there’s a common caveat to this: DTOs. Simple, immutable data objects are just fine for breaking this rule. But those data objects aren’t supposed to be the rule; they’re the exception. They’re only meant for passing data around. That data isn’t supposed to be “used” so much as displayed or stored.

          Check out Object Calisthenics (https://www.cs.helsinki.fi/u/luontola/tdd-2009/ext/ObjectCalisthenics.pdf) Rule #9 (and 8, which kind of leads into 9).

          Strict adherence to the Law of Demeter and Object Calisthenics can often bloat your class count and make some parts more difficult, but generally following them tends to make your code better.

          • http://sidburn.github.io/ David Raab

            > Anyone trying to make the dog walk has to know all about the legs.

            No, having access to the legs doesn’t mean you stop creating useful methods like Move(). You still create dog.Move() methods, and additionally you still can access legs. If the legs are immutable this also isn’t a problem.

            Your assumption is somehow, that with access to the legs you stop creating a Move() method. What is silly, nobody said or proposed that.

            > By restricting functionality, you may be protecting invariants.

            With immutable objects you don’t run in that problem in the first place. Lets’ consider the example again. You create C and only create the additional methods it needs.

            If you follow the law-of-demeter, you still have to explicit delegate those methods you need. It’s probably not 6, maybe just 2. But the exact amount isn’t that important. The more high-level an object and the more functionality you have, the more functionality you end up with delegating.

            Ignoring the law-of-Demeter means, you still have the same functionality, you probably don’t need to create delegates methods. And there is also no problem if a developer gets full access to all and every methods.

            It is not a problem because an object is immutable so its invariants are always protected. With an immutable object you only need to check for all invariants if you create an object.

            In the dog case you mentioned. By creating a dog, the dog checks if all legs are valid. There is no point in restriction access to the legs, because the dog anyway cannot change after its creation.

            > Plus, again, if C changes to not use A or B, then code that is “using C” needs to be changed. Keep all of that within C, and you’ll have fewer problems.

            That so far is the only kind of coupling that is true and i agree with. But the more important thing is to consider if that is bad or not.

            If we have a Person and Person delegates all methods its need to Position. Yes it means code that uses a Person only needs to depend on Person, and there is no coupling on Position.

            The point is, that this is not automatically better. If you create a Minimap that needs to display a symbol on a position. If you create a Path-Finding algorithm that need to calculate a path from a starting position to its end position, or you have network code that synchronizes a position between multiple player over network, then you really want to write code that depends on “Position”. You don’t care at all if that Position is attached to a “Player”, “Enemy”, “HealthBox” or whatever you have.

            You want to write code that give a start and end position, and it gives you a path of positions back. You want a minimap that you just give a symbol and a position, and it shows an icon on a minimap.

            If you don’t have access to the Position. Then it means you need to create special version for all kind of combination. And you definitely don’t want to write 12 times a path-finding algorithm that can work on the various objects.

            What you want is just stuff like:

            var path = shortestPath(player.Position, enemy.Position)

            > As for readability, those methods that DO delegate can often be renamed to something more specific and meaningful.

            Yes, sometimes that makes sense. And you can still do that. Note the difference. The Law-of-Demeter says you *always* should delegate stuff, and never ever should access attributes directly. Everything needs to be protected, everything needs to be closed otherwise invariants of objects can be ruined.

            What i’m telling and I also think Vladimir says. If you anyway have immutable objects the invariants anyway cannot be ruined. Because of that, you don’t need to follow the Law-of-Demeter strictly. There is nothing wrong on accessing attributes.

            If you think creating a delegate method is better because it has more meaning. Nice, then create a method. The point is you create those methods because you think it can increase readability. You don’t create such a method just blindly because a stupid rule tells you to do it.

            > In many cases where an outside class wants to directly access internal data, it’s the wrong thing to do. That use that needs access should be a method on the outside class. See Michael Martz’s comment below.

            Michael Martz comment is btw. a great post that describes why you should give access to internal data. In that sense his comment doesn’t make much sense to me, as he thinks he writes against this idea.

            > Strict adherence to the Law of Demeter and Object Calisthenics can often bloat your class count and make some parts more difficult, but generally following them tends to make your code better.

            I check it out, and i hear sentence like yours often. And it doesn’t make much sense. If the smallest part is already hard or more difficult, then it cannot be that everything you build on top of it becomes easier. Chances are, everything on top of it will only become harder and more complex.

            Lego is so successful because it was simple. It only had 3-4 different building blocks. And stacking those together is easy. That’s why you can create different structures or building a house is easy.

            If you had 200 different building blocks and stacking two pieces together would be hard as hell. Chances are you will never build a house.

        • http://programmingideaswithjake.wordpress.com Jacob Zimmerman

          Nvm what I wrote below. You’re anti-OO, so everything I say there will just frustrate you.

    • http://sidburn.github.io/ David Raab

      If your data is immutable and you separate data and behavior, you also don’t have any coupling. What increases/decreases coupling is not immutability, objects with behavior/methods increases coupling. So if you don’t want any coupling, you must drop OO.

      http://mergeconflict.com/coupling-in-object-oriented-programming/

      • Amir Shitrit

        If you have a deep structure hierarchy that might require to do A.B.C.D…. and you get coupling between the data and behaviour and I can’t see how immutability and data/behavior separation can help here.
        Consider the case in which you need to flatten B and have:
        A.B.C and A.B.D. now you need to change your behavior, which is something you could’ve have avoided by “not talking to strangers”.
        Not that i think that all coupling is evil, but in many cases it is.

  • http://www.jacopretorius.net Jaco Pretorius

    I would argue that in your example – ‘int positionX = player.Position.X;’ the real question is why do I need to know the x of the position? What am I trying to do what that information? If you really need access to the internals maybe the modeling is incorrect…?

  • http://programmingideaswithjake.wordpress.com Jacob Zimmerman

    I’m surprised that you didn’t givw the formal definition of the Law of Demeter

  • Raj Adigopula

    My understanding – Law of demeter is postulated for OOP and is only applicable to OOD.

  • Michael Martz

    I’d suggest that actually, the code int positionX = player.Position.X has some potential problems with it. The real question is why are you getting the x value of the player position directly?

    One example I can think of is to check for collision with another object, but in that case you don’t actually want to check individual components of the position, you want to compare the position of two objects. In that case you’d be better off either just using the Position object, or adding a method to the player to check for collisions.

    Another example might be to disallow the player from moving outside of some bounding box. To do that check you do need to check the x and y position of the player, but the code should be rewritten to not rely on the player object. Instead you should have some function that takes a position, some bounding conditions, and returns a boolean indicating if the entire position is within the bounding conditions, or perhaps a vector representing the correction to apply.

    My point is, there is likely a better way that player.Position.X and immutability of the position has nothing to do with it. Instead you need the full context of it’s usage to decide if the Law of Demeter applies.

    • http://enterprisecraftsmanship.com/ Vladimir Khorikov

      You could do that to draw the player on the map, for example. Drawing has nothing to do with the player’s responsibilities, so passing the canvas to the player wouldn’t be an option here.

      • http://programmingideaswithjake.wordpress.com Jacob Zimmerman

        The drawing part wouldn’t need the full class, though. Give it the Position and whatever other necessary data directly, instead of the entire Player.

        • http://sidburn.github.io/ David Raab

          Yeah exactly. So it makes sense if you can directly access the position of a player and pass it to the drawing routine.

          This is pretty much the reason why giving access to the position isn’t bad. For example if the Minimap just have a draw method you could call.

          minimap.DrawSymbol(player.Position, playerSymbol);

          This would mean player has no coupling with minimap, and minimap is also not coupled with Player. Giving access to Position directly and ignoring the Law-of-Demeter pretty much reduced coupling.

          Sure Minimap depends on Position, also Player depends on it. But that is anyway a valid coupling, because both needs Position so it can work. Doesn’t make much sense to eliminate the coupling on Position here.

          If you don’t have access to player.Position. It means you would end up with either:

          minimap.DrawPlayer(player)

          and the minimap object depends on the player. Or you could put the code inside the player.

          player.DrawOnMinimap(minimap)

          In this case player depends on Minimap. Coupling anyway exists. But in this case you have a coupling that doesn’t make any sense. There is no logical reason why Player should depend on minimap or Minimap depends on Play. It also has another problem that it is also not clear where to put the method. None of those seems more correct. In fact they both look wrong.

          Btw. one way out of this mess would be a static method. Something like:

          MinimapHelper.Draw(player, minimap)

          A static method that just expects both objects and do the right thing with both. But neither Player nor minimap are coupled with each other.

          But if you anyway have access to the Position of Player directly, you don’t run into any problem in the first place. Neither do you need a static method nor do you end up with any coupling between two classes that shouldn’t depend on each other.

          All the use-cases that Michael Martz describes are best solves by not following the Law-of-Demeter.