Fluent Interface by Example

Last updated on April 11, 2024

Chances are you have seen Fluent Interface in action. I’ve seen it without realizing what they were until I stumbled across Martin Fowler’s blog. The aim is simple – to provide for a more readable code.

SharePoint API
Several years ago, I wrote a SharePoint API in Java to interact with its List Soap Service. This soap service had a feature to query the target list using Collaborative Application Markup Language (CAML). Here’s an example of CAML query to filter the task list where the TaskName is “Foo Bar” and the Status is “In Progress”.

<query>
  <where>
    <and>
      <eq>
        <fieldref name="TaskName">
        <value type="Text">Foo Bar</value>
      </fieldref></eq>
      <eq>
        <fieldref name="Status">
        <value type="Text">In Progress</value>
      </fieldref></eq>
    </and>
   </where>
</query>

As part of this SharePoint API, I had written a corresponding set of Java classes – each node represented by a class. For trivial query like above, it would look like the following:

final Expression leftExpression = new Equals(new Field("TaskName", "Foo Bar"));
final Expression rightExpression = new Equals(new Field("Status", "In Progress"));
final Condition condition = new And(leftExpression, rightExpression);
final Where clause = new Where(condition);
final Query query = new Query(clause);

As you can predict, for complicated scenarios, this would quickly become unreadable. By applying the concept of Fluent Interface, we can make it far more readable. For example, the above become the following:

final Where clause =
  new Where(
    and(eq("TaskName", "Foo Bar"),
        eq("Status", "In Progress")));

Applying Fluent Interface
A good Fluent Interface takes a while to build. It should be built with the goal of readability and flow in mind. Return type should be chosen based on what you need to continue fluent action. Here’s the SharePoint API implementation. For the complete implementation, please see GitHub Source.

.
.
.
public static Condition and(Expression left, Expression right) {
  return new And(left, right);
}

public static Condition and(Expression left, Condition right) {
  return new And(left, right);
}

public static Condition and(Condition left, Expression right) {
  return new And(left, right);
}

public static Condition and(Condition left, Condition right) {
  return new And(left, right);
}
.
.
.
public static Expression eq(Field field) {
  return new Equals(field);
}

For complicated scenarios where you want to get all task assigned to John with status in “New” or “In Progress” and task created after Jan 1, 2014, the CAML would like the following.

<query>
  <where>
    <and>
      <eq>
        <fieldref name="AssignedTo">
        <value type="Text">John</value>
      </fieldref></eq>
      <and>
        <or>
          <eq>
            <fieldref name="Status">
            <value type="Text">New</value>
          </fieldref></eq>
          <eq>
            <fieldref name="Status">
            <value type="Text">In Progress</value>
          </fieldref></eq>
        </or>
        <gt>
          <fieldref name="CreateDate">
          <value type="DateTime">2014-01-01T00:00:00Z</value>
        </fieldref></gt>
    </and>
   </and></where>
</query>

Here’s the same in Fluent Interface

final Where clause =
  new Where(
    and(eq("AssignedTo", "John"),
    and(
      or(eq("Status", "New"),
         eq("Status", "In Progress")),
      gt("CreateDate", "2014-01-01T00:00:00Z"))));