Recently I read a discussion on an internal mailing list on whether ornot it would be worthwhile to add a null dereferencing operator to C#.
For example, one proposed idea would allow the following expression.
objecta=foo.?bar.?baz.?qux;
This would assign the variablea
the valuenull
if any one offoo,
bar
, orbaz
is nullinstead ofthrowing aNullReferenceException
. It’s a small, but potentially helpful,mitigation for thebillion dollarmistake.
Sure enough, it did not take long for someone to claim that this syntaxwould be unnecessary if the code here was not violating the sacredLawofDemeter(or LoD for short). I think this phenomena is an analog toGodwin’sLaw anddeserves its own name. Let’s call it the “LoD Dot Counting Law”:
As a discussion of a code expression with more than one dot growslonger, the probability that someone claims a Law of Demeter violationapproaches 1.
Count the dots and win a prize!
What is wrong with the claim that the above expression violates LoD? Toanswer that let’s briefly cover the Law of Demeter. I’m not going tocover it in detail but rather point to posts that describe it in muchbetter detail than I would.
The Many Forms of Demeter
Theformal objectformof the law can be summarized as:
A method of an object may only call methods of:
- The object itself.
- An argument of the method.
- Any object created within the method.
- Any direct properties/fields of the object.
Ageneral formulation of thelawis:
Each unit should have only limited knowledge about other units: onlyunits “closely” related to the current unit. Or: Each unit should onlytalk to its friends; Don’t talk to strangers.
This of course leads to the succinct form of the law:
Don’t talk to strangers
In other words, try to avoid calling methods of an object that wasreturned by calling another method. Often, people shorten the law tosimply state “use only one dot”.
One of the key benefits of applying LoD is low coupling viaencapsulation. In his paper,The Paperboy, The Wallet, and The Law ofDemeter(PDF)(it’s a relatively quick read so go ahead, I’ll be here), David Bockprovides a great illustration of this law with an analogy of a paperboyand a customer. Rather than having a customer hand over his wallet topay the paperboy, he instead has the paperboy request payment from thecustomer.
In answer to “Why is this better?” David Bock gives these three reasons.
The first reason that this is better is because it better models thereal world scenario… The Paperboy code is now ‘asking’ the customerfor a payment. The paperboy does not have direct access to thewallet.
The second reason that this is better is because the Wallet class cannow change, and the paperboy is completely isolated from that change…
The third, and probably most ‘object-oriented’ answer is that we arenow free to change the implementation of ‘getPayment()’.
Note that the first benefit is an improvement not only in encapsulationbut the abstraction is also improved.
Dot Counting Is Not The Point
You’ll note that David doesn’t list “50% less dots in your code!” as abenefit of applying LoD. The focus is on reduced coupling and improvedencapsulation.
So going back to the initial expression, doesfoo.bar.baz.qux
violateLoD? Like most things, it depends.
For example, suppose thatfoo
is of typeSomething
and it containsproperties namedBar
,Baz
, andQux
which each simply returnthis
.
In this semi-contrived example, the expression is not an LoD violationbecause each property returns the object itself and according to thefirst rule of LoD, “you do not talk about LoD” … wait … sorry… “a methodis free to call any properties of the object itself” (in a future post,I will cover theclass form of LoD which seems to indicate that ifBar
,Baz
, andQux
return the same type, whether it’s the sameobject or not, LoD is preserved).
This pattern is actually quite common with fluent interfaces where eachmethod in a calling chain might return the object itself, buttransformed in some way.
So we see that counting dots is not enough to indicate an LoD violation.But lets dig deeper. Are there other cases where counting dots leads donot indicate an LoD violation? More importantly, is it always a badthing to violate LoD? Are there cases where an LoD violation might evenbe the right thing to do?
Go Directly to Jail, Do Not Pass Go
Despite its name, violating the Law of Demeter will not get you on anepisode of Cops nor is it some inviolable law of nature.
As theoriginal paper pointsout,it was developed during design and implementation of the Demeter system(hence the name) and was held to be a law for the developers ofthatsystem.
The designers of the system felt that this practice ensured goodObject-Oriented design:
The motivation behind the Law of Demeter is to ensure that thesoftware is as modular as possible. The law effectively reduces theoccurrences of nested message sendings (function calls) and simplifiesthe methods.
However, while it was a law in the context of the Demeter system,whether it should hold the weight that calling it aLaw implies isopen to debate.
David Bock refers to it as an idiom:
This paper is going to talk about a particluar(sic) ‘trick’ I like,one that is probably better classified as an ‘idiom’ than a designpattern (although it is a component in many different designpatterns).
Martin Fowlersuggests(emphasis mine)
I’d prefer it to be called theOccasionally Useful Suggestion ofDemeter.
Personally, I think most developers are guilty of bad encapsulation andtight coupling. I’m a bit more worried about that than applying this lawinappropriately (though I worry about that too). Those who have deepunderstanding of this guideline are the ones who are likely to know whenit shouldn’t be applied.
For the rest of us mere mortals, I think it’s important to at leastthink about this guideline and be intentional about applying or notapplying it.
I Fought The Law and The Law Won
So what are the occasions when the Law of Demeter doesn’t necessarilyapply? There’s some debate out there on the issue.
In his post,Misunderstanding the Law ofDemeter,Daniel Manges argues that web page views aren’t domain objects and thusshouldn’t be subject to the Law of Demeter. His argument hinges on aRails example where you send anOrder
object to the view, but the viewneeds to display the customer’s name.
<%= @order.customer.name %>
Counting two dots, he considers the change that would make it fit LoD:
<%= @order.customer_name %>
He then asks:
Why should an order have a customer_name? We’re working with objects,an order should have a customer who has a name.
…when rendering a view, it’s natural and expected that the view needsto branch out into the domain model.
Alex Blabs of Pivotal Labstakes issue with Daniel’s post andarguesthat viewsaredomain objects and an order ought to have acustomer_name
property.
It’s an interesting argument, but thefollowing snippet of acommentby Zak Tamsen summarizes where I currently am on this subject (though mymind is open).
because they don’t. the primary job of the views (under discussion) isto expose the internal state of objects for display purposes. that is,they are expressly for data showing, not data hiding. and there’s therub: these kind of views flagrantly violate encapsulation, LoD is allabout encapsulation, and no amount of attribute delegation canreconcile this.
The problem as I see it with Alex’s approach is where do you stop? DoestheOrder
object encapsulate every property ofCustomer
? What aboutsub-properties of theCustomer
’s properties? It seems the decision toencapsulate the Customer’s name is driven by the view’s need to displayit. I wouldn’t want my domain object’s interface to be driven by theneeds of the view as that would violate separation of concerns.
There’s another option which might be more common in theASP.NETMVC world than in the Railsworld, I’m not sure. Why not have a view specific model object. Thiswould effectively be the bridge between the domain objects and the viewand could encapsulate many of the these properties that the view needsto display.
Another case where an LoD violation might not be such a bad idea is incases where the object structure is public and unlikely to change. Whilein Norway, I had the opportunity to briefly chat withMichaelFeathersabout LoD and he pointed out the example of Excel’s object model fortables and cells. If LoD is about encapsulation (aka information hiding)then why would you hide the structure of an object where the structureis exactly what people are interested in and unlikely to change?
Use It or Lose It
When I learn a new guideline or principle, I really like to dig intowhere the guideline breaks down. Knowing where a guideline works, andwhat its advantages are is only half the story in really understandingit. When I can explain where it doesn’t work and what its disadvantagesare, only then do I feel I’m starting to gain understanding.
However, in writing about my attempts at understanding, it may comeacross that I’m being critical of the guideline. I want to be clear thatI think the Law of Demeter is a very useful guideline and it applies inmore cases than not. It’s one of the few principles that can point to anempirical study that may point to its efficacy.
In aValidation of Object-Oriented Design Metrics as QualityIndicators,the authors of the study provide evidence that suggests The Law ofDemeter reduces the probability of software faults.
Still, I would hope that those who apply it don’t do it blindly bycounting dots. Dot counting can help you find where to look forviolations, but always keep in mind that the end goal is reducingcoupling, not dots.