Thursday, January 31, 2008 #

Fluent Interface Reservations

Reading Hanselman’s latest, still trying to work out whether I actually like fluent interfaces. The MBUnit example is particularly ugly, to my eyes:

testObject.ShouldBeTheSameObjectAs(targetObject).And.ShouldBeEqualTo(testObject).And.ShouldSatisfy(x => x is Object);

Recently I've been noodling about with writing a unit testing library in JavaScript (what's wrong with jsUnit? Nothing, obviously. Doesn't stop me noodling about.). I ended up with some experimental syntax like this:

// function to test
function add(a, b)
{
   return a + b; } // tests with (add) {
   ResultOf(0, 0).Is(0,  '0 + 0 = 0');
   ResultOf(2, 2).Is(4,  '2 + 2 = 4');
ResultOf(-3, 4).Is(1,  '-3 + 4 = 1'); }

Which is quite nice, but then I had to go and spoil it with some hideously tortuous hacking to support testing for JavaScript prototype/constructor-style OO:

// class Person to test
function Person(name, age)
{
   this.Name = name;
this.Age = age; } Person.prototype.Say = function(message) {
return this.Name + " says '" + message + "'"; } // tests with (Person) {
   AfterConstructing("Bob", 21)
   .Property("Name").Is("Bob", "set name to Bob")
   .Property("Age").Is(21, "set age to 21")
   .Calling("Say").With("Hi!").Returns("Bob says 'Hi!'", "Bob has a say method");



  
// or, alternatively:
with (Instance("Marjorie", 30))
{
Property("Name").Is("Marjorie ", "set name to Marjorie ");
Property("Age").Is(30, "set age to 30");
with (Say)
{
ResultOf("Hi!").Is("Marjorie says 'Hi!'", "Marjorie has a say method");
}
} }

So I did all that, and now I can’t decide if the fluent interface stuff is actually a good idea or not. I’m particularly not fond of

   .Calling("Say").With("Hi!").Returns("Bob says 'Hi!'", "Bob has a say method");

I know with my well-attested love for jQuery I should be all about the method-chaining, too, but I actually think I prefer

with (foo)
{
   X();
Y();
Z(); }

to

foo
.X()
.Y()
.Z();

too...

Am I just getting too old for fluent interfaces?

I think the point is that API design is all about making your functionality available in ways that developers can access using comfortable syntax. If a fluent approach makes sense, then go for it, but it doesn't help to shoehorn fluent approaches onto an API at the expense of enabling other syntaxes.

When I finally get round to completing my work on Flogo, I'll also have something to say about how method-chaining APIs let you do neat stuff in C# 3.0...

posted @ Thursday, January 31, 2008 11:12 AM | Feedback (0)