Fluent interfaces and state machines (part 1) - State-per-operation pattern

Fluent interfaces are a relatively new concept in object-oriented programming. Although it is not object-oriented, so to speak, it represents a compromise between object-oriented and functional way of thinking.

The real challenge with fluent interfaces is to have them "speak" to the user: Formulating sentences of phrases greatly improve the usability of a fluent API. Take this, for instance:


It's quite easy to guess what is this instruction doing. That is: Asserting that x is null. Notice how close the fluent instruction is to the actual "definition" of the behaviour.

Let's use the previous example to see how each call can be represented, in fluent interfaces. An API used to make assertions will most probably have a great number of potential expressions. Instead of defining each and every operation individually, we may allow the user to construct the expression using a syntax really close an english phrase. That being said, we also want the API to restrict the possibilities, therefore guiding the user into a more "discoverable" interface.

State-per-operation pattern

Designing fluent interfaces in static languages like C# is not an easy task. Be prepared to have lots of interfaces and methods.

State-per-operation (simple)

The simplest pattern that can be used to represent fluent interfaces is to use state machines, in a usage-first approach. That means designing your fluent interface first, and then make a mental map (or UML diagram like I did) of the corresponding state machine. The simplest way of doing this is to:

  • Add a state for every operation
  • Add a transition where it is legal to chain calls between two methods (states)

Let's say that we want to represent the following API:



What you get is the diagram on the right. It's not bad: In a state machine, only certain transitions are allowed, thus allowing us to restrict the possibilities. The loopback (from Null to That) is a classic trait of fluent state machines; We want to "reset" the state machine so the user can fluently add another expression. It this case, it allows for calls like:


It's all good. We can easily materialize that state machine into interfaces by defining an interface per operation, and a method/property per transition.

public static class Assert
    public static IFluentThat That<T>(T x) { /* ... */ }

public interface IFluentThat
    IFluentIs Is { get; }

public interface IFluentIs
    IFluentThat Null();
    IFluentNot Not { get; }

public interface IFluentNot
    IFluentThat Null();

Loopback states are usually not materialized into an interface. They are also preferably represented as a methods instead of properties. This is why there's no IFluentNull interface. This pattern generally works well, but does have some downsides.

While this works well for a small amount of methods (one or two), it quickly grows out of control when adding other methods. Let's say we want to add a "between x and y" functionality to our assert API:

State-per-operation (Complex)


A glimpse of the diagram on the right will suffice to convince you that it's not a good approach when designing fluent APIs. It grows really complex, real fast. And chances are, if you are opting for a fluent API, the functionality your trying to expose is complex. Bummer.

So, this approach:

  1. Think of the usage
  2. Represent each operation as a state in a state machine (with corresponding transitions)
  3. Materialize each state into an interface (and each transition as a method/property)

does not work well for complex APIs.

More fundamentally, this pattern does not represent the state machine as it wants to be. There is no "Null" state; It's an operation, not a state. It really wants to be a transition.

In my next post, I'll try and explain another way of pairing fluent interface with state machines.

Posted by: Bryan Menard
Last revised: 20 Nov, 2011 04:13 AM History


No comments yet. Be the first!

No new comments are allowed on this post.