What is the Fluent Interface Design Pattern?

Göksu Deniz
7 min readDec 14, 2022
Image is created by DALL-E 2 AI

A fluent interface is a design pattern that is used to create an object-oriented API that is easy to read and understand. The purpose of using a fluent interface is to make the API more readable and intuitive, so that developers can work with it more easily. By using method chaining and method cascading, a fluent interface allows developers to write code that reads like a sentence in a natural language, making it easier to understand and maintain. This can help to improve the clarity and reliability of the code, and can make it easier to work with complex data structures and algorithms.

Why did the fluent interface go to therapy? It was feeling too chained up!

To use a fluent interface in C#, you can create an object-oriented API that uses method chaining and method cascading to make the code more readable and intuitive. For example, you could create a class that represents a shopping cart, and define methods that allow you to add items to the cart, remove items from the cart, and calculate the total cost of the items in the cart. Then, you could use method chaining to allow developers to write code that looks like this:

shoppingCart.AddItem("apple").AddItem("banana").AddItem("orange").CalculateTotalCost();

In this example, the methods are called in a way that reads like a sentence in a natural language, making the code easy to read and understand. This can help to improve the clarity and reliability of the code, and can make it easier to work with complex data structures and algorithms.

string result = FluentLibrary.Create()
.Add("Hello")
.Add("World")
.ToString();

Imagine you have a toy box with different blocks in it. The FluentLibrary class is like the toy box, and the Create method is like opening the toy box and taking out a block. The Add method is like adding another block to the one you already have, and the ToString method is like putting all of the blocks together to make a complete sentence.

var account = new BankAccount()
.Deposit(100)
.Withdraw(25)
.Transfer(50, "savings account");

In this example, we are creating a BankAccount object and using method chaining to call the Deposit, Withdraw, and Transfer methods on the object. This allows us to write code that reads like a sentence in a natural language, making it easy to read and understand.

In the context of a game, a fluent interface could be used to define the skills of a character. For example, a character might have the ability to cast spells, and the fluent interface could be used to define the different spells that the character knows.

Here is an example of how a fluent interface might be used to define a character’s spells in C#:

public class Character
{
private List<Spell> spells = new List<Spell>();

public CharacterSpells Fluently()
{
return new CharacterSpells(this);
}

public class CharacterSpells
{
private Character character;

public CharacterSpells(Character character)
{
this.character = character;
}

public CharacterSpells Add(Spell spell)
{
character.spells.Add(spell);
return this;
}
}
}

public class Spell
{
// properties and methods for the spell go here
}

To use this fluent interface, you would call the Fluently() method on a Character object, and then use the methods on the returned CharacterSpells object to define the character’s spells. For example:

var myCharacter = new Character();

myCharacter.Fluently()
.Add(new Spell())
.Add(new Spell())
.Add(new Spell());

This code adds three spells to the myCharacter object using the fluent interface. The code is easy to read and understand, and it makes it clear that the Add() method is being used to add spells to the character.

Here is an example of how a fluent interface might be used to create a calculator in C#:

public class Calculator
{
private int result = 0;

public Calculator Fluently()
{
return this;
}

public Calculator Add(int value)
{
result += value;
return this;
}

public Calculator Subtract(int value)
{
result -= value;
return this;
}

public Calculator Multiply(int value)
{
result *= value;
return this;
}

public Calculator Divide(int value)
{
result /= value;
return this;
}

public int Result()
{
return result;
}
}

To use this fluent interface, you would call the Fluently() method on a Calculator object, and then use the methods on the returned Calculator object to perform the desired calculations. For example:

var myCalculator = new Calculator();

int result = myCalculator.Fluently()
.Add(5)
.Multiply(3)
.Subtract(2)
.Divide(4)
.Result();

This code uses the fluent interface to perform the following calculation: ((5 * 3) — 2) / 4 = 3. The result of the calculation is returned by the Result() method.

Fluent interfaces are often used in startup files of projects, such as in the Configure() method of an ASP.NET Core application. In this context, a fluent interface can be used to define the services and middleware that the application will use.

