views:

1023

answers:

11

When is it ok to break "the law of demeter"? Any examples??

+6  A: 

This is a hard question. Basically the law of demeter is more a convention than a strict rule. It is true that following it allows for a better OOP and results in a more decoupled code. In my experience, it's common to break this rule when you're working with User Interfaces. If you're creating your system from scratch, it's easier to attend this rule. Remember that like design patterns, this rule is not an absolute.

Stefano Driussi
+2  A: 

The only programming law I follow is KISS (Keep It Simple, Stupid or i prefer to call it, Keep it simply stupid).

At the end of the day what really matters is that: 1 - The software works. 2 - No bugs in it (or as minimal as possible) 3 - Your code is easy to read/understand and easy to modify.

So, I think that you might follow this or that convention, as long as it serves you, not the other way around.

Sergio
-1 I disagree with this because, if you follow the law of demeter, you make your design slightly more complex (remove public field, add a method). You reduce coupling but wind up with more code/indirection.
Outlaw Programmer
If KISS is your only law, you might like this: http://thedailywtf.com/Articles/FrontAhead-Design.aspx :-)
DR
+1 for the three points you mentioned in your second paragraph, and for your conclusion.
e.James
KISS = Keep It Surreal, Sergio!
Steven A. Lowe
I also must state that i am a perfectionist. While my first priority is to keep my code simple and easy to maintain i also try to write the best code possible, as long as it makes sense.
Sergio
While fanatically adhering to Law of Demeter's simplification to "one dot"-rule is bad for the code, I generally consider the ideology behind it sound.Little indirection goes a long way towards keeping a project maintainable. Structs are of course a exception to the rule, no reason to hide those.
Jukka Dahlbom
+11  A: 

It's okay to break any rule when you understand the consequences and are willing to either deal with the fallout or fix it. Usually that means living with it forever until you get fired or quit or refactor.

Usually people break rules without understanding higher goals or a more global context. That's when it is bad. Unfortunately, it takes discipline and experience to not break rules unnecessarily, and experience is not contagious.

MSN

MSN
+7  A: 

Whenever it makes your code more readable / maintainable. The Law of Demeter is (IMHO) somewhat schizophrenic. On the one hand, it is extremely detailed. On the other hand, it's only a very general rule because in many contexts it simply doesn't apply. Method chaining may actually be a good thing. Consider the following builder class application (notice that in this code, each method actually returns a different type so this code violates the Law of Demeter).

Date date = Date.year(2009).month(1).day(1);

First, what are the advantages of such a pattern over the following construct?

Date date = new Date(2009, 1, 1);
  • It improves readability,
  • It improves compile-time type safety, and
  • It allows Date very easily to be an immutable class which in itself has a lot of advantages.

Now, applying the Law of Demeter would yield code that is (again, IMHO) neither as readable nor as maintainable and simply offers not a single advantage over the terse form.

DateYearProxy y = Date.year(2009);
DateMonthProxy m = y.month(1);
Date date = m.day(1);

Discuss.

Konrad Rudolph
Your example isn't breaking the Law, is it? The Law is about calling methods down the hierarchy, not about chaining methods at one level of the hierarchy. That is, if month was a sub-class of Date, and day a sub-class of month within Date, then it would break the Law, but as it stands, it is fine.
Jonathan Leffler
A C++ example: cout << "abc" << i << "def"; Not breaking the law - but is chaining methods.
Jonathan Leffler
@Jonathan: I might have always understood the LoD wrong, then. But I don't think so. No definitions that I know restrict themselves to subtypes. See also the German Wikipedia article, it gives an example equivalent to mine.
Konrad Rudolph
@Konrad: 300 characters ain't gonna be enough! I've gone to the LoD Wikipedia page, and is says "one dot". It also has a detailed list of 4 criteria, and I'd have thought that "one dot" was an over-simplification of the 4 criteria. It also says there is debate about the approach.
Jonathan Leffler
@Jonathan: well, these four detailed criteria (of when to allow member access) implicitly exlude *all* instances of other types, not only of subtypes.
Konrad Rudolph
… and the whole page (en) doesn't contain a single reference to either in the following list: “(sub|super)(class|type)”, “inherit”, “derive”, “base”, “interface”, “implement” or “hierarchy”.
Konrad Rudolph
-1 Method chaining doesn't break the LoD just because you have more than one dot per line. Each method is part of the same class. I prefer immutability but for some classes, like Java's ByteBuffer, chaining just makes things cleaner.
Outlaw Programmer
Outlaw Programmer: No, that's the whole point! In the above example these are *different* classes! DateYearProxy, DateMonthProxy and so on. As I have already written in my original posting.
Konrad Rudolph
Isn't the law of Demeter about reducing dependencies and least knowledge ? To me, introducing DateYearProxy and DateMonthProxy classes (or interfaces) looks worse than method chaining regarding the law of Demeter. I might be wrong though.
Sébastien RoccaSerra
Sébastien: I'm interested: why does this look bad to you? Actually, it makes the code more type safe and more explicit, thus more robust. I don't see any downsides (for the client). By the way, this example is taken from here: http://www.pcordes.de/?page_id=88 -- courtesy to Philipp Cordes.
Konrad Rudolph
This is a really a bad example
Greg Dean
@Greg: care to explain? I think it is actually rather good.
Konrad Rudolph
I can not imagine a situation where I would prefer the first construct to the second one. Or where I'd build a date handling class from scratch to begin with.I agree that fluent interface - when done right by returning this pointer - are useful, but chaining like that looks dirty.
Jukka Dahlbom
+2  A: 

