Demeter Transmogrifiers To The Rescue

0 comments suggest edit

In a recent post, The Law of Demeter Is Not A Dot Counting Exercise, I wanted to peer into the dark depths of the Law of Demeter to understand it’s real purpose. In the end I concluded that the real goal of the guideline is to reduce coupling, not dots, which was a relief because I’m a big fan of dots (and stripes too judging by my shirt collection).

However, one thing that puzzled me was that there are in essence two distinct formulations of the law, the object form and the class form. Why are there two forms and how do they differ in a practical sense?

Let’s find an example of where the law seems to break down and perhaps apply these forms to solve the conundrum as a means of gaining better understanding of the law.

Rémon Sinnema has a great example of where the law seems to break down that can serve as a starting point for this discussion.

Code that violates the Law of Demeter is a candidate for Hide Delegate, e.g. manager = john.getDepartment().getManager() can be refactored to manager = john.getManager(), where the Employee class gets a new getManager() method.

However, not all such refactorings make as much sense. Consider, for example, someone who’s trying to kiss up to his boss: sendFlowers(john.getManager().getSpouse()). Applying Hide Delegate here would yield a getManagersSpouse() method in Employee. Yuck.

This is an example of one common drawback of following LoD to the letter. You can end up up with a lot of one-off wrapper methods to propagate a property or method to the caller. In fact, this is so common there’s a term for such a wrapper. It’s called a Demeter Transmogrifier!

transmogrifier_small

Who knew that Calvin was such a rock star software developer?

Too many of these one-off “transmogrifier” methods can clutter your API like a tornado in a paper factory, but like most things in software, it’s a trade-off that has to be weighed against the benefits of applying LoD in any given situation. These sort of judgment calls are part of the craft of software development and there’s just no “one size fits all follow the checklist” solution.

While this criticism of LoD may be valid at times, it may not be so in this particular case. Is this another case of dot counting?

For example, suppose the getManager method returns an instance of Manager and Manager implements the IEmployee interface. Also suppose that the IEmployee interface includes the getSpouse() method. Since John is also an IEmployee, shouldn’t he be free to call the getSpouse() method of his manager without violating LoD? After all, they are both instances of IEmployee.

Let’s take another look at the the general formulation of the law:

Each unit should have only limited knowledge about other units: only units “closely” related to the current unit. Or: Each unit should only talk to its friends; Don’t talk to strangers.

Notice that the word closely is in quotes. What exactly does it mean that one unit is closely related to another? In the short form of the law, Don’t talk to strangers,we learn we shouldn’t talk to strangers. But who exactly is a stranger? Great questions, if I do say so myself!

The formal version of the law focuses on sending messages to objects. For example, a method of an object can always call methods of itself, methods of an object it created, or methods of passed in arguments. But what about types? Can an object always call methods of an object that is the same type as the calling object? In other words, if I am a Person object, is another Person object a stranger to me?

According to the general formulation, there is a class form of LoD which applies to statically typed languages and seems to indicate that yes, this is the case. It seems it’s fair to say that for a statically typed language, an object has knowledge of the inner workings of another object of the same type.

Please note that I am qualifying that statement with “seems” and “fair to say” because I’m not an expert here. This is what I’ve pieced together in my own reading and am open to someone with more expertise here clearing up my understanding or lack thereof.

Found a typo or error? Suggest an edit! If accepted, your contribution is listed automatically here.

Comments

avatar

