Fluent Interface
   HOME

TheInfoList



OR:

In
software engineering Software engineering is a systematic engineering approach to software development. A software engineer is a person who applies the principles of software engineering to design, develop, maintain, test, and evaluate computer software. The term '' ...
, a fluent interface is an
object-oriented Object-oriented programming (OOP) is a programming paradigm based on the concept of "objects", which can contain data and code. The data is in the form of fields (often known as attributes or ''properties''), and the code is in the form of pro ...
API An application programming interface (API) is a way for two or more computer programs to communicate with each other. It is a type of software interface, offering a service to other pieces of software. A document or standard that describes how ...
whose design relies extensively on
method chaining Method chaining, also known as named parameter idiom, is a common syntax for invoking multiple method calls in object-oriented programming languages. Each method returns an object, allowing the calls to be chained together in a single statement ...
. Its goal is to increase code legibility by creating a
domain-specific language A domain-specific language (DSL) is a computer language specialized to a particular application domain. This is in contrast to a general-purpose language (GPL), which is broadly applicable across domains. There are a wide variety of DSLs, ranging f ...
(DSL). The term was coined in 2005 by Eric Evans and Martin Fowler.


Implementation

A fluent interface is normally implemented by using
method chaining Method chaining, also known as named parameter idiom, is a common syntax for invoking multiple method calls in object-oriented programming languages. Each method returns an object, allowing the calls to be chained together in a single statement ...
to implement
method cascading In object-oriented programming, method cascading is syntax which allows multiple methods to be called on the same object. This is particularly applied in fluent interfaces. For example, in Dart, the cascade: a..b() ..c(); is equivalent to the in ...
(in languages that do not natively support cascading), concretely by having each method return the object to which it is attached, often referred to as
this This may refer to: * ''This'', the singular proximal demonstrative pronoun Places * This, or ''Thinis'', an ancient city in Upper Egypt * This, Ardennes, a commune in France People with the surname * Hervé This, French culinary chemist Arts, e ...
or self. Stated more abstractly, a fluent interface relays the instruction context of a subsequent call in method chaining, where generally the context is * Defined through the return value of a called method *
Self-referential Self-reference occurs in natural or formal languages when a sentence, idea or formula refers to itself. The reference may be expressed either directly—through some intermediate sentence or formula—or by means of some encoding. In philosop ...
, where the new context is equivalent to the last context * Terminated through the return of a
void Void may refer to: Science, engineering, and technology * Void (astronomy), the spaces between galaxy filaments that contain no galaxies * Void (composites), a pore that remains unoccupied in a composite material * Void, synonym for vacuum, a ...
context Note that a "fluent interface" means more than just method cascading via chaining; it entails designing an interface that reads like a DSL, using other techniques like "nested functions and object scoping".


History

The term "fluent interface" was coined in late 2005, though this overall style of interface dates to the invention of
method cascading In object-oriented programming, method cascading is syntax which allows multiple methods to be called on the same object. This is particularly applied in fluent interfaces. For example, in Dart, the cascade: a..b() ..c(); is equivalent to the in ...
in
Smalltalk Smalltalk is an object-oriented, dynamically typed reflective programming language. It was designed and created in part for educational use, specifically for constructionist learning, at the Learning Research Group (LRG) of Xerox PARC by Alan Ka ...
in the 1970s, and numerous examples in the 1980s. A common example is the
iostream In the C++ programming language, input/output library refers to a family of class templates and supporting functions in the C++ Standard Library that implement stream-based input/output capabilities. It is an object-oriented alternative to C's F ...
library in
C++ C++ (pronounced "C plus plus") is a high-level general-purpose programming language created by Danish computer scientist Bjarne Stroustrup as an extension of the C programming language, or "C with Classes". The language has expanded significan ...
, which uses the << or >>
operators Operator may refer to: Mathematics * A symbol indicating a mathematical operation * Logical operator or logical connective in mathematical logic * Operator (mathematics), mapping that acts on elements of a space to produce elements of another sp ...
for the message passing, sending multiple data to the same object and allowing "manipulators" for other method calls. Other early examples include the Garnet system (from 1988 in Lisp) and the Amulet system (from 1994 in C++) which used this style for object creation and property assignment.


Examples


C#