A common example would be an object that exposes a collection that is mutable.

e.g.: customerObject.Orders.Add(order);

Scott Dowding
Well, isn't that rather the archetypal example of wht LoD is justfied and your class lacks encapsulation?
Konrad Rudolph
yes, it should be customerObject.AddOrder(order), otherwise you have to know that e.g. Orders is a collection with an Add method
Steven A. Lowe
+2  A: 

it's not ok. ever. That's why it's the Law of Demeter, not the suggestion of Demeter.

Violators will be prosecuted. ;-)

Steven A. Lowe
sigh - no sense of humor!
Steven A. Lowe
I feel your pain Steven.
gnovice
lol - cant believe this was down voted.
Greg Dean
A: 

In the shop I work at, the Law of Demeter is not even discussed. It doesn't exist.

We have a kind of intermediate API called ObjectLayer (dumb name but its stuck) that hosts the Object-Relational mapping. It uses lots of public properties, etc. It serves as the Model part of MVC. Part of the controller is grafted into ObjectLayer because it is programmable by the end user and needs to work on an alternate interface.

The GUI objects have references to the objects in ObjectLayer. These are passed around, manipulated almost at will, etc by the controller code attached to the GUI.

The mini-programming language is the only truly stable part of the interface. ObjectLayer stabalized in its form almost by accident because it works really well until someone tries to change it (not that the code is bad but half the developers have difficulty writing truly reusable code).

Joshua
+3  A: 

At some point in my career the pragmatic businessman in me started to have serious issues with the pragmatic programmer in me.

The sad truth is: If you are spending time worrying about The Law of Demeter, you are more than likely just wasting time/money. It's a good academic exercise, but only good in practice for a very limited subset of real world projects where attention to that level of design detail really matters.

Get it done, get it out the door, use it to generate revenue (monetary or otherwise). Any problems associated with the lack of adherence to The Law of Demeter can be filed under "problems I hope to have some day".

In short, almost always

Greg Dean
+1  A: 

Sorry to say but this is one law I had never heard of until this post and I don't think it is particularly widely followed in the programming community.

The wikipedia article wrote:

The guideline was invented at Northeastern University towards the end of 1987, and can be succinctly summarized as “Only talk to your immediate friends.” The fundamental notion is that a given object should assume as little as possible about the structure or properties of anything else (including its subcomponents).

I don't see any reference here to the rule being followed in the agile community, in the most influential language design groups or any place else besides Northeastern University, illustrious school though it may be.

For example, on the c2 website, someone wrote

Before reading further please see LawOfDemeterVsInformationHiding, LawOfDemeterMakesUnitTestsEasier, LawOfDemeterIsHardToUnderstand, LawOfDemeterIsTooRestrictive, LawOfDemeterAndCoupling.

Joe Soul-bringer
Did you read the whole article? I didn't understand the law correctly until I did. See in particular the "More formally..." section.
Kyralessa
+1  A: 

One case I've hit a few times where it would simply make a huge amount of stupid code:

Classes whose purpose is to round up a bunch of elements into some entity, say a customer's order.

Ok, there's an object in there for customer information. There's also one for the graphics. (CAD/CAM system) There's a third holding subdivisions in the order and these contain a fourth that are actually descriptions of the objects involved.

On the CAD side of things the descriptions of how to build the objects have virtually no effect outside the pricing engine--the rest of the program almost totally ignores the groups and works on the list of individual objects.

Note that these various data elements are virtually independent of each other, the top level container exists because there are cases where multiple plans can be loaded and the top level object contains things like I/O routines etc.

To provide routines to drill down into the various objects would be a huge waste of code. Many of the routines deal only with a smaller object and thus don't run afoul of the LoD but there are many cases where you simply need one piece of data that a couple of layers down--to provide ways around this would probably add 10k of code for no benefit other than complying with the LoD.

Loren Pechtel
A: 

Suppose you have this:

function(foo) {
   doSomethingWith(foo.bar.baz.fooBar);
   // ...
}

then if you also

doSomethingElseWith(foo)

in the same function then maybe it's not too bad.

However, clearly if you never do anything with foo, but only use it to get to fooBar, then breaking the law is bad.

Another variation of the law is "don't look for things, ask for them". (Asking for them means "require them as arguments").

See here for a good discussion.

KaptajnKold