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