10.28
I like to learn to write code by writing software, I like to learn about writing software by writing about it. My goal is to build a series of posts which will reflect the knowledge I have gained regarding this topic of Fluent Interfaces and Internal DSLs.
Disclaimer: Authorship is not equal to Authority. I don’t claim to be an expert in this domain. I’m merely learning by doing so take what I write with a pinch of salt!
Fluent Interfaces & Fluent APIs
A fluent interface to me is a the way you interact with a class in a fluent fashion. A fluent API is how you interact with a framework of classes in a fluent fashion. In all reality the terms are interchangeable with one another.
Over the last month I have been thinking a lot about fluent interface design in C# to create a DSL for an “Fluent” API I will be working on. I am starting to see more and more “Fluent” APIs emerging in the .NET space.
I am currently researching quite heavily in this area and I will be blogging about the different approaches that can be taken to develop an effective Fluent API. I want to know first hand how to create structured and compiler controlled sentences, the positives and negatives of doing so by experiencing the process of developing and developing with my own Fluent API.
Definitions
“In software engineering, a fluent interface (as first coined by Eric Evans and Martin Fowler) is a way of implementing an object oriented API in a way that aims to provide for more readable code. A fluent interface is normally implemented by using method chaining to relay the instruction context of a subsequent call (but a fluent interface entails more than just method chaining).” Wikipedia: Fluent Interface
“Typically, method chaining simply consists of many methods on a class, each of which return the current object itself. This enables invoking another method on the same object immediately, leading to code that may look something like:” Wikipedia: Method Chaining
Simple Fluent Interface
This is a simple example, my goal is to elaborate into more complex scenarios in later posts.
Here is an example of a fluent interface for creating a Coffee, it could be said we are creating a ‘internal’ DSL for creating coffee.
The first thing to note is that all public methods return ‘this’ in turn allowing us to chain methods together.
public class CoffeeItem : ICoffeeItem { public bool HasMilk { get; set; } public bool HasCream { get; set; } public CoffeeSize Size { get; set; } public ICoffeeBlend Blend { get; set; } public ICoffeeItem SetSizeTo(CoffeeSize size) { Size = size; return this; } public ICoffeeItem WithCream() { HasCream = true; return this; } public ICoffeeItem WithMilk() { HasMilk = true; return this; } public ICoffeeItem SetBlendTo(ICoffeeBlend blend) { Blend = blend; return this; } }
Lets create an order and test that it works with a unit test.
[Test] public void CoffeeItem_OrderAJavaSumutraWithCreamOfSizeEpic_ShouldContainSaidAttributes() { var coffee = new CoffeeItem(); //Set Order coffee.SetBlendTo(new JavaSumutra()).WithCream().SetSizeTo(CoffeeSize.Epic); //Assert that order was issued correctly Assert.That(coffee.HasCream, Is.True); Assert.That(coffee.Blend, Is.TypeOf(typeof(JavaSumutra))); Assert.That(coffee.Size, Is.EqualTo(CoffeeSize.Epic)); }
I find this a nice way to write software, and it lends well to test driven development. Now lets create a Coffee Order which will contain many coffees.
public class CoffeeOrder { public CoffeeOrder() { CoffeeItems = new List(); } public List CoffeeItems { get; set; } public ICoffeeItem AddCoffee(ICoffeeItem coffee) { CoffeeItems.Add(coffee); return coffee; } }
So now we can create a coffee order which contains the a coffee with its attributes being set in a a sentence. We can run this inside a unit test like so:
[Test] public void AddCoffee_WhenPassedACoffee_ShouldContainCoffee() { var order = new CoffeeOrder(); var coffee = new CoffeeItem(); order.AddCoffee(coffee) .SetBlendTo(new JavaSumutra()) .WithCream() .SetSizeTo(CoffeeSize.Small); Assert.That(order.CoffeeItems, Has.Member(coffee)); }
So that concludes the simple Coffee example. It is quite contrived but hopefully gives a quick and dirty glimpse at what a Fluent Interface is.
Topics I wish to cover next in the near future:
- Returning Interfaces to Control sentence structure within Fluent Interfaces.
- Using Extensions Methods (C# 3.0) within Fluent Interfaces.
- An overview of Quality Open Source Fluent APIs in .NET and what you can learn.
- Passing in predicates and utilizing lambda expressions in Fluent Interfaces.
- Internal versus External DSLs.


An Introduction to Fluent Interfaces & Internal DSLs in C#…
Thank you for submitting this cool story – Trackback from DotNetShoutout…
[...] An Introduction to Fluent Interfaces & Internal DSLs in C# – Steven Holdsworth shares a simple introduction to the concepts of Fluent Interfaces and Internal DSLs with a simple code example to illustrate, showing that these concepts don’t have to be big and complicated [...]
This is an interesting topic. I’ll be following your posts.
How is this different from using an object initializer where the said methods are properties?
e.g. var coffee = new CoffeeItem {
Blend = new JavaSumutra(),
HasCream = true,
Size = CoffeeSize.Small)
}
This was a very simple example granted. I am a fan of object initializers.
I will be going into more detailed assembly of a internal DSL in later posts.
But in the meantime think about these examples.
A simple internal time DSL in C#:
var time = Twelve.Minutes().Ago();
Could be (roughly):
var time = new Time { InPast = true, Perioid = 12, Unit = Unit.Minutes };
This just doesn’t read as well nor is as nice to program against.
Then this example is where we need to build an encapsulated expression.
If we wish to build a rule that is readable and gets composed as a sentence:
Rule.BecomesActive().When().ValueReaches(100);
Or
Rule.When(rule => rule.Value >= 100).BecomesActive();
This is fluency in chaining methods, in a instance which is more complex that I find preferable to using an object initializer.
I don’t like programming against an implementation, in fact I would actively avoid doing so (I would use a factory or some varient) in order to avoid the coupling that “new” keyword entails. A factory would allow me to string methods on my created object at the point of creation without knowing the underlying implementation.
Hope this helps. Thanks for the comment