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
is not valid according to LawOfDemeter, but:
Y y = x.y();
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) );
refactored it to this to obey the LawOfDemeter
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) );
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:
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
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:
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."
- Which raises the question: Which toys weren't given to a method? Even the toys it creates were given to it by a class's constructor. The whole notion of toy ownership is suspect.
- And the presumption that only constructors can construct object is useless and harmful. Since we have to take into account that all methods/functions can be constructing object (rather than just "give away" references to objects ), it follows that there's no syntactical tool to recognize law of demeter violations.
- It isn't a presumption, it's a rule, isn't it? Only constructors create objects.
- What do you think FactoryMethods, AbstractFactory and other patterns do in a non-trivial object system? They are used to construct objects on behalf of their clients. Plus, in some languages there's no such thing as a distinguished type of procedure called constructor - that's the problem that Creational Patterns are designed to solve in the first place: the fact that somebody thought that distinguishing constructors from other methods is a good idea, and that constructors should not be FirstClass.
- I know what factories do. Inside a factory a constructor creates the object. That was my point. Every method (including factory methods) are "given" their toys by another method.
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.