10 responses

  1. Avatar for Justin Pitts
    Justin Pitts August 16th, 2009
    It seems it’s fair to say that for a statically typed language, an object has knowledge of the inner workings of another object of the same type.


    Except, of course, for subtypes. Then that knowledge is somewhat less perfect.

  2. Avatar for Justin James
    Justin James August 16th, 2009

    This is the kind of discussion that gives huge amounts of ammunition to the anti-OOP folks, and the kind of discussion that makes languages like Ruby and Python very attractive.
    At the end of the day, one can focus on all sorts of OO wonkishness, or one can focus on getting the job done. The OO dynamic languages like Ruby and Python really follow the Smalltalk school of thought when it comes to OO architecture, in that the *actions* matter more than the *architecture*. This kind of discussion is clerarly in the C++/Java/C# realm, in which the architecture is much more important to folks than the actions in performs.
    At the end of the day, I "get" why these kinds of conversations are important, but at the same time, I wish they weren't needed. C# 3 is the first time VB.NET or C# appealled to me at all, and a lot of that is because things like extension methods, lambdas, and LINQ allow me to focus on getting the job done, and spend less time worrying about the architecture. C# 3 was the first time since I was a hardcore Perl user that I actually felt child-like curiosity and enjoyment in the "art of programming". Something about Java, SQL, VBA, and VB.NET (the languages I've primarily dealth with since I left Perl) just feel like total psychic energy vampires to me, if that makes any sense.
    J.Ja

  3. Avatar for Prajwal Tuladhar
    Prajwal Tuladhar August 16th, 2009

    I would rathergive more priority to www.c2.com/.../wiki than Law of Demeter.
    And in the above examples, you are using getters. Do getters and setters really expose behavior of any object? If they would have exposed, why do most unit test experts don't bother testing them?
    I think, counting dots matter regarding LoD only when you are using methods that are exposing real behavior of any object rather than getters/setters.

  4. Avatar for Mark Rendle
    Mark Rendle August 16th, 2009

    @Justin: sub-types should be fine as long as Liskov is in effect.

  5. Avatar for JonR
    JonR August 16th, 2009

    @Justin James: what a vague and handwavey comment. a bit like dynamic languages, haha. nil points!

  6. Avatar for Jon
    Jon August 17th, 2009

    I hate the 'Law of Demeter' with a passion. It is a 'law' coined on the basis of anecdotal evidence, which serves only to make developers hesitant and confused, and leads to them wasting time and brainpower considering its consequences in the fashion of this blog, or simply feeling vaguely guilty for not following its edicts through to their illogical conclusion.
    If it has any basis in real best practice, it is only as a cargo-cultish approximation of how experienced developers may sometimes reduce coupling. As Justin said, it focuses too much attention on the form of the code, and not enough on the purpose. Getting the architecture of a software system right is an important task, but the idea that it can be done, or even helped, by applying this sort of rule is dangerous nonsense.
    I hereby propose that we improve discussion of OO development immeasurably by all agreeing henceforth to forget the 'Law of Demeter' completely, thus freeing us from its idiotic tyranny.

  7. Avatar for Haacked
    Haacked August 17th, 2009

    @Jon In my last post on LoD I pointed to a study that provide evidence to suggest The Law of Demeter reduces the probability of software faults.
    So it's not merely anecdotal evidence. One study does not make a proof, but I think it's more than we typically have for many of the axioms and best practices that we take for granted. So I wouldn't be so quick to dismiss it.

  8. Avatar for Jon
    Jon August 18th, 2009

    @haacked That study does not look at the Law of Demeter though, it is and analysis of a set of metrics proposed for measuring the likelihood that an individual C++ class contains faults. One of the metrics is Coupling Between Object classes, and yes, it is found to have apparently significant relationship with the probability of fault detection.
    This says 'a highly coupled class is more likely to have faults', which I would not dispute, but it is a big leap to say it therefore supports applying the 'Law of Demeter'. For example, an obvious objection that springs to mind just from this study is that applying the 'Law of Demeter' could lead to an increase in at least two other metrics it looks at, namely Weighted Methods per Class and Response For a Class, both of which were found to be as, or more, significant as Coupling Between Object classes in determining the likelihood of faults.
    So, if I were feeling mischievous, I could just as easily claim this study supports not using the 'Law of Demeter'. If I were being more reasonable, I would say that the metrics that it sets out to investigate, including the level of coupling, appear to be good indicators of the likelihood of faults in OO code. It would be a good starting point for further studies, that could investigate areas such as the severity of faults, the effect of different strategies for reducing each metric (such as the 'Law of Demeter'), and the effect of these strategies on other metrics, and overall quality. I certainly would not make any pronouncements on best practices in real-world software development and, unsurprisingly, neither do the authors of the study. Their 'Conclusions and Further Work' section lists a number of fascinating potential futures studies, but it does not endorse any kind of strategy for reducing coupling, or any other metric.
    I think the above illustrates two points: Firstly, that the evidence given for the 'Law of Demeter' is anecdotal, in this case the anecdote being that a study was conducted and was found to support using the 'Law of Demeter', when in fact this is a misrepresentation of its conclusions. Secondly, that software development, software architecture, and software quality, are very complex and subtle topics, which need a lot of careful study and consideration.
    This brings me back to the point I was getting at in my previous post, which is not that high coupling is fine, or that reducing it where appropriate is bad, but that reductive rules like the 'Law of Demeter' do not help, and often hinder, as they distract the developer from focusing on the actual requirements of the system, and instead waste their time on considering the situation applicability of the 'law' itself.
    Wow, that turned out to be a bit of an essay.

  9. Avatar for Graham
    Graham August 18th, 2009

    @Haacked: Phil, is the null dereferencing operator a real proposal? When will we know if we will actually get this operator? Would it be in time for .NET 4?
    Graham O.

  10. Avatar for cellphonelookup
    cellphonelookup August 19th, 2009

    That’s why they give you a 56 day guarantee with every lookup. Not only that but the service is 100% legal and confidential.