Law Of Demeter Is Hard To Understand

If you find LawOfDemeter hard to understand maybe LawOfDemeterRevisited makes more sense.


[Moved from LawOfDemeter]

The arguments here are wrong. The arguments here propose that

   x.y().z()
is not valid according to LawOfDemeter, but:
   Y y = x.y();
   y.z();
is valid. Both are invalid according to the LawOfDemeter. In fact even:
   z( x.y() );
is invalid according to the LawOfDemeter. Also note how hard it is to produce valid code according to this law.


My problem with the LawOfDemeter:

On another page I posted this code:

 edgeGroups.add( edge.getDirection().combine(edges) );
and StevenNewton refactored it to this to obey the LawOfDemeter:

 edgeGroups.add(combine(edge.getDirection(), edges));
IMHO the code is now harder to read. It makes more sense to say "get the direction from edge and ask it to combine edges" than "get the direction from edge and combine it with edges."

In other words, whenever you access a "forbidden" (as per LOD) reference you can always refactor to complying code by adding one more method, where you pass that reference to make it a parameter and therefore LOD compliant. Oh, boy.

In my understanding of the LOD, a correct refactoring would be:

 edgeGroups.add( edge.combineInSameDirection(edges) );
-- NatPryce

It might be correct re LoD, but it means that combining Edges is now Edge's responsibility instead of Direction's. That decision shouldn't be driven by LoD, but by the cohesion exhibited in combine()'s implementation. If I remember correctly, combine() didn't reference a specific Edge. It determined the combination of a set of Edges based on a specific Direction. -- EH


After just recently studying Law of Demeter and getting involved in discussions in a Usenet newsgroup, I have come to the conclusion that there is a logical fallacy in the arguments for it which is a form of affirming the consequent. One of the claimed benefits is that Law of Demeter reduces dependency among classes. I think it is true that software with lower class dependency will be more compliant with the Law of Demeter. In logic terms, this can be expressed as:

lower class dependency -> compliance with LoD
The fallacy is that proponents for Law of Demeter are claiming that the reverse is also true, namely that:

compliance with LoD -> lower class dependency
That implication does not appear to be true. Imagine if I had a method that had a line like this:

myMember.a().b().c().d();
That violates Law of Demeter. But I can make it comply with Law of Demeter simply by shuffling things off to another method on my object as in:

invokeD( invokeC( invokeB( myMember.a() ) ) );
This does not violate Law of Demeter, but has not reduced dependencies among classes one iota.

As I understand it, this does violate the LoD. You're still invoking b() on the object you got from the call to a(). How does it matter in which method you do it? -- DanielBrockman

The conclusion that Law of Demeter is an indication of software quality seems to be quite flawed to me. In almost all cases where it is presented you see an example where they make a correction in such a way that it does improve the software, but there are ways to achieve Law of Demeter compliance and make the software worse.

I would agree that Law of Demeter violations is a code smell and that can be an indication that there is a better way to do things. The problem is that lack of Law of Demeter violations does not mean that code doesn't stink as it is easy to apply a code deodorant.

-- Dale King


As I understand it, this does violate the LoD. You're still invoking b() on the object you got from the call to a(). How does it matter in which method you do it? -- DanielBrockman

Because the Law of Demeter allows code to call methods on arguments passed to the current method. If you want to call a method on an object that wasn't passed as an argument to the current method you can always create a new method and pass it that object. This renders the Law of Demeter meaningless as commonly formulated.

I find the whole notion of classes being "close" to one another bothersome. Proximity is important in real machines (see the trouble it takes to plot a trace from one end of a circuit board to the other, or to connect a rod from one end of an engine to the other), but one of the main advantages of imaginary machines is that everything can be equidistant from everything else without interference. The relationships between parts exist in as many dimensions as we want, allowing us to connect anything to anything else as needed.

I'd rather focus on clean interfaces, AlternateHardAndSoftLayers, ShearingLayers and things like that. The Law of Demeter sounds like superstition to me. -- EricHodges


Does this law have anything to do with the idea that, say, if you have a lot of objects in your program you should organize the way that they communicate with each other so that the objects are somehow 'layered'. You shouldn't just let any given object communicate with any other given object, each object should only communicate with its immediate neighbours..... or am I completely missing the point ;-P

If you're getting code like this:

myMember.a().b().c().d();

or this:

invokeD( invokeC( invokeB( myMember.a() ) ) );

Perhaps you should stop and think about what it is you are trying to do. If your object needs information from objects which are not that objects immediate neighbours, perhaps that object should call some kind of messenger object which goes and tells another object with the right "connections' to do the thing, and then give the result back to the messenger who delivers the results back to the original object.... or something.... you can delete all this if its totally irrelevant.

It should all seem automagical to the object. The object is only talking to its friends and to the messenger. The messenger can communicate with several groups of friends... possibly not all the groups of friends... you're probably going to run into networking and routing problems if the number of objects gets big enough....

You can play with the toys that were given to you, but you should never have to worry about how they got to you from the giver?

Perhaps this should be a clarification of the third law, "Giving yourself toys that were given to you does not make them yours."

For example:
 myField.a().b().c()
Can very well be "law of Demeter" kosher, although syntactically looks like a LOD violation myField.a() can construct a new object, the new object's b() can construct yet another object and the third object's c() can construct yet another object. That is always a violation of the Law of Demeter, regardless of whether the objects already existed or were constructed. The single line of code as you have described it embodies the knowledge that a() answers a factory, A, for which b() is a method that answers a factory, B, for which c() is a method which answers some object C. It does not matter whether A, B, and C were constructed vs. being instance variables. The coupling is the same regardless. If it is indeed valid to expect myField to be able to produce instances of C, then that should be a method on myField, and that line of code should embody the fact that myField can produce it. myField should know no more than the fact A can produce it. A should know no more than the fact that B can produce it. This makes the coupling of objects through each single coupled object, making changing the program structure easier. The single line of code violating Demeter couples these objects all together in a chain. Doing this everywhere in your program makes changing the structure of A and B and their relationship to C extraordinarily difficult, and is the reason for the Law of Demeter.


EditText of this page (last edited October 14, 2010) or FindPage with title or text search