C# uses fluent programming extensively in
LINQ Language Integrated Query (LINQ, pronounced "link") is a Microsoft .NET Framework component that adds native data querying capabilities to .NET languages, originally released as a major part of .NET Framework 3.5 in 2007. LINQ extends the langua ...
to build queries using "standard query operators". The implementation is based on
extension method In object-oriented computer programming, an extension method is a method added to an object after the original object was compiled. The modified object is often a class, a prototype or a type. Extension methods are features of some object-orie ...
s. var translations = new Dictionary ; // Find translations for English words containing the letter "a", // sorted by length and displayed in uppercase IEnumerable query = translations .Where(t => t.Key.Contains("a")) .OrderBy(t => t.Value.Length) .Select(t => t.Value.ToUpper()); // The same query constructed progressively: var filtered = translations.Where(t => t.Key.Contains("a")); var sorted = filtered.OrderBy (t => t.Value.Length); var finalQuery = sorted.Select (t => t.Value.ToUpper()); Fluent interface can also be used to chain a set of method, which operates/shares the same object. Instead of creating a customer class, we can create a data context which can be decorated with fluent interface as follows. // Defines the data context class Context class Customer class Program


C++

A common use of the fluent interface in
C++ C++ (pronounced "C plus plus") is a high-level general-purpose programming language created by Danish computer scientist Bjarne Stroustrup as an extension of the C programming language, or "C with Classes". The language has expanded significan ...
is the standard
iostream In the C++ programming language, input/output library refers to a family of class templates and supporting functions in the C++ Standard Library that implement stream-based input/output capabilities. It is an object-oriented alternative to C's F ...
, which chains overloaded operators. The following is an example of providing a fluent interface wrapper on top of a more traditional interface in C++: // Basic definition class GlutApp ; // Basic usage int main(int argc, char **argv) // Fluent wrapper class FluentGlutApp : private GlutApp ; // Fluent usage int main(int argc, char **argv)


Java

An example of a fluent test expectation in the jMock testing framework is: Martin Fowler,
FluentInterface
, 20 December 2005
mock.expects(once()).method("m").with( or(stringContains("hello"), stringContains("howdy")) ); The jOOQ library models SQL as a fluent API in Java: Author author = AUTHOR.as("author"); create.selectFrom(author) .where(exists(selectOne() .from(BOOK) .where(BOOK.STATUS.eq(BOOK_STATUS.SOLD_OUT)) .and(BOOK.AUTHOR_ID.eq(author.ID)))); The fluflu annotation processor enables the creation of a fluent API using Java annotations. The JaQue library enables Java 8 Lambdas to be represented as objects in the form of expression trees at runtime, making it possible to create type-safe fluent interfaces, i.e., instead of: Customer obj = ... obj.property("name").eq("John") One can write: method(customer -> customer.getName()

"John")
Also, the
mock object In object-oriented programming, mock objects are simulated objects that mimic the behaviour of real objects in controlled ways, most often as part of a software testing initiative. A programmer typically creates a mock object to test the behaviou ...
testing library EasyMock makes extensive use of this style of interface to provide an expressive programming interface. Collection mockCollection = EasyMock.createMock(Collection.class); EasyMock .expect(mockCollection.remove(null)) .andThrow(new NullPointerException()) .atLeastOnce(); In the Java Swing API, the LayoutManager interface defines how Container objects can have controlled Component placement. One of the more powerful LayoutManager implementations is the GridBagLayout class which requires the use of the GridBagConstraints class to specify how layout control occurs. A typical example of the use of this class is something like the following. GridBagLayout gl = new GridBagLayout(); JPanel p = new JPanel(); p.setLayout( gl ); JLabel l = new JLabel("Name:"); JTextField nm = new JTextField(10); GridBagConstraints gc = new GridBagConstraints(); gc.gridx = 0; gc.gridy = 0; gc.fill = GridBagConstraints.NONE; p.add( l, gc ); gc.gridx = 1; gc.fill = GridBagConstraints.HORIZONTAL; gc.weightx = 1; p.add( nm, gc ); This creates a lot of code and makes it difficult to see what exactly is happening here. The Packer class provides a fluent mechanism, so you would instead write: JPanel p = new JPanel(); Packer pk = new Packer( p ); JLabel l = new JLabel("Name:"); JTextField nm = new JTextField(10); pk.pack( l ).gridx(0).gridy(0); pk.pack( nm ).gridx(1).gridy(0).fillx(); There are many places where fluent APIs can simplify how software is written and help create an API language that helps users be much more productive and comfortable with the API because the return value of a method always provides a context for further actions in that context.


JavaScript

