My understanding of consequences of the Law of Demeter seems to be different to DrJokepu’s – whenever I’ve applied it to object oriented code it’s resulted in tighter encapsulation and cohesion, rather than the addition of extra getters to contract paths in procedural code.
Wikipedia has the rule as
More formally, the Law of Demeter for
functions requires that a method M of
an object O may only invoke the
methods of the following kinds of
objects:
- O itself
- M’s parameters
- any objects created/instantiated within M
- O’s direct component objects
If you have a method which takes ‘kitchen’ as a parameter, Demeter says you cannot inspect the components of the kitchen, not that you can only inspect the immediate components.
Writing a bunch of functions just to satisfy the Law of Demeter like this
Kitchen.GetCeilingColour()
just looks like a total waste of time for me and actually gets is my way to get things done
If a method outside of Kitchen is passed a kitchen, by strict Demeter it can’t call any methods on the result of GetCeilingColour() on it either.
But either way, the point is to remove the dependency on structure rather than moving the representation of the structure from a sequence of chained methods to the name of the method. Making methods such as MoveTheLeftHindLegForward() in a Dog class doesn’t do anything towards fulfilling Demeter. Instead, call dog.walk() and let the dog handle its own legs.
For example, what if the requirements change and I will need the ceiling height too?
I’d refactor the code so that you are working with room and ceilings:
interface RoomVisitor {
void visitFloor (Floor floor) ...
void visitCeiling (Ceiling ceiling) ...
void visitWall (Wall wall ...
}
interface Room { accept (RoomVisitor visitor) ; }
Kitchen.accept(RoomVisitor visitor) {
visitor.visitCeiling(this.ceiling);
...
}
Or you can go further and eliminate getters totally by passing the parameters of the ceiling to the visitCeiling method, but that often introduces a brittle coupling.
Applying it to the medical example, I’d expect a SolubleAdminstrationRoute to be able to validate the medicine, or at least call the medicine’s validateForSolubleAdministration method if there’s information encapsulated in the medicine’s class which is required for the validation.
However, Demeter applies to OO systems – where data is encapsulated within the objects which operate upon the data – rather than the system you’re talking about, which has different layers an data being passed between the layers in dumb, navigatable structures. I don’t see that Demeter can necessarily be applied to such systems as easily as to monolithic or message based ones. (In a message based system, you can’t navigate to anything which isn’t in the grams of the message, so you’re stuck with Demeter whether you like it or not)