I notice that more and more frameworks, toolkits and libraries use fluent interfaces. Here are two examples:
Rhino Mocks
1: [Test]
2: public void SomeTest() {
3: var mocks = new MockRepository();
4: var service = mocks.CreateMock<IAccountService>();
5: using (mocks.Record()) {
6: Expect
7: .Call(service.Login(null, null))
8: .Constraints(Is.NotNull() & Is.NotSame("foo"), Is.NotNull())
9: .Repeat.AtLeastOnce()
10: .Return(LoginResult.Failed);
11: // ...
12: }
13: }
Castle Windsor
1: var container = new WindsorContainer();
2: container.Register(
3: Component
4: .For<IAppContext>()
5: .ImplementedBy<AppContext>()
6: .Parameters(Parameter.ForKey("synchronized").Eq("true")));
[Maybe its not surprising that both libraries use fluent interfaces. Ayende Rahien, creator of Rhino Mocks, is also a huge contributor the the Castle project. ]
Most of the time I really like fluent interfaces. Not only does the code reveal its intention more clearly - at least most of the time. You also get support while writing the code: depending on the FI, the object returned by a call to an FI method might only a reduced set of methods that are meaningful at that point which drives you more into the correct direction.
If you write a FI for a library yourself, be sure to not overdo it. Keep it simple and don't try to get everything FI-esque just because you know how to do it. One possible pitfall of fluent interfaces is that it is not always clear how many times a method should be called. For example, imagine the case where you have a Client class that can have multiple order Objects, each containing multiple OrderLine objects. This resembles the example of Martin Fowler. You decide to provide an FI for the operation of adding configuring an order, like so:
1: var c = new Client();
2: c.AddOrder()
3: .WithLine(10, "Apple", 0.49m)
4: .WithLine(4, "Banana", 0.59m)
5: .ExpressDelivery();
This looks certainly more fluent than the "conventional" way:
1: var client = new Client();
2: var order = new Order();
3: order.ExpressDelivery = true;
4: var line = new OrderLine();
5: line.Quantity = 10;
6: line.UnitCost = 0.49m;
7: line.Product = "Apple";
8: order.AddLine(line);
9:
10: line = new OrderLine();
11: line.Quantity = 5;
12: line.UnitCost = 0.59m;
13: line.Product = "Banana";
14: order.AddLine(line);
15:
16: client.AddOrder(order);
However, in the FI it is not that obvious that ExpressDelivery() should be called only once. Maybe the user wants to deliver the order twice (ok, the example is bad). The non-fluent version does not have this potential confusion. No one would assign order.ExpressDelivery multiple times and expect it to generate multiple deliveries.
Still, I think this is a small price to pay compared with the improved readability gained by FI.
Of course, the non-FI example is a worst case scenario. For example, you could provide constructor arguments to OrderLine. With C# 3.0 and object/collection initializers the example can be approved even more:
1: var client = new Client();
2: var order = new Order {
3: new OrderLine {Quantity = 10, UnitCost = 0.49m, Product = "Apple"},
4: new OrderLine {Quantity = 5, UnitCost = 0.59m, Product = "Banana"}
5: };
6: order.ExpressDelivery = true;
7: client.AddOrder(order);
I even find the object initializer more expressive than the WithLine FI. I'm really looking forward to all the future APIs that will leverage fluent interfaces and C# 3.0 syntax features.