There are many examples of JavaScript libraries that use some variant of this:
jQuery jQuery is a JavaScript library designed to simplify HTML DOM tree traversal and manipulation, as well as event handling, CSS animation, and Ajax. It is free, open-source software using the permissive MIT License. As of Aug 2022, jQuery is used ...
probably being the most well known. Typically, fluent builders are used to implement "database queries", for example in the Dynamite client library: // getting an item from a table client.getItem('user-table') .setHashKey('userId', 'userA') .setRangeKey('column', '@') .execute() .then(function(data) ) A simple way to do this in JavaScript is using prototype inheritance and this. // example from https://schier.co/blog/2013/11/14/method-chaining-in-javascript.html class Kitten // use it new Kitten() .setName('Salem') .setColor('black') .save();


Scala

Scala supports a fluent syntax for both method calls and class
mixin In object-oriented programming languages, a mixin (or mix-in) is a class that contains methods for use by other classes without having to be the parent class of those other classes. How those other classes gain access to the mixin's methods depend ...
s, using traits and the with keyword. For example: class Color object Black extends Color trait GUIWindow trait WindowBorder extends GUIWindow class SwingWindow extends GUIWindow val appWin = new SwingWindow() with WindowBorder appWin.render()


Raku

In Raku, there are many approaches, but one of the simplest is to declare attributes as read/write and use the given keyword. The type annotations are optional, but the native
gradual typing Gradual typing is a type system in which some variable (computer science), variables and expressions may be given types and the correctness of the typing is checked at compile time (which is static typing) and some expressions may be left untyped ...
makes it much safer to write directly to public attributes. class Employee my $employee = Employee.new(); given $employee say $employee; # Output: # Name: Sally # Surname: Ride # Salary: 200


PHP

In
PHP PHP is a general-purpose scripting language geared toward web development. It was originally created by Danish-Canadian programmer Rasmus Lerdorf in 1993 and released in 1995. The PHP reference implementation is now produced by The PHP Group ...
, one can return the current object by using the $this special variable which represent the instance. Hence return $this; will make the method return the instance. The example below defines a class Employee and three methods to set its name, surname and salary. Each return the instance of the Employee class allowing to chain methods. class Employee # Create a new instance of the Employee class, Tom Smith, with a salary of 100: $employee = (new Employee()) ->setName('Tom') ->setSurname('Smith') ->setSalary('100'); # Display the value of the Employee instance: echo $employee; # Display: # Name: Tom # Surname: Smith # Salary: 100


Python

