views:

97

answers:

2

The LOD description I've seen (for example, Wikipedia, C2 Wiki) talk about not calling methods. To quote Wikipedia:

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
- a global variable, accessible by O, in the scope of M

But what about accessing properties, variables or enums? For example, given this:

class FirstClass {
    public SecondClass GetRelatedClass() {
        return new SecondClass();
    }

    public enum InnerEnum {
        Violated,
        NotViolated
    }
}

class SecondClass {
    public int Property {get; set;}
    public string _variable = "Danny Demeter";
}

Are any/all of these LOD violations? (Ignore the direct variable access for now, if you can..)

void Violate(FirstClass first) {
    SecondClass second = first.GetRelatedClass();
    var x = second.Property;
    var y = second._variable;
    var z = FirstClass.InnerEnum.Violated;
}

I wouldn't do the first two (whether 'official' violations or not), not quite so sure about the enum though.

+5  A: 

I can't answer on the enum question -- I seem to recall that the standard recommendation is not to define enums inside of a class.

For properties, you can really consider properties to be shortcuts to methods (getProperty() and setProperty(value)). In that case, your answer is that property accesses are violations.

For fields (variables), once again, common practice is not to expose them but rather to use properties, really exposing fields is a violation of encapsulation.

Ultimately though, the intent of the Law of Demeter is to limit the knowledge of implementation between classes. To me that means all of your examples are violations.

Chris Shaffer
Indeed. The reason why the C2 Wiki doesn't talk about instance variables, fields, properties, enums, attributes, slots etc. is simply because a large portion of the members of that community are old Smalltalkers where all of those are private anyway. Fields, attributes, instance variables, slots or whatever they are called are isomorphic to a pair of getter/setter methods anyway, and since they *are* isomorphic it should be obvious that switching back and forth between a field and a getter should not change the Demeter properties in any way. A field should be simply treated as a method.
Jörg W Mittag
+1  A: 

FWIW...

Violation #1 (x) looks like a rough service location pattern, so I would suspect that the example is not a violation.

Violation #2 (y) looks like a class design smell, but generally doesn't demonstrate anything above what violation #1 demonstrates.

I don't think that public enumerations (z), however they are scoped, would count against LOD here.

Do you have a better real world example to demonstrate your concerns? Without proper context, simple code examples could be ok, or they could violate design principles.

Dave White
Maybe, although I think it looks less like that if you write it all together (which from LOD's point of view is the same): 'x = first.GetRelatedClass().Property;'. Or perhaps service location is sometimes an LOD violation?
Grant Crofton