Curried Object Violates Demeter

I have not looked at the paper, but a CurriedObject seems to be in pretty strong opposition to the LawOfDemeter. Thoughts? -- BillTrost

I don't see why it would ... LoD says that you don't rip the guts out of another object and send messages to them. A CurriedObject is bound to the original, not to its guts. Say more about this concern, please? -- RonJeffries

Well, the LoD says you're not supposed to call a method to get an object you then call methods on. The part one might forget is that it's perfectly kosher to call a method to create an object you then call methods on. (You can play with toys you made yourself. How else are you going to make them than to call methods? Inline assembly?)

That's creating a local variable and using methods on it - perfectly within the rules of demeter, I don't think you've made you point very well, maybe a code sample?

  Creating a local variable is different from creating of an object.

That's just not a logical statement. In an OO langage, variables are most certainly objects. An int/double/date/etc... are all objects, all with methods.

eg: myParent.printerList.createNewPrinter().print(myPage)

That creates a new printer object without assigning it to a variable. The demeter violation is myParent.printerList.createNewPrinter(), it's not the call to .print(myPage). If that were just PrinterFactory?.CreateNewPrinter?().Print(myPage), it would be fine.

CurriedObjects? seem like another way to look at FlyweightPattern to me...


Example of CurriedFunction:

 >sum a b = a + b
 sum: real * real -> real

>sum 1 2 3

>sum 1 anonymous: real -> real

Therefore creating "sum 1" and then using it on the same method is exactly using the result of a message: sum method on 1 object.

Well, not exactly, because "sum 1" is a function (method) to be applied on object 2 (when saying sum 1 2), so it is the method that is generated on the fly. This doesn't break LawOfDemeter as it is stated, because LawOfDemeter doesn't even think that it is possible to generate new methods on the fly. It certainly looks messier than breaking LawOfDemeter, but this is applied all the time in FunctionalProgramming with good results.

Effectively CurriedObject violates LawOfDemeter.

I disagree. The LawOfDemeter also allows you to call methods on objects given to you, and says nothing restrictive about passing along an object that was given to you, i.e. currying. Because of this, currying is perfectly within the bounds of LawOfDemeter.

Mmmhh, so when all methods return brand new objects, you can type:

   a.bee().cee().dee().ee().fee(); 
instead of:
   a.beeCeeDeeEeFee();
I thought this was exactly what LawOfDemeter was trying to avoid.

-- GuillermoSchwarz

I think your example is bad. You're taking things too literal, you need to consider the spirit of demeter. It's to reduce coupling and increase encapsulation, if you need to get to "fee" from "a" with a long chain of calls, that's a demeter violation, and it points to a bad model. Don't just add a bunch of delegation methods to hide the call chain, change the model to eliminate the chain. Demeter violations usually mean your design is bad.

Well, how can the code where that chain of calls exists guarentee that each of those methods always returns a new object? And still returns a new object today, and will also tomorrow? That is exactly the kind of coupling that Demeter is trying to avoid. But there is no currying in your example, so it doesn't seem to support or contradict the claim.

 f 1 2 3 4 5 6
and that would be equivalent to:
 (((((f 1) 2) 3) 4) 5) 6)
which is exactly like gathering a resulting function (method) and applying it on another object. Demeter prohibits calling methods on resulting objects, not calling resulting methods on given objects, so maybe CurriedFunction does not violate Demeter. But please consider that a function is an object (at least in a FunctionalProgrammingLanguage sense), so maybe, just maybe, Demeter is a bit too strong.

The above example in Java:

 f( 1, 2, 3, 4, 5, 6 );
it just violates the rule that says that no method should have more than 3 parameters.

Also this page is about CurriedObjects, not CurriedFunctions. A CurriedObject is one that is half generated by the constructor and then it is built using several method calls.


EditText of this page (last edited May 28, 2004) or FindPage with title or text search