one year ago by James Hickey

Ever find yourself frustrated with 3rd party libraries that are supposed to be useful? Easy to use?





Ever gone back to some nice/reusable class that you built a few weeks ago only to realize you have no idea how to get started with it. Nothing obviously sticks out as a starting point?





So, you decide to check out the documentation only to spend an hour trying to figure out how to get started with the one thing you need the library for!





I've been there so many times! Throughout my career I've always wondered if there was a way to build reusable pieces that are just 100% plain and obvious to use . Something that just guides you through the proper usage.





Let's Learn From The Best





Let's try to learn from the best. The tools that are the easiest to use. Here are a few tools that I personally find are enjoyable to use:





Laravel (PHP Framework)

JQuery

.NET Core

LINQ





These represent, to me, some of the easiest-to-use yet powerful tools I've encountered in my career.





I don't use JQuery anymore, nor will I (by choice). But everyone would agree that JQuery made working with the DOM enjoyable compared to the native tools at the time.





So - what do all of these tools have in common? What makes them so easy to use?





They are (mostly) Fluent APIs .





Eh? What's A Fluent API?





The term "fluent" has the connotation that "fluent API" somehow relates to (spoken) languages. You can be fluent in English, for example.





Fluent interfaces are a style of programming that focuses on how your code reads easily and naturally - like you are reading a book.





Readability





For example,in .NET Core you might find code like this:





app.UseDeveloperExceptionPage() .UseDatabaseErrorPage();





This is very easy to understand and to read. You intend to use the developer exception page (which has nice debugging info for developers). You also wish to use some special error page when you get database errors.





Unlocking New Methods





Let's look at another example:





services .AddMvc() .SetCompatibilityVersion(CompatibilityVersion.Version_2_1);





In this example, calling the "AddMvc" method unlocks access to other methods that only make sense within that specific context.





This to me is the most powerful aspect of fluent interfaces - they only let you use what makes sense to use within the current context .





Other Benefits





When a fluent API is done properly you shouldn't be able to:





Call methods in the wrong order (ever used code like this?)

(ever used code like this?) Be confused where to start (since the IDE intellisense will tell you what methods are available to "get started")

to "get started") Call methods in a specific chain partially. (E.g. "You forgot to call the "Done" method of some class so it never performed it's logic) (This is in advanced usages of the fluent pattern)





If you want to continue reading about these ideas you can read this post where I discuss more benefits you get with fluent APIs.





Applied To A Real Library





For the reasons above (and the reasons in the post I linked to) I opted to use a fluent API when writing Coravel. I think this is one of the main reasons that people are using it - it's so easy to work with.





For example, can you figure out what this code is intending to do?

















This is how easy code written in a fluent style can be to understand. There's no mistaking what this code does.





Wizard-like Code Completion





Take this example of me using Coravel in Visual Studio Code:













When someone wants to schedule something they get access to new methods . These methods are only ever available in the context of scheduling something.





Also notice that only methods related to scheduling are available. There's no bleeding of methods from other contexts here.





After selecting the frequency those methods are gone and you get access to a new group of selections:













Let's Build A Fluent API Right Now!





So you're dying to know - how do I actually build one?





Building basic fluent APIs can actually be really simple. The key "trick" is that the methods in your class can return an interface that restricts what methods the caller can use.





Here's what a working example might look like:





public class MyFluentClass : ICalculation , IResult { private int _value; private int _result; private MyFluentClass() { } public static ICalculation WithValue(int value) { return new MyFluentClass { _value = value }; } public IResult Add(int toAdd) { this._result = this._value + toAdd; return this; } public IResult Subtract(int toSubtract) { this._result = this._value - toSubtract; return this; } public int Result() => this._result; } public interface ICalculation { IResult Add(int toAdd); IResult Subtract(int toSubtract); } public interface IResult { int Result(); }





Things to notice:

Use a private constructor so the caller is forced to use the static factory method

The static factory method has access to the instances private members

"WithValue" returns the interface "ICalculation". This is what begins to restrict what methods the caller can use.

"Add" and "Subtract" return the interface "IResult". This is what unlocks the next series of methods in the chain (which happens to be "Result").





Here's what it looks like in action:

















Conclusion





Thanks for taking the time to go through this - I hope you learned something new and enjoyed the content!





By the way, this is part 2 of my series "What I've Learned So Far Building Coravel". Here are the other parts of the series:





Part 1 - What I've Learned So Far Building Coravel (Open Source .NET Core Tooling)

Part 3 - .NET Core Dependency Injection: Everything You Ought To Know