In
Python Python may refer to: Snakes * Pythonidae, a family of nonvenomous snakes found in Africa, Asia, and Australia ** ''Python'' (genus), a genus of Pythonidae found in Africa and Asia * Python (mythology), a mythical serpent Computing * Python (pro ...
, returning self in the instance method is one way to implement the fluent pattern. It is however discouraged by the language’s creator, Guido van Rossum, and therefore considered unpythonic (not idiomatic). class Poem: def __init__(self, title: str) -> None: self.title = title def indent(self, spaces: int): """Indent the poem with the specified number of spaces.""" self.title = " " * spaces + self.title return self def suffix(self, author: str): """Suffix the poem with the author name.""" self.title = f" - " return self >>> Poem("Road Not Travelled").indent(4).suffix("Robert Frost").title ' Road Not Travelled - Robert Frost'


Swift

In
Swift Swift or SWIFT most commonly refers to: * SWIFT, an international organization facilitating transactions between banks ** SWIFT code * Swift (programming language) * Swift (bird), a family of birds It may also refer to: Organizations * SWIFT, ...
3.0+ returning self in the functions is one way to implement the fluent pattern. class Person let person = Person() .set(firstname: "John") .set(lastname: "Doe") .set(favoriteQuote: "I like turtles")


Immutability

It's possible to create immutable fluent interfaces that utilise
copy-on-write Copy-on-write (COW), sometimes referred to as implicit sharing or shadowing, is a resource-management technique used in computer programming to efficiently implement a "duplicate" or "copy" operation on modifiable resources. If a resource is dupl ...
semantics. In this variation of the pattern, instead of modifying internal properties and returning a reference to the same object, the object is instead cloned, with properties changed on the cloned object, and that object returned. The benefit of this approach is that the interface can be used to create configurations of objects that can fork off from a particular point; Allowing two or more objects to share a certain amount of state, and be used further without interfering with each other.


JavaScript example

Using copy-on-write semantics, the JavaScript example from above becomes: class Kitten // use it const kitten1 = new Kitten() .setName('Salem'); const kitten2 = kitten1 .setColor('black'); console.log(kitten1, kitten2); // -> Kitten(), Kitten()


Problems


Errors cannot be captured at compile time

In typed languages, using a constructor requiring all parameters will fail at compilation time while the fluent approach will only be able to generate runtime errors, missing all the type-safety checks of modern compilers. It also contradicts the "
fail-fast In systems design, a fail-fast system is one which immediately reports at its interface any condition that is likely to indicate a failure. Fail-fast systems are usually designed to stop normal operation rather than attempt to continue a possibly f ...
" approach for error protection.


Debugging and error reporting

Single-line chained statements may be more difficult to debug as debuggers may not be able to set breakpoints within the chain. Stepping through a single-line statement in a debugger may also be less convenient. java.nio.ByteBuffer.allocate(10).rewind().limit(100); Another issue is that it may not be clear which of the method calls caused an exception, in particular if there are multiple calls to the same method. These issues can be overcome by breaking the statement into multiple lines which preserves readability while allowing the user to set breakpoints within the chain and to easily step through the code line by line: java.nio.ByteBuffer .allocate(10) .rewind() .limit(100); However, some debuggers always show the first line in the exception backtrace, although the exception has been thrown on any line.


Logging

Adding logging into the middle of a chain of fluent calls can be an issue. E.g., given: ByteBuffer buffer = ByteBuffer.allocate(10).rewind().limit(100); To log the state of buffer after the rewind() method call, it is necessary to break the fluent calls: ByteBuffer buffer = ByteBuffer.allocate(10).rewind(); log.debug("First byte after rewind is " + buffer.get(0)); buffer.limit(100); This can be worked around in languages that support
extension methods In object-oriented computer programming, an extension method is a method added to an object after the original object was compiled. The modified object is often a class, a prototype or a type. Extension methods are features of some object-orie ...
by defining a new extension to wrap the desired logging functionality, for example in C# (using the same Java ByteBuffer example as above): static class ByteBufferExtensions // Usage: ByteBuffer .Allocate(10) .Rewind() .Log( log, b => "First byte after rewind is " + b.Get(0) ) .Limit(100);


Subclasses

Subclasses in
strongly typed In computer programming, one of the many ways that programming languages are colloquially classified is whether the language's type system makes it strongly typed or weakly typed (loosely typed). However, there is no precise technical definition o ...
languages (C++, Java, C#, etc.) often have to override all methods from their superclass that participate in a fluent interface in order to change their return type. For example: class A class B extends A ... A a = new B().doThat().doThis(); // This would work even without overriding A.doThis(). B b = new B().doThis().doThat(); // This would fail if A.doThis() wasn't overridden. Languages that are capable of expressing F-bound polymorphism can use it to avoid this difficulty. For example: abstract class AbstractA> class A extends AbstractA class B extends AbstractA ... B b = new B().doThis().doThat(); // Works! A a = new A().doThis(); // Also works. Note that in order to be able to create instances of the parent class, we had to split it into two classes — AbstractA and A, the latter with no content (it would only contain constructors if those were needed). The approach can easily be extended if we want to have sub-subclasses (etc.) too: abstract class AbstractB> extends AbstractA class B extends AbstractB abstract class AbstractC> extends AbstractB class C extends AbstractC ... C c = new C().doThis().doThat().foo(); // Works! B b = new B().doThis().doThat(); // Still works. In a dependently typed language, e.g. Scala, methods can also be explicitly defined as always returning this and thus can be defined only once for subclasses to take advantage of the fluent interface: class A class B extends A ... val a: A = new B().doThat().doThis(); // Chaining works in both directions. val b: B = new B().doThis().doThat(); // And, both method chains result in a B!


See also

*
Command-query separation *
Method chaining Method chaining, also known as named parameter idiom, is a common syntax for invoking multiple method calls in object-oriented programming languages. Each method returns an object, allowing the calls to be chained together in a single statement ...
*
Named parameter In computer programming, named parameters, named argument or keyword arguments refer to a computer language's support for function calls that clearly state the name of each parameter within the function call. Overview A function call using na ...
*
Pipeline (Unix) In Unix-like computer operating systems, a pipeline is a mechanism for inter-process communication using message passing. A pipeline is a set of processes chained together by their standard streams, so that the output text of each process (''stdou ...


References


External links


Martin Fowler's original bliki entry coining the term



A .NET fluent validation library written in C#

A tutorial for creating formal Java fluent APIs from a BNF notation

Fluent Interfaces are Evil

Developing a fluent api is so cool
{{Design Patterns Patterns Software design patterns Articles with example C Sharp code