13

What is a fluent interface? I can't find a good definition of this, but all I get are long code examples in a language I am not very familiar with (e.g. C++).

Also, what is a leaky abstraction?

Thanks

Lasse V. Karlsen
  • 380,855
  • 102
  • 628
  • 825
GurdeepS
  • 65,107
  • 109
  • 251
  • 387

7 Answers7

27

A fluent interface is an API that allows you to write code that reads more or less like normal English. For example:

Find.All.Questions(Where.IsAnswered == true);

Method-chaining is usually used as part of the implementation, but there is more to it than that. To quote Fowler:

I've also noticed a common misconception - many people seem to equate fluent interfaces with Method Chaining. Certainly chaining is a common technique to use with fluent interfaces, but true fluency is much more than that.

It is also often called an internal DSL, since the syntax resembles that of a DSL, but it is implemented inside the host language instead of being processed by a parser.

Rasmus Faber
  • 48,631
  • 24
  • 141
  • 189
18

A leaky abstraction is an abstraction where the details of the underlying reality often "leaks through".

All abstractions lie more or less, but sometimes the abstraction is such a bad fit to the underlying reality, that it causes more harm than it helps.

A simple example of a "leak" in an abstraction might be the usual float type. It seems to represent general real numbers and you can use it to perform basic calculations. But at some time you encounter a scenario where 1/3*3 != 1 or 1 + 10^-20 = 1. That is when the actual implementation details leak through and the abstraction breaks.

Rasmus Faber
  • 48,631
  • 24
  • 141
  • 189
9

A fluent interface a term Eric Evans coined and it's just another name for method chaining. Martin Fowler wrote a couple of articles on this subject, but it roughly looks like this:

m_Window = window::with()
    .width(l_Width)
    .height(l_Height)
    .title("default window")
    .left(200)
    .top(200)
.create();

Fluent interface are generally used to create named parameters in a language that doesn't support them (the Named Parameter Idiom in C++ for example), or in Domain Specific Languages to make the code read more fluently.

I've seen them being used for everything from image processing libraries, to regular expression libraries, 3D libraries. Other examples include the construction of tree structures, lists, or other datastructures. Everything that requires the construction of complex objects (load of parameters) can make use of Fluent Interfaces to make it more readable. For example, compare the previous example to the CreateWindow function call:

 ::CreateWindow(
      "Window class", 
      "Window title", 
      dwStyle, X, Y, 
      nWidth, nHeight, 
      hWndPant, hMenu, 
      hInstance, NULL
 );
Jasper Bekkers
  • 6,711
  • 32
  • 46
  • It's been a while since I did any web related development, but judging from the jQuery documentation, it seems like it is. – Jasper Bekkers Jan 11 '09 at 19:33
  • 1
    This is method chaining, not fluent interfaces. See the quote from Rasmus' answer above *"Certainly chaining is a common technique to use with fluent interfaces, but true fluency is much more than that...."* – Pacerier Aug 13 '15 at 11:22
5

Here's a regular every-day interface:

public interface NotFluent
{
  void DoA();
  void DoB();
  void DoC();
}

And here's a fluent interface:

public interface Fluent
{
  Fluent DoA();
  Fluent DoB();
  Fluent DoC();
}

The most obvious difference is that when we return a void, we return instead an instance of the interface type. What's understood is that the interface returned is the CURRENT INSTANCE, not a new instance of the same type. Of course, this isn't enforceable, and in the case of immutable objects (like string) it is a different instance but can be considered to be the same instance only updated.

Here are examples of their use:

NotFluent foo = new NotFluentImpl();
foo.DoA();
foo.DoB();
foo.DoC();

Fluent bar = new FluentImpl();
bar.DoA().DoB().DoC();

