3

I'm writing a C# style guide for my team and I'm trying to describe the benefits of side-effect-free functional-style methods. I want to include online references to back up the suggestions, but I can't seem to Google the kind of functional method chaining I have in mind.

When I think "method chain", I imagine something like this (in Ruby)

userInput.chomp.downcase.split(",").map(&:to_i)[3].to_s(16)

where each method returns a new object (maybe even of a different class) and everything is side-effect-free, so it's like composing functions in a functional language. Writing function-like methods make these kinds of chains very easy to construct and, in my experience, greatly simplify code.

But when I Google "C# method chaining", I keep finding stuff like this

myObj.AddItem(mItem).AddItem(mItem2).AddItem(mItem3);

where each method mutates and returns the receiver. This is pretty much the opposite of functional programming and, if anything, is the kind of thing I want to discourage on my team. Even when I Google "C# functional method chaining", the top result is blog post about StringBuilder, which relies entirely on the side-effects of each method call!

Is there a different term for this than just "method chaining"? Or, even better, is there some place that documents the benefits of this style?

  • 2
    What if you say that you should only do method chaining on immutable objects? – Matthew Oct 17 '17 at 14:17
  • Your first example is a violation of the Principle of least knowledge or the Law of Demeter wiki.c2.com/?LawOfDemeter The second is a fluent interface. They are separate things, that work differently and should appear differently in a code guidelines. The first should be avoided, the second potentially useful. – Martin Spamer Oct 17 '17 at 14:24
  • I'd suggest the term commonly used to indicate function chaining and immutability is functional composition. – David Arno Oct 17 '17 at 14:36
  • 1
    @MartinSpamer I agree that my first example violates the Law of Demeter, but not all method chains necessarily do. A better example would have been LINQ, where you call several query methods in a row. – Max Oct 17 '17 at 14:37
  • 1
    I think this could be a pretty short style guide "use F#" – Ewan Oct 17 '17 at 21:30
4

The commonly used name for this is a Fluent Interface. In the functional world, it's simply Function Composition.

But outside of the functional world, it has few good applicable uses. Yeah, it's great for enumerables. And it's workable for date/times. But mostly it's a vile construct that is abused to create code that is overly clever, or "readable" (but only for a select few familiar with your weird in-house fluent library).

Side effect free functional-style methods (pure functions especially) do have huge benefits around testability, reusability, robustness, concurrency, performance... focus on those, not this syntactic fluffery.

  • My understanding of a fluent interface is that must not be functional, and always mutates the receiver. – Max Oct 17 '17 at 14:32
  • 4
    @Max, that's a silly restriction. Do what works best in the situation. If mutating the receiver makes sense; do so. If not; don't. For example, the fluent style of LINQ clearly is a fluent interface, yet it is immutable in nature. – David Arno Oct 17 '17 at 14:37
  • 1
    I agree with @DavidArno; making these sorts of arbitrary restrictions in a style guide about very specific techiques seems like a bit of an overreach. If these considerations are important, make them a part of a code review and evaluate them on a case-by-case basis. Let the team help you decide whether they should be part of their tool belt, or eliminated altogether. – Robert Harvey Oct 17 '17 at 15:11
  • Outside the functional world, it has always been common to use this type of API for mathematical objects, as they are typically immutable. Sometimes you need mutable versions of the API for performance reasons. For example, vector and matrix libraries for linear algebra. However, it was not called fluent until more recently. – Frank Hileman Oct 17 '17 at 16:42
  • I still see the fluent interface more commonly used for just a single class/interface. It's intended to be used for several chained calls all in the same class/interface. I'm talking about chaining methods in general across several classes. – Max Oct 17 '17 at 16:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.