So, in a general, strongly-typed language this might look like:
public class Foo {
public Foo FluentMethod() {
// do some stuff
return this;
}
}
For simplicity's sake, I will use Ruby for the rest of this post. In the Ruby language this would look more like:
class Foo
def fluent_method()
# do some stuff
self
end
end
One of the biggest benefits of fluent interfaces is that they make change easier. For example consider the following, non-fluent code:
a_chicken = Chicken.new mr_fox = Fox.new mr_fox.is_quite(:fantastic) mr_fox.lives_in(:a_tree) mr_fox.eat(a_chicken)
This code annoys me (somewhat) because
mr_fox appears on four lines, which implies that if you wanted to change it, you would have to change each of the four lines. Also, if I fat-fingered one of those references, I would waste time fixing it when the interpreter caught it. Here comes fluent to the rescue:
a_chicken = Chicken.new Fox.new .is_quite(:fantastic) .lives_in(:a_tree) .eat(a_chicken)
Isn't that better?
mr_fox doesn't even exist anymore. Also, in my humble opinion, this style of method chaining greatly improves readability. There's also a hidden benefit in this example: fluent interfaces logically group operations of a single object onto, technically, one SLOC. For example, if I didn't use fluent method chaining, there's nothing stopping me from mixing
Chicken logic with Fox logic:a_chicken = Chicken.new
mr_fox = Fox.new
mr_fox.is_quite(:fantastic)
a_chicken.is_named("rodrick")
mr_fox.lives_in(:a_tree)
a_chicken.still_has_its_head(true)
mr_fox.eat(a_chicken)
But if I made
Fox fluent and described it with method chaining then there's no way for me to interleave Chicken logic, and, frankly, create a mess:
a_chicken = Chicken.new
a_chicken.is_named("rodrick")
a_chicken.still_has_its_head(:eggs)
Fox.new
.is_quite(:fantastic)
.lives_in(:a_tree)
.eat(a_chicken)
Of course, I (at this point in my software career) would probably make
Chicken fluent as well, but I think it's fairly clear what that would look like at this point.Hopefully you've come to dig fluent interfaces (at least a little) at this point. To me it's pretty cool that (in dynamic languages) implementing a fluent interface can be as simple as tacking a four-letter-word (
self) on the end of methods whose return value we found otherwise uninteresting.
No comments:
Post a Comment