Notice that the fluent interface is easier to use when chaining different calls. IRL, check out the Linq extension methods and how each call is designed to flow into another. None of the methods return void, even if it would be a valid result.

  • 1
    Isn't this example simply method chaining? Fowler notes [*"many people seem to equate fluent interfaces with Method Chaining"*](http://www.martinfowler.com/bliki/FluentInterface.html). What property does the code above have that makes it a fluent interface as opposed to mere method chaining? – Pacerier Aug 13 '15 at 11:28
  • @Pacerier if you're interested in splitting this hair (and that reference doesn't go much at all into the distinction the author supposedly sees), then instead of dropping comments on every answer, why not answer it yourself? Or if you want to learn more about how to split that hair, ask a new question which concentrates on the distinctions between the two. Personally, I don't see much. Definitely not enough to make a worthwhile distinction. I see them inextricably linked. It's just that sometimes the patterns emerge and sometimes they don't. I'm not interested in the aesthetics, I guess. –  Aug 13 '15 at 12:23
  • Re *"why not answer it yourself"*, I don't have an answer, hence the questions. And this is not "splitting hairs", it seems to be quite clear that FluentInterface is not equal to Method Chaining. – Pacerier Aug 14 '15 at 06:48
  • @Pacerier Well, that makes no sense. You claim it's evidently clear they are different, yet you don't have an answer yourself? I believe you're trolling. Good day to you, sir. –  Aug 14 '15 at 14:03
  • 2
    [Cool down](https://en.wikipedia.org/wiki/Wikipedia:Assume_good_faith), I don't get why the amount of rep correlates with the tendency to leap to [negativity](https://goo.gl/2rTjDy). It's fine if you don't have an answer too, that's not a big deal. My comment above isn't "senseless" if it's read slowly: it's **clear** from Fowler's article that there's a distinction between Method Chaining and FluentInterface, even while the distinction **itself** is unclear. While I'm trying to improve the quality of the answers here through your responses, you're always free to leave the posts as they are. – Pacerier Aug 18 '15 at 03:23
  • @Pacerier The amount of rep has nothing to do with it--I've just been around for a long time. You claim it's clear, even though there is absolutely **no evidence** of such clarity other than a statement that it is. You come here citing this incomplete source as proof that the distinction is clear, and demand answers proving this claim while specifically stating "the distinction itself is unclear", in other words *that you have no evidence it is*. ***That makes no sense***. I reject the original claim unless given evidence to the contrary. And now, **I say good day!** –  Aug 18 '15 at 14:20
3

An object-oriented interface is fluent if methods that are executed for side effect return self, so that such methods can be chained together.

I first encountered fluent interfaces in 1990 when the Modula-3 Interface Police (I am not making this up) required all initialization methods to return the object initialized. I believe this usage predates the coinage of the term "fluent interface".

Norman Ramsey
  • 198,648
  • 61
  • 360
  • 533
  • Actually when OP says "fluent interface", he's very likely referring to Fowler's definition of [FluentInterface](http://www.martinfowler.com/bliki/FluentInterface.html). Not just *fluent* interfaces in general. – Pacerier Aug 13 '15 at 11:33
1

Neal Ford does a nice job of explaining and giving Fluent Interface examples in his book the 'Productive Programmer'.

Traditional Object or 'bean' with getters/setters:

Car car = new CarImpl();
MarketingDescription des = new MarketingDescriptionImpl();
desc.setType("Box");
desc.setSubtype("Insulated");
desc.setAttribute("length", "50.5");
desc.setAttribute("ladder", "yes");
desc.setAttribute("lining type", "cork");
car.setDescription(desc);

Meet the same need with a fluent interface:

Car car = Car.describedAs()
  .box()
  .length(50.5)
  .type(Type.INSULATED)
  .includes(Equipment.LADDER)
  .lining(Lining.CORK);
Brian
  • 13,412
  • 10
  • 56
  • 82
1

In a fluent interface, a object's methods will return a reference to the object, so that you can chain the method calls together.

For example, in NValidate, I did this to simplify parameter validation:

public City GetCity(string zipCode)
{
   zipCode.Assert("zipCode").IsNotNullOrEmpty().HasLength(5,10).Matches("\\d[5]-\\d[4]");
   // Continue processing
}

I can't speak to leaky abstractions, though.

Mike Hofer
  • 16,477
  • 11
  • 74
  • 110