The
LawOfDemeter specifies a style guideline: "Only talk to your immediate friends." E.g. one never calls a method on an object you got from another call nor on a global object. This helps a lot later when you
ReFactor the code.
http://www.ccs.neu.edu/research/demeter/papers/law-of-demeter/oopsla88-law-of-demeter.pdf
PeterVanRooijen
? posted the following description of the
LawOfDemeter to Usenet:
- You can play with yourself.
- You can play with your own toys (but you can't take them apart),
- You can play with toys that were given to you.
- And you can play with toys you've made yourself.
Explanation in plain English:
- Your method can call other methods in its class directly
- Your method can call methods on its own fields directly (but not on the fields' fields)
- When your method takes parameters, your method can call methods on those parameters directly.
- When your method creates local objects, that method can call methods on the local objects.
but
- One should not call methods on a global object (but it can be passed as a parameter ?)
- One should not have a chain of messages a.getB().getC().doSomething() in some class other than a's class.
One should not have a chain of messages a.getB().getC().doSomething() in some class other than a's class.
I have a slight problem with this. Even if you limit calls to a.getB().getC().doSomething() to within class 'a', aren't you still violating the principle in terms of 'b' since 'a' is calling b.getC().doSomething() ?
So 'b' needs a method called doSomething() that calls c.doSomething() and then 'a' needs a method called doSomething that calls b.doSomething()
Here's an exact quote briefly summarizing the topic from a slide for a university course found on the web, maybe it'll help clarify the historical confusion on this page:
Law of Demeter
- governs the communication structure within an object-oriented design
- restricts message-sending statements in method implementations
- only talk to your immediate friends
- message target can only be one of the following objects:
- the method's object itself (C++, Java, C#: this; Smalltalk: self, super; VB.NET: Me)
- an object that is an argument in the method's signature
- an object referred to by the object's attribute
- an object created by the method
- an object referred to by a global variable
Note: format changed by a WikiGnome. Original at http://216.239.59.104/search?q=cache:VWLF3svy_ewJ:www.isys.uni-klu.ac.at/ISYS/Courses/02WS/sete/folien/Fse0207_DFDConcepts.pdf (Google HTML version, strip everything before www.isys for address of original PDF).
An alternative take (trying to improve) is proposed in
LawOfDemeterRevisited.
Before reading further please see
LawOfDemeterVsInformationHiding,
LawOfDemeterMakesUnitTestsEasier,
LawOfDemeterIsHardToUnderstand,
LawOfDemeterIsTooRestrictive,
LawOfDemeterAndCoupling.
The Demeter literature talks about the introduction of
lots of additional small methods, which started getting unwieldy to add manually, and is part of why the Demeter tools exists, so they can be autogenerated as needed.
This gets into issues of propagation of results of partial computations, which is a whole other area of Demeter called "propagation patterns" (not be confused with "design patterns"). Beyond the straightforward stuff, trying to go "full" Demeter without the niceties of the "full" Demeter system has lots of not niceties" associated with it because without Demeter's tool-support you can't so easily propagate what is needed where in an orthogonal fashion. --
AnonymousDonor
I don't see this as a problem. I think FewShortMethodsPerClass and lack of FearOfAddingClasses fits LawOfDemeter. -- GuillermoSchwarz
LoD can be regarded as the principle of assuming "least structural knowledge" (something its creator calls "Structure-shy programming"). The idea is to assume knowledge of no object's internal structure other than your own immediate self.
When an object is encapsulating structural knowledge and you try to take advantage of that, your object method is making a rigid assumption about the traversal path to access that knowledgehen they represent facets of the problem domain.''
If a fundamental structural relationship in the domain really does change then its almost certain that a clients requirements of the interface will also change and thus the facade provided by the outer objects hasn't bought you anything other than an extra layer (or even several layers) of code to maintain. Conversely, a structural change that is not domain oriented should be hidden behind a bridge where it cannot affect the exposed structure.
Structural relationships between objects are a powerful abstraction mechanism in their own right, and thus a powerful force for simplicity when used in the right place -- Paul Campbell
The Law of Demeter is (or might be in some designs) related to the
VisitorPattern: if you have to do something to object X at the end of a long chain of composites and accessors, the wrong way is digging up X yourself and perform the operation directly; one of the good ways is having a Visitor look for object X with the collaboration of all involved objects.
It is much less brittle because you don't need to know the details of the data structure; the visitor only needs to visit X to do its job. The visitor can also seek objects satisfying some condition.
The use of a visitor in this case is motivated by the fact that the intermediate objects don't know (and probably have no business knowing) how to do the special operation you want, but they can be expected to support a generic visitor.
Some work by
KarlLieberherr (see his university page) has the purpose of generating the visitor infrastructure from object graphs; it can perhaps be considered an instance of
AspectOrientedProgramming (the aspect of visiting messy object graphs). --
LorenzoGatti
Perhaps what is needed is a hierarchical composite - Pass the Person node to a Find
Whatever
Visitor class whose result is the value you need. Then
person deductionProfiles last stateTaxDeduction amount each class may need a method that reports what elements are composites and leafs and a method to indicate what kind of composite it is, but you've removed the need for at least a part of this problem. The ImA()
(or KindOf() ), My
Leaves
Are() and My
Composites
Are() methods work well in testing as well if you've forgotten what is in your composite. Of course, this is more code that you may not need. --
WyattMatthews.
ObjectQueries
? and the
AdapterPattern are two ways to implement the
LawOfDemeter. --
DaveOrme
You'll likely find similar code all over the system - That repetition is itself sufficient reason to refactor.
OnceAndOnlyOnce. We don't need Demeter to tell us that. --
DaveHarris
My XP formulation about
ShieldPattern is described in
BridgePatternIsJustGoodFactoring. When we see a method like:
person profiles identityProfile lastName
we tend to replace it with
person lastName
with the appropriate definition of lastName in Person. Apply recursively. If you look at this from the viewpoint of
ShieldPattern, you can say we do it because the handling of profiles is up to Person. We just think it makes the code look nicer ;-> (I oversimplify for effect, of course.) --
RonJeffries
I also create:
person identityProfile
as
^self profiles identityProfile
Of course you see that kind of code all the time in Smalltalk, but very few times in Java.
--
GuillermoSchwarz
Sometimes different just think it makes the code look nicer ;-> (I oversimplify for effect, of course.) --
RonJeffries
I also create:
person identityProfile
as
^self profiles identityProfile
Of course you see that kind of code all the time in Smalltalk, but very few times in Java.
--
GuillermoSchwarz
Sometimes different clients need different types of access. With regard to the dog mentioned above: A vet may very well want to violate a dog's encapsulation and manipulate its legs directly. So it seems like the
LawOfDemeter, as an axiom, is flat out opposed to any sort of inspection/reflection business.
Reflection doesn't necessarily violate the LawOfDemeter if you keep in mind the "principle of least structural knowledge" definition. You're supposed to encapsulate structural knowledge in a few places in the code; nothing in reflection would necessarily contradict that. Now, if you make assumptions about what to look for when inspecting, that would need to be modified if the access path/interface changes, then that very well could be a violation of the LawOfDemeter.
See also:
InterfaceMarket
A vet should be able to manipulate the Dog's leg as it is a 'visible interface'. He, however, can manipulate the Dog's intestinal parasites only via an available interface, i.e. the mouth, by the introduction of worming tables. To do otherwise, i.e. to operate, would break the 'rules'. --
NickAdie
In fact we can make the Leg interface visible only to the Vet. E.g. Dog exposes Leg objects via its allow_manipulation_by(Vet) method which only accepts a Vet. This method, if the Dog is not using the Leg, passes the Leg to the Vet by calling the allowed_to_manipulate(Leg) method, hence the interfaces must hold good if the interface check holds good. For real safety the Dog could pass a proxy instead which it can release at any point, that way the Vet cannot manipulate the Leg if the Dog does not like it. It occurred to me that following the laws of Demeter effectively prohibits return statements from methods. I find that banishing return statements from my code and solving problems without them has excellent effects on readability and flexibility of classes. In effect it forces two-way contracts between objects, which seems to be beneficial. Unlike the following post, I have found this extends to Collections and ValueObjects
?. Factories, however, do seem to need to return objects.
-- MikeAmy
?
I've had success applying the Law of Demeter by allowing exceptions for three kinds of class:
- Collections (as described above)
- ValueObjects (especially as I follow ValueObjectsShouldBeImmutable)
- Factories (and any object that returns another object and does not keep its own reference to the returned object).
So, in my code the Law of Demeter only applies to
ReferenceObjects that embody domain knowledge. This has been very successful in making code easy to read, easy to test and easy to change. The use of automatic refactoring tools helps a great deal with the "easy to change" aspect, so I'm not sure how well this would work in a more manual coding environment. --
NatPryce
See
DemeterGoddess to see where this name came from.
- Wikipedia is not a dictionary, but I'd be interested in what the connection with the goddess is.
- Taken from http://www.ccs.neu.edu/home/lieber/LoD.html: 2003 was the 15 Year Anniversary of the Law of Demeter: The Law of Demeter is a simple style rule for designing ObjectOriented systems. "Only talk to your immediate friends" is the motto. The style rule was first proposed at Northeastern University in the fall of 1987 and popularized in books by Booch, Budd, Coleman, Larman, Page-Jones, Rumbaugh and others. A 2000 book that describes it well is The Pragmatic Programmer by AndrewHunt and DavidThomas. The name "Law of Demeter" was chosen because the style rule was discovered while working on the The Demeter Project which ever since was strongly influenced by the Law of Demeter. The Demeter Project develops tools that make it easier to follow the Law of Demeter. (Demeter = Greek Goddess of Agriculture; grow software in small steps) For example, "only talk to your immediate friends that share the same concerns" leads to tools for Aspect-Oriented Software Development.
I wonder
CanLawOfDemeterBeRefactoredAutomatically?
See also:
EncapsulationIsHierarchical,
TreeOrientedPerspective,
TellDontAsk,
ShieldPattern,
CapabilityComputing,
LawOfDemeterExample,
AlternateHardAndSoftLayers,
ShearingLayers.
Other references:
We think it's possible to try
too hard to avoid violating this rule. For example, adding in 'convenience' methods, which act as bridges, or over-zealous
use of the
ShieldPattern.
We've just finished a pair-programming session where we've found that taking
out these convenience methods helps to reveal
FeatureEnvy, which in turn indicates refactorings which otherwise would have remained hidden.
And finally, there's no problem breaking
LawOfDemeter in tests, right? --
MalcolmSparks,
EamonWalshe (pairing)
IOW: do not call
foo.getBar().doSomething()
instead, implement doSomething() on Foo by having it call bar.
- from the caller's point of view, the thing that you are interested in is "what does bar do?"
- from Bar's point of view, I don't want people monkeying about with my contents without me knowing about it. Maybe bar always needs to do a thing before and after foo does something.
I would like a
JavaLanguage feature allowing you to do this declaratively.
class Foo implements IBar {
// all calls to IBar methods on Foo get implemented by calls to this variable
IBar myIbar implements IBar;
// except for barMethod, which I implement here explicitly
void barMethod3() {...}
}
the compiler would generate methods barMethod1(), barMethod2(), barMethod4() etc.
Or you could just use Objective-C or Smalltalk...
Is this generally refuting the technique of "pathing", such as that commonly found in JavaScript DOM references where you get long references? They tend to look like:
todds.parents.dogs.bitee.brothers.house.garage.door.open();
Well, in that case the structure may actually be important. But often it's still better to get a hold of objects via id references...
Trying to come up with a more simple (non-foobar) example, is this correct?
currentPerson.Account.Deposit(500) <-- bad
Account.Deposit(currentPerson, 500) <-- good
Reason:
Account may need to be initialized before it can be accessed
Say currentPerson.Account = null, will throw null reference exception in bad code
In good code, Deposit method can check if null and setup a new one before depositing
What about when you want to look something up in a dictionary with more than one index in something like Java? You could define a pair object with a comparable interface on it, but that requires writing a new class for each different number of indices. I think a more natural way of doing this is curried dictionaries, like
HashMap<FirstIndex
?,
HashMap<SecondIndex
?, Value>>. Then when looking up you do dictionary.get(firstIndex).get(secondIndex).
- Does this break LawOfDemeter
- If so, what's the better way of doing it?
IsLawOfDemeterOverspecifiedOnCeeTwo
'Tis a silly law with diminishing returns on model complexity. Interesting, but irrelevant except in remarkably simple cases.
See
ContractiveDelegation.
CategoryModellingLawsAndPrinciples