If you are not familiar with the term "Fluent API," review these two earlier articles and then come back:
tl;dr: Fluent programming interfaces use method chaining and domain-specific language to mimic declarative programming concepts in procedural programming languages.
You can use them to turn these nine lines of code...
With CreateControl(CtlName, acLabel) .Caption = "My Label" .Width = 2 * TwipsPerInch .TextAlign = 2 'Center .FontSize = 14 .FontName = "Segoe UI" .FontBold = True .FontItalic = True End With
...into this one line of code...
fb.AddLabel("My Label").Width(2).Center.Size(14).Font("Segoe UI").Bold.Italic
Knowing When to Build Fluent APIs
Having built a few fluent APIs myself, I've noticed the work extremely well in very specific circumstances.
This approach works best when you have a class module with:
- Several very similar methods,
- Where each method could have lots of optional parameters,
- But most of those optional parameters are not used
In other words, it works best in the programming equivalent of a sparsely populated dataset, "where any individual entity may have a modest selection from a very wide set of attributes." So what sorts of programming problems fit this criteria?
In general, I find that "builder" APIs make great candidates for fluent interfaces.
4 Examples of Fluent APIs I've Written
In the past few years, I've built four different fluent APIs:
- A customized report builder API
- A generic report builder API
- A generic form builder API
- A ribbon XML generator API
I'll cover each of these topics more in depth in future articles.
If you find the idea of fluent interfaces intriguing, be sure to check out the rest of my articles on the topic:
To be notified of future articles in the series, you can subscribe to this RSS feed.
The seminal article on fluent interfaces was written by Martin Fowler back in 2005.
In my first article on fluent interfaces, I closed with the following thoughts:
There's no doubt that fluent interfaces are one of the shiniest of hammers to keep in your toolbox. But they are not for every situation. In fact, they are ill-suited for most situations. However, in the right situation, they can be pretty badass.
I'm apparently not alone in my belief that fluent interfaces are "ill-suited for most situations." Despite the title–Fluent Interfaces are Evil–Marco Pivetta's article is less an indictment of fluent interfaces themselves, and more a rant against the proliferation of fluent APIs in situations for which they are ill-suited. While most of his technical objections do not apply to VBA (he's a PHP dev), I do agree with his conclusion:
I know the article is titled "Fluent Interfaces are Evil", but that doesn't mean it's an absolute.
Fluent interfaces are useful and easy to read in some contexts. What I am showing here is a set of problems that raise when inheriting them or making every piece of your code fluent.
I just want you to think carefully next time you want fluent interfaces in your libraries, especially about the downsides that I have just exposed.
You must have a very good reason to implement a fluent interface, otherwise it's just a problem that you are possibly dragging into your codebase.