Fluent interfaces

Speaking some language fluently means that we speak without pauses needed to find appropriated words for example. In programming, fluency has almost the same meaning and we'll prove that through this article.

Firstly, we'll try to define fluency in programming. After that, we'll explore the source code of Google Guava FluentIterable object to illustrate the concept of fluent programming. At the end, we'll try to write fluent and non-fluent code to show that the differences are not always very significant between fluent and non-fluent interfaces.

What is fluent interface ?

Fluent interface is also called "method chaining". Basically it means that instead of invoke methods separately, we'll invoke them in chain. A great example of this concept is builder design pattern which main advantage is separation of representation from construction of very complex objects. It guarantees that by the possibility of call setters in chained mode (each setter returns the instance of builder object, or another object depending on expected context). After call of all setters needed to construct an object, a building method called build() is invoked to construct final object.

According to this short description, we can define the goals of fluent interfaces:

FluentIterable as an example of fluent interface

To see fluent interfaces in action, we'll take a look on com.google.common.collect.FluentIterable class (Google Guava 18). According to its comment, it allows to "manipulate Iterable instances in a chained fashion". To see what does happen under-the-hood, we'll define an use case, representing by following snippet:
boolean elementPresent = FluentIterable.from(myList)
  .filter(myFilter)
  .firstMatch()
  .isPresent();
Let's begin by inspecting from() method:
public static <E> FluentIterable<E> from(final Iterable<E> iterable) {
  return (iterable instanceof FluentIterable) ? (FluentIterable<E>) iterable
    : new FluentIterable<E>(iterable) {
        @Override
        public Iterator<E> iterator() {
          return iterable.iterator();
        }
    };
}

As you can see, it returns an instance of FluentIterable object, got through casting or through object creation. After that, we invoke filter() method of FluentIterable which looks like:

@CheckReturnValue
public final FluentIterable<E> filter(Predicate<? super E> predicate) {
  return from(Iterables.filter(iterable, predicate));
}

It also returns an instance of FluentIterable, got also directly as a result of from() method. The only difference is that the elements are filtered by Predicate defined in the method signature and applied in Iterables.filter() call. As you can observe, we are still using FluentIterable instance. Thanks to it, we can call firstMatch() method which return an instance of Optional<E> object:

public final Optional<E> firstMatch(Predicate<? super E> predicate) {
  return Iterables.tryFind(iterable, predicate);
}

In this way we are "fluently" passing from FluentIterable context to the context of another object, Optional<E>. After that, we're using isPresent() method which returns true if Optional contains a reference to non-null object.

Comparison of fluent and not fluent interface

To see some code with and without fluent interface, we'll try to build following HTML content:

<body><h1></h1><div><p><span></span></p></div><ul><li>The 1st list element</li><li>The 2nd list element</li><li>The 3rd list element</li></ul></body>

Below, you can find the code of two simple builder: one being fluent and another one normal object:

// FluentHtmlBuilder.java
public class FluentHtmlBuilder {

  private String tag;
  private String opening;
  private String closing;
  private String content = "";

  public static FluentHtmlBuilder openTag(String tag) {
    FluentHtmlBuilder builder = new FluentHtmlBuilder();
    builder.tag = tag;
    builder.opening = "<"+tag+">";
    return builder;
  }

  public FluentHtmlBuilder closeTag() {
    this.closing = "</"+this.tag+">";
    return this;
  }

  public FluentHtmlBuilder withContent(String...contents) {
    for (String content : contents) {
      this.content += content;
    }
    return this;
  }

  public String asString() {
    return opening + content + closing;
  }

}

// NonFluentHtmlBuilder.java
public class NonFluentHtmlBuilder {

  public String generateContent(String tag, String content) {
    return "<"+tag+">"+content+"</"+tag+">";
  }

}

As you can see, the code of non fluent builder is easier than the code of fluent one. However, in the implementation fluent builder seems to be readable easier:

public class FluentCodeTest {

  private String expected = "<body><h1></h1><div><p><span></span></p></div><ul><li>The 1st list element</li><li>The 2nd list element</li><li>The 3rd list element</li></ul></body>";
  private String firstLi = "The 1st list element";
  private String secondLi = "The 2nd list element";
  private String thirdLi = "The 3rd list element";

  @Test
  public void testWithFluent() {
    String code = openTag("body").withContent(
      openTag("h1").closeTag().asString(),
      openTag("div").closeTag().withContent(
        openTag("p").closeTag().withContent(
          openTag("span").closeTag().asString()
        ).asString()
      ).asString(),
      openTag("ul").withContent(
        openTag("li").withContent(firstLi).closeTag().asString(),
        openTag("li").withContent(secondLi).closeTag().asString(),
        openTag("li").withContent(thirdLi).closeTag().asString()
      ).closeTag().asString()
    ).closeTag().asString();

    assertThat(code).isEqualTo(expected);
  }

  @Test
  public void testWithoutFluent() {
    NonFluentHtmlBuilder builder = new NonFluentHtmlBuilder();
    String listContent1 = builder.generateContent("li", firstLi);
    String listContent2 = builder.generateContent("li", secondLi);
    String listContent3 = builder.generateContent("li", thirdLi);
    String ul = builder.generateContent("ul", listContent1+listContent2+listContent3);
    String h1 = builder.generateContent("h1", "");
    String span = builder.generateContent("span", "");
    String p = builder.generateContent("p", span);
    String div = builder.generateContent("div", p);
    String body = builder.generateContent("body", h1+div+ul);

    assertThat(body).isEqualTo(expected);
  }

}

In the case of FluentHtmlBuilder we have the impression that whole code constructs one thing. While in the case of NonFluentHtmlBuilder we take more time to understand that the 9 generateContent() calls are linked together.

In this article we can see the utility of fluent interfaces in the way of writing code more readable and understandable. However, not always and they shouldn't be overused. The overusing can lead into some bad situations as, for example, breaking encapsulation or making tests more difficult to write.


If you liked it, you should read:

📚 Newsletter Get new posts, recommended reading and other exclusive information every week. SPAM free - no 3rd party ads, only the information about waitingforcode!