Law Of Demeter Is Invalid

Superseded by LawOfDemeterRevisited

Most of the details here are still valid objections to the original LawOfDemeter, but the author further considered the important cases when the law is still valid.

The ultimate proof that LawOfDemeterIsInvalid is that there are mechanical refactorings that transform code that breaks LoD into code that conforms to LoD, but leaves everything untouched with regards to InformationHiding criteria: the same dependencies are there, the same coupling, just the syntactic verification of the code will pass LoD. So clearly LoD fails to distinguish good designs from bad designs. However, LawOfDemeterRevisited tries to make the distinction more meaningful.


If you follow LawOfDemeter as we have it on wiki, it is plain and simple self-contradictory. Anybody have a good formal definition?

In particular, it makes a non-existent distinction between objects "created" by a method and objects that come back from other method calls.

Compare this code:

 void doSomething() {
   B b= new B();
   b.callSomething();
 }

// that would be perfectly ok.

To begin with, in SmallTalk and other fine languages a new operator is just a method call sent to a global object. Ooops in Smalltalk you cannot create any objects without violating LOD. Let's say however that a constructor is a special exception to LoD.

But how about if one wants to abstract (parameterize ) the call to constructor.

 void doSomething(A a) {
   B b= a.makeMeaB();
   b.callSomething()
 }
In essence, there's no reason why this variant should be verbotten while calling new is OK. But from this variant one should only notice that it's just as good as:

 void doSomething(A a) {
    a.makeMeaB().callSomething();
 }
Oops - the latter is an absolute violation of LoD.

No it isn't, that's perfectly valid. "You can play with toys you made yourself". If a is a factory for making b's, then calling makeMeaB is building your own toy, so you can call methods on it without violating demeter. If b is just a property of a and you aren't creating a new b, then it is a violation of demeter, because you didn't make it.

If you take this position, than you make the client class privy of the information of whether a.computeSomething() actually creates (computes) a new object - therefore being suspect of factory and thus DemeterOK, or gives you some already existent object from its own private fields, and therefore being DemeterNotOK. This violates InformationHiding, since it increases coupling between module. If class A has a method called XXXX() that returns an object of class B, the mere fact that it returns the damn thing means that the receiver can put it to good use (send a message), otherwise the method should have returned void. Just think about the lots SmallTalk methods returning booleans, in Smalltalk there's no if keyword, there's the ifTrue message on booleans, so merely doing an if on a boolean returned from something else, already violates demeter. Just look at the following Smalltalk code retrieved randomly from Google:

 (denominator = 0) ifTrue:  [ ' ... actual block ellided]
The above is already a LoD violation because (denominator = 0 ) returns an object, it's not a factory by any means, which is then sent the message ifTrue: .

I disagree, (denominator = 0) creates a boolean object, which is then used by the caller, not a violation of demeter, you made the boolean, you can play with it. The fact that true and false are global singletons is an optimization and has no bearing on the matter. You are ignoring the intent of demeter and focusing on the words too much, it's not an absolute law, it's a guidline to help reduce coupling in code, and a valid one at that. Demeter is an aid to refactoring, and true and false aren't going to change, use your brain and know when to apply the guideline.

So when you're caling a.aMethod(), are you willing to make the distinction on whether the returned result is newly created by the method, and is safe to use, or is it not? Then you've just increased the information shared between the modules. So it is not an absolute law, it is almost an AntiPattern, as we already have a general principle called InformationHiding that covers all aspects covered by LoD, while the developers trying to stay LoD correct need to make irrelevant distinctions (between results that are freshly new object versus already existing objects, also OK global objects like Class objects versus non-Class global objects and many other arbitrary distinciton), and in doing so they've just broken the information hiding principle.

The very common sense principle that should replace LoD is:

"Use your brain" and recognize that a "law" that states a counterindication to using objects returned by a method call ( or more generally the result of an expression), violates common sense and is entirely useless.

Many guidelines of programming overlap or disagree with one another, it isn't science, there are not exact rules, you have to consider paradigms and origin. InformationHiding isn't specific to OO, but certainly applies, whereas demeter is an OO guideline meant to help newbies not write bad code. As a guideline, its enormously useful until you learn to grasp the bigger picture of InformationHiding. That takes time and is harder to explain to people, demeter serves as a simpler guideline to follow for beginners.

Many people find demeter useful and will continue to do so, regardless of your opinion of it. For all practical purposes, demeter simply means be suspicious of any long chains of .this.that.this.that.

[I don't believe that to be accurate.]

Might you be a bit more specific, there were two statements there?

This contradiction derives from the fact that LoD allows one to call something on objects hold as local stack variables, while not allowing chains of calls, and these two conditions together are self contradictory since there's obviously no valid distinction between an object held in a local variable and a temporary object behind a link in a chained call. In the reference definition of LoD http://www.ccs.neu.edu/research/demeter/demeter-method/LawOfDemeter/object-formulation.html the consequence local variables are totally verbotten. LawOfDemeter is also in conflict with a good language design principle that everything should be an expression. What's the point then in having expression evaluated to objects, if the results have to be discarded (if you use them you're likely to violate LoD).

All in all LoD is reinvented wheel as argued in LawOfDemeterVsInformationHiding, and now it turns out to be squared.

It does not, really. If it was called "suggestion of demeter" it could have been better accepted. As already pointed out, the LoD is just "obj.something.somethingelse.seeWhat may be bad", and writing

 baz= bar.getBaz()
 foo=baz.getFoo()
 hoge=foo.getHoge()
 hoge.doStuff()
is exactly as evil as
 bar.getBaz().getFoo().getHoge().doStuff()
Also, being expression oriented is not demonstrated to be the RightThing (or you have to kill GuidoVanRossum, JamesGosling et many al)

You mean you don't take all laws as suggestions? I thought that was a given in computer programming. Even GotoConsideredHarmful has its exceptions. We're talking software here, not high crimes against the state.

The code above, with the intermediate assignments, is also in violation of LawOfDemeter.

The Law states which "toys" you can play with; baz, foo, and hoge were not passed in, created by the method (unless bar, baz, and foo are all factories, but why would you need a 3-deep chain of AbstractFactorys?), or part of the enclosing method. It doesn't matter whether you chain the expressions together or assign them to temporaries, you still got them by calling methods on other objects.

As for expression-orientedness, you're MixingParadigms. Demeter is a statement about good ObjectOrientedDesign; it's obviously not applicable to FunctionalProgramming. While functional programming is often good practice and can be mixed fairly freely with objects, don't expect OOD principles to hold for the functional parts of a program.

If you want a somewhat easier-to-understand formulation of LoD, see TellDontAsk. -- JonathanTang

It sounds like the LawOfDemeter primarily is important with regards to languages that are ambiguous about references and mutation of objects (like all the usual garbage collected OOP languages). In C++ if you stick to using value-ownership, auto_ptr, and weak references, there is no ambiguity of ownership - any method that returns an auto_ptr to an object is either returning a new object or giving you ownership of it anyways, so you can do whatever you like with it. Then the LawOfDemeter looks much less absurd - do not modify objects that are owned by other objects... which is basic encapsulation - I shouldn't be able to see objects owned by other objects - weak references exist for the rare exceptions to that rule.


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