Confusion about Law of Demeter

Started by
26 comments, last by Lewis_1986 12 years, 7 months ago
Does this code violates the Law of Demeter?



void object::foo()
{
//...

std::string s1 = "Hello World!";

string s2 = s1.substr(0, 5);

// process string s2...
//.....
}


The function foo() calls a function on object string s1, which returns s2 to be further processed in this function...This looks like violating the Demeter law since it calls functions on an object
returned by another function. If so then what should be the alternative?

Thanks.
Advertisement
s1 is stored locally within foo(), so anything that accesses s1's member functions is legit within foo().

A violation would be if you had something like:

struct bletch
{
bletch(const std::string& contents)
: Something(contents)
{ }

std::string Something;
};

void foo()
{
bletch b;
std::cout << b.Something.substr(0, 5); // Directly accessing a method of bletch's members is forbidden
}


However, the practical applications of the Law of Demeter are often limited. It is much more useful to work in terms of layered abstractions than strict adherence to LoD style. Rather than demanding that you never access nested members, for instance (which can become really impractical in real code), you build everything like layers of lasagna. One layer may access the layer below it, but no layer may access the layer above it. Reaching more than one layer down is permissible but should be minimized when it makes sense.

Wielder of the Sacred Wands
[Work - ArenaNet] [Epoch Language] [Scribblings]

Very helpful. Thanks!
Short version, don't do this:

foo->bar->baz->sayHello();

foo().getBar().getBaz().sayHello()


Stick to single level of indirection (aka one dot or one arrow).
Now this triggered another question. If the data member Something is returned by getters as a reference which is the case of managed languages like C# or JAVA, then it's a violation of the Demeter law. However, in case of C++ where we can get a copy of the object it's not. So although both languages used getters, it's the language semantics that determines this kind of violation. Correct?
Not quite.

foo.GetSomething().bar(); // violation
foo.DoBarOnSomething(); // ok


This holds regardless of language semantics. It doesn't matter what GetSomething() returns (a value, a reference, a const reference) because the very existence of GetSomething() means you're violating the one-degree-of-separation clause of the Law of Demeter.

Remember, it is better to tell an object to do something to itself than to ask it for information so you can do the same operation externally.

Wielder of the Sacred Wands
[Work - ArenaNet] [Epoch Language] [Scribblings]

Incorrect. The Law of Demeter isn't about whether the data you're accessing is a copy or a reference, it's about maintaining a coherent abstraction and limiting the impact of change.
I'm now more confused. In one of the text books, it says that calling a method on an object not created by the function itself violates the law.

In this case

Something s = obj.GetSomething();

s.DoSomething();

Now if "s" was a copy rather than a reference it would be an object created inside the caller method and hence does not violate the Demeter. Otherwise, it's manipulating "obj's" data member directly.

I'm now more confused. In one of the text books, it says that calling a method on an object not created by the function itself violates the law.
Clearly that definition is not right as it would mean calling anything on a global variable would be a violation.

It's really all about how many dots or arrows you have following from an object or pointer, in an expression. > 1 = bad.
"In order to understand recursion, you must first understand recursion."
My website dedicated to sorting algorithms
Specifically from the "Clean Code," by Robert C. Martin, page 98, where it explains that it's not only about dots...

Something fishy about the law of Demeter???

Any good reference?

This topic is closed to new replies.

Advertisement