Law Of Demeter: Extension Methods Don’t Count

We all know the Law of Demeter, right? It’s the principle that says “don’t let the paperboy reach into your wallet when he wants to be paid. It’s your wallet, you decide what form of payment and how much without letting him have access to the contents of your wallet.”

A couple of days ago, a coworker told me to use this code for a specific situation:

   1: var asset = assets.FirstOrDefault().As<RecordUniqueAsset>();

He immediately followed that with a statement about Demeter screaming at him.

It occurred to me at that point, that extension methods are just syntax sugar on top of what would otherwise take 10 or 15 lines of code and they don’t really count in the Law Of Demeter evaluation. Extension methods are typically just nice wrappers to help cut down on repeated code. For example, the “As” extension method in this snippet is one that we wrote to cast an object as the specified type (ignore how simple this extension is. it has it’s usefulness in some specific scenarios). Other extension methods that I write tend to be a little more involved, but still have the same basic idea behind them: take 4 or 5 lines of code that I use a lot and make it DRY.

With that in mind, I say this:

   1: var asset = null;

   2: if (assets != null && assets.Count > 0)

   3:     asset = assets[0] as RecordUniqueAsset;

is the same as the first code snippet in functionality and intent. The extension methods just makes it prettier, and does not violate the Law of Demeter.

There probably are scenarios where the implementation of an extension method would violate LoD and thus the extension itself would… but for the simple scenario extension methods like this… I’m not convinced they violate LoD. What do you think? Does it violate LoD? If so, why? … and I’m also wondering if there are any similar constructs in other languages that would fall under the same exception.

About Derick Bailey

Derick Bailey is an entrepreneur, problem solver (and creator? :P ), software developer, screecaster, writer, blogger, speaker and technology leader in central Texas (north of Austin). He runs - the amazingly awesome podcast audio hosting service that everyone should be using, and where he throws down the JavaScript gauntlets to get you up to speed. He has been a professional software developer since the late 90's, and has been writing code since the late 80's. Find me on twitter: @derickbailey, @mutedsolutions, @backbonejsclass Find me on the web: SignalLeaf, WatchMeCode, Kendo UI blog, MarionetteJS, My Github profile, On Google+.
This entry was posted in .NET, C#, Principles and Patterns. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • KevDog

    I’ve got no problems with what you’re doing, it seems quite fluent and readable, actually.

    I’ve always felt that “law” was too string a word. It implies a punishment for violating it. Maybe it’s my naiveté, but I don’t see a penalty.

  • jdn

    I really consider it more of a guideline than a law.

  • I tend to think of it as the “suggestion of Demeter”, because sometimes there are good reasons to “violate” it, and I agree with you that extension methods are a good example.

    The purpose of Demeter is to prevent outside objects from having too much knowledge and reliance on the behavior of objects contained within other objects. This makes clear division of responsibilities (not to mention refactoring) difficult.

    E.g., object foo contains object bar. Object baz should not invoke Foo.Bar.DoSomething(). In my opinion, it IS ok for baz to reference Foo.Bar.DataProperty when foo has some public composite data (otherwise you end up doing a lot of work to have all properties directly on foo, just to avoid calling Foo.Bar.SomeProperty). Or in your example here, call some static extension methods.

    Unfortunately, when you simplify Demeter from “don’t rely on behavior on internals of other objects” to “don’t use more than one dot”, you lose this critical thinking on context.

  • Isn’t this a LSV violation, with the down-casting? Then you have the check to see if a collection is null. Collections should never be null, but just in case, I also have a IsNullOrEmpty() extension method:

    return sequence == null && !sequence.Any();

    If you want the first item of a certain type, I’d do sequency.OfType().FirstOrDefault();

  • I wouldn’t go so far as to exempt extension methods from the Law of Demeter (LoD).

    As Phil Haack once wrote, the Law of Demeter is not a Dot Counting Excersize. It’s about controlling how many dependencies you force code to have.

    In this example, we simply don’t know enough about the context to say whether it does or does not violate the law (shamelessly lifted from Wikipedia):

    M of an object O may only invoke the methods of the following kinds of objects:

    1. O itself
    2. M’s parameters
    3. any objects created/instantiated within M
    4. O’s direct component objects
    5. a global variable, accessible by O, in the scope of M

  • Nathan Evans

    Extension methods are good refactoring candidates at a later stage as well. I’d much rather refactor a single one of those than refactoring a ton of foreach loops and what not.

    I would agree that extension methods are a very special case and are exempt from demeter law.

  • Derek Hammer

    If you are counting dots, you’re doing it wrong.

  • Extensions methods aren’t somehow excluded from the restrictions imposed by the Law of Demeter because they appear to be methods of the extended class, but the particular example presented here isn’t a violation since the get_Count() method (i.e. the Count property) is a method of Asset which is a parameter to the As() method. Were an extension method to execute a method of a property of one its parameters then it could be a violation depending on the instance type (i.e. ExtensionMethod() -> Parameter.Property.Method()).

  • As Nolan pretty much said, LoM is more of a principle than a law, and the crux of the principle is what needs to be focused on and not the syntactic evidence of its application (or lack thereof). With this understanding, I would no longer call extension methods, particularly those of the LINQ variety, simple syntactic sugar.

    You can refactor any LoM violating line of code into something that doesn’t appear to violate LoM, by extracting a method or, more-so, a helper class. Your refactoring, depending on what it was, will have its own benefits and costs, and it might even contribute as a whole to the overall improvement of the solution’s design. If your refactoring was naive, such as in the dangerous case of simply removing the symptoms of a LoM violation, there really is no improvement in quality and, in fact, only more potential maintenance and mystery has been created.

    As you mentioned in your post, you derived the extension method for DRY principles. The extension method itself may or may not violate LoM, but it was still a good refactoring for both LoM and DRY purposes. If the extension method is using an unchangeable archaic piece of some framework (even .NET), it might reasonably use more than one “.” in some member accesses or make vast assumptions about types in casting, where creating an extra-special class to remove this appearance within the extension method had no other obvious use within the system. In other words, violating the “Principle of Demeter” might be a good idea to achieve more important broader system goals, but the violations might should be moved into special places, like extension methods or utility classes that have single self-describing responsibilities.

    Anyway, sorry for beating this one to death — just hope my two cents adds some clarity for someone. I also welcome any suggested adjustment in my perception.

  • I agree. Extension methods are a form of method chaining, and while method chains do have a bunch of ‘dots’ in them, they’re not the same as the ‘dots’ in LoD violations. Counting dots isn’t the point.

  • dave-ilsw

    I don’t see any way in which this use of an extension method could be considered a violation of LoD, because this lets you ask the collection to reach into it’s own pocket and hand you the first or default item.

    Failing to use an extension method, however, would be a clear violation of LoD, because then your code is reaching into the collection’s pocket to fetch the first or default item instead of letting the collection do it.

  • Dathan Bennett

    @dave-ilsw I think you’re inferring properties of extension methods that don’t exist. Underneath the hood, all the FirstOrDefault() extension method does is essentially call GetEnumerator(), then MoveNext() on the enumerator. If MoveNext() returned false, then return null, else return enumerator.Current. It’s the same code you’d write if you did it on your own – it’s just wrapped up in a convenient method, but one that is still external to the target. The fact that you’re using an extension method has no bearing on whether you’re violating the LoD – it’s what the extension method does that matters.

    That having been said, the code sample looks just fine to me – no smell whatsoever.