views:

238

answers:

7

I really love the philosophy of chaining methods, like jQuery emphasys in its library. I found it quite elegant and clear.

Being primarily Java developper, I've always wondering myself why this practice was not more used in this language. For example, the Collection interface was not designed in the that way (for adding/removing methods), and I found it quite sad.

Is there real cons against this practice or is it just something that has not enough "sex-appeal" before?

+1  A: 

I really like this approach as well. The only downside I can think of is that it seems a bit awkward at times to 'return this' at the end of every method. For JQuery, for example, it makes it slightly awkward to allow plugins, because you have to say "make sure you don't forget your returns!!" but there's no good way to catch it at compile time.

chessguy
it would be nice if java had a pragma which said 'return this if no other return value was specified'? Or more likely a compiler warning.
David Medinets
+1  A: 

The only con is you loose the return type, so Chaining is good for operations that do things, but not good for operations that calculate things.

Another issue is, with chaining the compiler can't as easily determine trivial function calls for inlining. But as I said if your chaining does operations, and not calculations, then its most likely that the compiler wouldn't change anything anyways.

Robert Gould
A: 

JavaScript is (more or less) a functional language, with functions as first-class citizens.
Adding/removing methods to objects, passing functions as parameters, all this is natural for this language.

On the other hand, Java is strictly OO, a function cannot exist outside of a class. Using inheritance, composition and interfaces is a more natural way for this language.

PhiLho
And? what's the relation between OO/functionnal concept and the way of writing method call? Does the paradigm really impact on using a.b().c() rather than x = a.b(); x.c() ? I don't think so.
gizmo
oops, sorry, wrong example. I wanted to write a.b(); a.c() of course.
gizmo
Ah, I though of chaining in the sense of overriding a function, then calling the old function at the end of the new one, like when bubbling up events. Chaining like you describe is indeed possible in Java (and quite common), as long as the functions return the proper object.
PhiLho
+3  A: 

IMO it is painful to debug as you tend to have no intermediary variables for inspection.

leppie
As far as I know, all the actual IDE provide step-in/step-out features to ease the debugging of chainable method as well as method call used as parameters.
gizmo
A: 

Chainable methods are another great tool in our design toolbag. Just make sure you don't run into the common "I have a hammer, therefore every problem is a nail" design mess.

Every design problem isn't solved by chainable methods. Sometimes it does help make an interface easier to use (ie. the collection issue you mentioned). Sometimes it doesn't. The trick is figuring out which case applies.

Jonathan
A: 

Martin Fowler discusses this topic as 'fluent interfaces' at http://www.martinfowler.com/bliki/FluentInterface.html. One main issue is that fluent interfaces are designed for humans, therefore frameworks like Spring are not able to understand them. Simplistically using a fluent interface provides maintainability in one sense (readability) but loses maintainability in another (flexibility).

David Medinets
+2  A: 

There's a common problem with chainable methods and inheritance. Assume you have a class C whose methods F1(), F2(), etc. return a C. When you derive class D from C, you want the methods F1, F2, etc to now return a D so that D's chainable methods can be called anywhere in the chain.

LBushkin
In C++ this is generally solved with CRTP: http://en.wikipedia.org/wiki/Curiously_Recurring_Template_Pattern
Jasper Bekkers
True, unfortunately, .NET generics do not allow template parameters to be used in the base class spec for a generic class. Eric Lippert has a good explanation on his blog (http://blogs.msdn.com/ericlipper) why this restriction is unavoidable in the .NET implementation of generics.
LBushkin
If C# ever supports covariant return types this may become less of an issue. In the meantime, you can use the new keyword to hide base methods and replace them with versions that use the appropriate return type. I would suggest calling the base class in these cases to avoid duplicating code.
LBushkin