Thinking a bit about LawOfDemeter
I've come to think that existing code can be refactored automatically to fulfill LawOfDemeter
Push all calls of the form x.foo().bar() into x.fooBar() moving arguments and parameters as needed.
Is this true?
If is is true, then the usefulness of the LawOfDemeter
is questionable, because it is just a simple code-transformation like loop-unrolling, that might or migt not be done by a compiler/refactoring browser, but will not help the programmer/reader any bit.
That was the whole point of the DemeterProject? (they developed tools to perform such automated refactoring), which is where the LawOfDemeter came from in the first place. -- JonathanTang
Demeter has raised what we would know here as a CodeSmell
to the level of a law. I take this clear overstatement to mean that the smell and its solution was the strongest pattern found by the Demeter project. Their law is to me only a hint. As such it is best applied with reason. When x.foo().bar() is the best expression of my intent then I am happy with it. When x.fooBar() is better I usually find that x was well suited to take on the fooBar() responsibility and might even have a better name for it. This is a judgement, best left to humans, though mechanical assist with specific refactorings is always appreciated. -- WardCunningham
Yes, but isn't this the case with all laws? The whole point is to produce working, maintainable, reasonably efficient software. If we have to break a zillion best practices to do so, why not? Demeter is no different from GotoConsideredHarmful
: it's something to be aware of, not an absolute proscription.
said it best: "The whole reason we have rules is so you think
before you break them." -- JonathanTang
If you believe the solution to the LawOfDemeter
is automatic combination of such methods, then automatic refactoring makes sense. If you believe the point of the LawOfDemeter
is to make you think about TellDontAsk
, then automatic methods cannot help you. --francis
I'm not sure this representation of the Law is accurate. With x.foo().bar(), you are calling a method on a return value. A return value is "a toy that was given to you", and the Law of Demeter allows manipulating such objects. What it forbids, is x.foo.bar(), reaching inside another object (x) and doing something with its "toys" (foo). --WillMacKay?