Here is an example of how a fluent interface might be used in the Configure() method of an ASP.NET Core application:

public void Configure(IApplicationBuilder app)
{
app.UseMiddleware<LoggingMiddleware>()
.UseMiddleware<AuthenticationMiddleware>()
.UseMiddleware<AuthorizationMiddleware>()
.UseMvc();
}

In this example, the UseMiddleware<T>() method is used to add middleware to the application pipeline. The fluent interface makes it easy to read and understand the code, and it clearly shows the order in which the middleware will be executed.

Another common use of fluent interfaces in startup files is to define the services that the application will use. For example:

public void ConfigureServices(IServiceCollection services)
{
services.AddTransient<ILogger, Logger>()
.AddSingleton<IDatabase, Database>()
.AddScoped<IUserService, UserService>();
}

In this example, the AddTransient<T, U>(), AddSingleton<T, U>(), and AddScoped<T, U>() methods are used to register services with the service container. The fluent interface makes it easy to see which services are being registered and what their lifetime is.

What did the fluent interface say to the object-oriented API? “I just love the way you flow!”

One common use case for the fluent interface pattern is in creating complex object hierarchies. For example, a fluent interface could be used to build a SQL query by chaining together method calls that specify different criteria and options. This allows developers to specify complex queries in a more intuitive and readable way, without the need for complex constructors or factory methods.

Another use case for the fluent interface pattern is in configuration. Fluent interfaces can be used to configure objects in a more readable and concise way. For example, a fluent interface could be used to configure a log manager by chaining together method calls that specify different logging options, such as the log level or the output destination. This allows developers to specify complex configurations in a more readable and maintainable way.

The fluent interface pattern can also be useful in data processing scenarios. Fluent interfaces can be used to perform data processing tasks in a more intuitive and readable way. For example, a fluent interface could be used to filter and transform a data stream by chaining together method calls that specify different processing steps. This allows developers to express complex data processing tasks in a more natural and readable way.

Another common use case for the fluent interface pattern is in creating domain-specific languages (DSLs). Fluent interfaces can be used to create DSLs that allow developers to express complex concepts in a more natural and readable way. For example, a fluent interface could be used to define a set of rules for a business process by chaining together method calls that specify different conditions and actions. This allows developers to express complex business logic in a more intuitive and maintainable way.

Finally, the fluent interface pattern can be useful in testing scenarios. Fluent interfaces can be used to create more readable and maintainable test cases by chaining together method calls that specify different expectations and assertions. This allows developers to specify complex test cases in a more readable and maintainable way.

UML Diagram

Created on stackedit.io

In this diagram, the FluentInterface class defines a set of methods for setting properties that returns FluentInterface and an execute method for executing an action using those properties. The ConcreteFluentInterface class implements the FluentInterface and provides concrete implementations for the methods. The Type classes represent the types of the properties, and the Result class represents the type of the result of the execute method.

Conclusion

A fluent interface is a design pattern that can be used to create an API that is easy to use and read. It is often used in scenarios where an API needs to provide a simple, intuitive way for developers to interact with it. Some examples of scenarios where the fluent interface design pattern may be useful include:

- Creating an API for a database, where the fluent interface allows developers to easily build complex queries using a simple, readable syntax.

- Creating an API for a machine learning model, where the fluent interface allows developers to easily specify the parameters for training and testing the model, and to access the results of the model.

- Creating an API for a web service, where the fluent interface allows developers to easily specify the parameters for the request and to access the response from the service.

In general, the fluent interface design pattern can be useful in any scenario where an API needs to provide a simple, intuitive way for developers to interact with it.

Thanks for reading! If you found the article helpful, you can clap and follow. So you will notified of new articles.

# References

It was created with the help of ChatGPT AI.

--

--

Göksu Deniz

Software Engineer, passionate about creating efficient solutions. Skilled in mentoring teams to deliver successful projects. Always exploring new tech trends.