You should categorically not be implementing chaining semantics unless your operations are non-mutating.<p>If they are mutating and you return the same object, it's possible for people to go <i>years</i> without realizing that's what's happening (no, most people don't read the manual), assigning the result to something else, reusing the original for another thing and introducing subtle bugs all over the place.<p>See the design of python's list `.sort()` returning None for this exact reason.<p>(and of course there are sometimes performance penalties to implementing non-mutating methods, so there are lots of valid cases for not implementing chaining semantics)
First, needs a (2012).<p>Second, this is the very top:<p>> Edit from 2018: The tone of this post is a little cringe-worthy to me now in retrospect, and I think that many APIs are probably clearer when you return void. Leaving this here for posterity.
The "Galaxy Brain" version of this advice is using plain old designated initialization of 'option bag' data structures. Here's a non-trivial C99 example from the sokol_gfx.h API to create a pipeline-state-object for 3D rendering:<p><pre><code> state.pip = sg_make_pipeline(&(sg_pipeline_desc){
.layout = {
.attrs = {
[ATTR_vs_position].format = SG_VERTEXFORMAT_FLOAT3,
[ATTR_vs_color0].format = SG_VERTEXFORMAT_FLOAT4
}
},
.shader = shd,
.index_type = SG_INDEXTYPE_UINT16,
.cull_mode = SG_CULLMODE_BACK,
.depth = {
.write_enabled = true,
.compare = SG_COMPAREFUNC_LESS_EQUAL,
},
.label = "cube-pipeline"
});
</code></pre>
Chaining might be useful for data processing pipelines, but not for simple data initialization tasks IMHO.
I like function chaining more. E.g. Elixir's `Map.set(map, field, value)` function combined with the `|>` operator, which feeds the value from the previous operation in to the function as the first argument:<p><pre><code> person_map
|> Map.set(:name, "Peter")
|> Map.set(:age, 37)
|> Map.set(:married, true)
</code></pre>
It's so much fun to look at a chain of generic functions working on a generic data structure, while keeping the code clear. Makes me feel all warm inside. Immutability and functional programming, ain't it nice, huh?
I like dart's cascade operator (..) a lot, that way you can chain calls on an object without the functions returning this. I'm sure other languages have something similar, kotlin has apply which feels a bit more heavy handed though.
My functional API's never return void because they're functions and immutability is the benefit there. Returning void means you're either mutating something or interacting with something thing that does. Also, chaining can be dangerous, as if it's not implemented correctly, can hide errors, or not have adequate failure tolerance, and cleanup can be a mess if a stream or connection disconnects in the middle of your chain.<p>But in an OO project, void is a really useful. If you're doing game programming, mutability is required for all but the most trivial games. And throwing in more functions and more variables on the stack isn't going to benefit anything. You click a button, the gun fires. I don't need to check the return, it add no value, adds complexity and isn't idiomatic to the language.<p>Use the right tool for the job.
Chaining is fine when building up an object, but definitely not something that should be systematically used. That's making the interface more complicated for little gain.
I work in C# but have come to a similar conclusion to his note at the top of his article.<p>C# supports extension methods, so if you want you can augment the original 3rd party class with your own (chaining in this case) methods.
Or author your own “fluent interface” on your own classes, as he’s done here.<p>I’m the end, most of the time I found I was wanting a function ‘forward composition’ operator (like F#’s |> ). And the only place the chaining methods really made sense was factory classes/methods for complex declarative configuration.<p>The only ones that stuck for us were ORM mapping declarations, and factories for setting up complex domain specific data setup in tests.
I love this kind of blog posts because not only they present different ways of doing things and a fairly sane discussion about it, but also showing the author learning from experience and telling about it.<p>Young people are very creative (mostly between ages of 15 and 25) and that creates new ideas. Experienced people test the new ideas and draw conclusions. We need both to progress, the first should be as creative as possible and the later as analytical thinking as possible. It is the innovation pipeline, the first throw the ideas, the others refine, filter and select.
There's competing incentives for API ergonimics and making mutations / ownership explicit. Kotlin's scope functions really get you the best of both worlds with this.<p>Lambdas can have a "receiver", which acts as the (implicit or explicit) `this` for the lambda.<p>`apply` even returns the object itself, so the first example could be:<p><pre><code> frame.add(FormPanel().apply {
setSize(300, 150)
add(usernameLabel)
add(usernameField)
add(passwordLabel)
add(passwordField)
})</code></pre>
This can be inefficient depending from the language and the compiler. The compiler many not always know that the this that you return is the same of the object you are calling the method to, and that can prevent further optimizations.<p>I don't see either any readability advantages of doing so, doing that just for not typing the name of the variable is nonsense, also the code is less clear to the reader (you have to know that the method that you call returns the same objects, it's not obvious, it can as well return another object, or a copy of that object). It's more explicit doing it the normal way.
You could also make a single-letter alias:<p><pre><code> auto& r = rectangle;
r.width(100);
r.height(100);
</code></pre>
I like to use very short variable names(single or 3 letters at most) but fully write out the type:<p><pre><code> Rectangle r;
</code></pre>
Which is similar in spirit to aliasing the variable.<p>"Rectangle" is probably not a good example, because rectangles are pure data used for many different purposes. So "rectangle" is often a poor variable name. But many programs use 1 type for 1 purpose, and then the type alone is enough.
Chaining works well in builder objects and perhaps in some GUI programming or some other very specialized cases but most of the classes I write don't have sufficient mutable state to make this kind of thing worth it.<p>My advice would be to almost always start with a void (unless builder objects) and then add chaining if the evolution of your API dictates that chaining together calls would be a common enough usecase.
A better reason to not return void is that it will make you think more about immutability and side-effects. Not returning void allow you to reduce the hidden state changes or at least to manage them better
These tricks ate necessary due to lack of property assignment syntax in languages such as Java. C# does not have this problem and they may start pointing fingers.