Design Patterns – Is a Class Allowed to Return One of Its Members According to Demeter’s Law?

design-patternslaw-of-demeter

I have three questions concerning Demeter's law.

Apart from classes which were specifically appointed to return objects – such as factory and builder classes – is it okay for a method to return an object, e.g. an object held by one of the class's properties or would that violate the law of demeter (1)? And if it violates the law of demeter, would it matter if the object returned is an immutable object that represents a piece of data and contains nothing but getters for this data (2a)? Or is such a ValueObject an anti-pattern in itself, because everything that is done with the data in that class is done outside of the class (2b)?

In pseudo code:

class A {}

class B {

    private A a;

    public A getA() {
        return this.a;
    }
}

class C {

    private B b;
    private X x;

    public void main() {
        // Is it okay for B.getA to exist?
        A a = this.b.getA();

        a.doSomething();

        x.doSomethingElse(a);
    }
}

I suspect that Demeter's law forbids a pattern such as the above. What can I do to ensure that doSomethingElse() can be called while not violating the law (3)?

Best Answer

In many programming languages, all returned values are objects. As others have said, not being able to use the methods of returned objects forces you to never return anything at all. You should be asking your self, "What are the responsibilities of class A, B and C?" This is why using metasyntactic variable names like A, B and C always solicit the answer "it depends" because there is no inherit responsibilities in those terms.

You may want to look into Domain Driven Design, which will give you a more nuanced set of heuristics to reason about where functionality should go and who should be invoking what.

Your second question concerning immutable objects speaks to the notion of a
Value Object compared to an Entity object. in DDD, You can pass value objects around with almost no restrictions. This does not speak true for entity objects.

The simplistic LOD is much better expressed in DDD as the rules for accessing Aggregates. No external objects should hold references to members of aggregates. Only a root reference should be held.

DDD aside, you at least want to develop your own sets of stereotypes for your classes that are reasonable for your domain. Enforce rules about those stereotypes as you design your system.

Also always remember that all of these rules are to manage complexity, not to hamstring yourself.

Related Topic