14

I recently suggested a method of chaining be implemented for a certain class in a certain project so readability of the code could be improved. I got a "fluent interfaces should not be implemented just for convenience, but for semantics" answer and had my suggestion shot down. I answered that I was not suggesting a fluent interface but method chaining itself (both can be confused with each other, read at bottom) to improve readability and coding comfort, suggestion was shot down again.

Anyhow, this got me thinking that maybe I could be incurring in a bad practice by always returning "this" in methods that are not supposed to return anything (e.g. setters).

My question is: can applying the previous convention be regarded as bad practice or abuse?, why?. I don't think there are any performance drawbacks, or are there?.

4
  • 2
    Look at this question for a nice discussion programmers.stackexchange.com/questions/48419/…
    – KeesDijk
    Commented May 30, 2011 at 8:40
  • @KeesDijk Thanks, I edited my question a little so its not to similar to that one, as I'm more interested in the case of chaining methods from the same class Commented May 30, 2011 at 9:01
  • 1
    at SO, they told me, that chaining is not for C++ - stackoverflow.com/questions/5760551/… - what do you think about?
    – kagali-san
    Commented May 30, 2011 at 16:05
  • 1
    @mhambra It looks like you would only need to be careful when implementing method chaining and define clear standards for that. Commented May 30, 2011 at 21:49

4 Answers 4

10

No

As Kent Beck points out, code is read far more often than it is written.

If method chaining makes your code more readable, then use method chaining.

4
  • 1
    Great book.. +1 Commented May 30, 2011 at 18:25
  • 5
    BUT, what if your are the only one finding method chaining more readable? If this is a matter of sytilistic issue, then you'll have stick to a set of coding conventions: this means, writing in the same fashion as existing code, for consistency.
    – coredump
    Commented Nov 9, 2014 at 19:43
  • @coredump It sounds like the OP's already been told to do that, but I think Steven was just saying this for if method chaining makes it more readable. Commented Dec 16, 2014 at 13:57
  • 1
    @Panzercrisis OP's been told to refrain using method chaining due to convenience vs. semantics. Steven's answer basically says "do it anyway" and only consider readability of OP's code by itself, without considering the team's opinion or consistency. What if OP wants to rewrite every existing class in the project so that it suits his taste regarding code readability? That's how I understand the convenience/semantics argument: there should be a "technical" reason to have method chaining (btw, that argument also sounds as if the other person is making up an an excuse for his/her own preferences)
    – coredump
    Commented Dec 16, 2014 at 14:55
9

Yes, there are drawbacks

Code that is easy to read is good, but also beware of what the code communicates as well. When an object's methods always return the object, it communicates a couple of things:

  1. I require advanced configuration that isn't necessarily obvious in which order things should be set or configured
  2. Each subsequent method call builds on the last

Valid Use Case: Ad Hoc Database Queries

Class libraries exist in most every language that allow you to query a database without resorting to hard coded SQL. Take the Entity Framework for .NET as an example:

DBContext db = new DBContext();
List<Post> posts = db.Posts
    .Where(post => post.Title.Contains("Test"))
    .OrderBy(post => post.DateCreated)
    .ToList();

This is a fluent interface where each subsequent method call builds on the previous one. Reading these calls logically makes sense in the context of querying a database.

Invalid Use Case: Syntactical Sugar For Setting Properties

Now let's use the same pattern with the Post class:

public class Post
{
    public string Title { get; set; }
    public DateTime DateCreated { get; set; }
    public string Body { get; set; }

    public Post SetTitle(string title)
    {
        Title = title;

        return this;
    }

    public Post SetDateCreated(DateTime created)
    {
        DateCreated = created;

        return this;
    }

    public Post SetBody(string body)
    {
        Body = body;

        return this;
    }
}

Now let's look at how you would use this class:

Post post = new Post()
    .SetTitle("Test")
    .SetDateCreated(DateTime.Now)
    .SetBody("Just a test");

When I see this code, I immediately ask this question: "After calling SetBody, does it query the database? Do I need to call another method to say 'I'm done?'"

What do the chained method calls communicate to the code using the Post class?

  1. I have a complicated setup
  2. Each method call builds on the previous one

Is this actually true? No. The Post class does not have a complicated setup. Setting the title, date created and body do not build on each other towards a more complicated end goal. You've mashed a square peg into a round hole.

The drawback to self-referential method chaining is that you communicate that multiple method calls are required to do something, and that each call builds off the last. If this is not true, then method chaining could be communicating the wrong thing to other programmers.

When your coworkers said:

Fluent interfaces should not be implemented just for convenience, but for semantics

They were absolutely correct. A fluent interface, or method chaining, communicates something in and of itself which might not be true.

10
  • This assumes that method chaining and complex configuration always go hand in hand. They're distinct entities and the presence of one should not make you assume the other.
    – Jack
    Commented Dec 16, 2014 at 14:05
  • It's not just "complex configuration," it's also "subsequent method calls build off the previous one". Method chaining has a meta communication about it that isn't always true to the purpose of a class. Commented Dec 16, 2014 at 14:07
  • 1
    Subsequent method calls building off of previous ones is distinct from method chaining as well, and I don't think that treating the syntax of method chaining as strong communication for the semantics of order-dependent series of side-effecting operations is reliable or useful. It's a syntactic shorthand, nothing more. Use it where it makes things shorter and more readable.
    – Jack
    Commented Dec 16, 2014 at 14:16
  • 1
    I understand you think method chaining is separate, but I'm saying that other programmers who weren't inside your head and use other class libraries that do implement method chaining for these reasons could end up making assumptions about your code that are untrue. Be aware that method chaining could imply something that you, the code author, did not intend. Code that communicates clearly is just as important as code that is easy to read. Don't sacrifice one for the other. Commented Dec 16, 2014 at 14:24
  • 1
    When an object's methods always return the object, it communicates a couple of things - I think this is a personal opinion; it's hard to claim that everyone looking at chained methods will assume the same things.
    – Sam Dufel
    Commented Dec 16, 2014 at 19:47
1

The main drawback is a loss of clarity. For instance:

x.foo();
x.bar();
x.baz();

Since none of those statements return a value (or if they do, it's been ignored), they can only be useful if they produce side effects. Contrast that to:

x.foo()
 .bar()
 .baz();

First, it's not clear that bar and baz operate on objects of the same type as x, unless you know for a fact that x's class is the only class with those methods. Even if that's the case, it's not clear the methods operate on x, or new objects.

Highlighting the parts of the code that have side effects is useful, since you need to track those side effects to reason about the program. You have to weigh the potential loss of clarity against the potential gain in ease of writing code, but also consider that code is read more than it's written.

0

Consider all the stylistic elements of programming languages (as opposed to hand-coding machine language), and it weakens the "semantics not convenience" argument.

A whole lot of what we do as engineers is providing convenience around semantics.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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