Fluent interface and Delphi

The fluid interface (Fluent interface) - a very young technique, even rather a design pattern that has gained popularity and is widely used among Java, C #, PHP coders.
Most of the methods of “good code” contain the discharge of the text of the code (dangling lines, spaces, indents, etc) and this is very cool, but sometimes it turns into hell. Jogging along the code, remembering the method call chain, the eternal dilemma between the long method and readability, etc.
But there is a solution - A fluid interface! Now on Delphi!

So what is a fluid interface?

In short, this is a simplification of multiple method calls of a single object using a chain of methods that return the object that called it (i.e. itself). It sounds complicated, but it looks very easy and simple:
CreateFluentBinaryWriter(Stream)
  .WriteString('active')
  .WriteByte(130);

Implementation

The interface looks elementary - like this:
IFluentBinaryWriter = interface
  function WriteByte(Value: Byte): IFluentBinaryWriter; 
  function WriteString(Value: string): IFluentBinaryWriter; 
end;

The helper function for creating a class that implements the interface looks very simple - like this:
function CreateFluentBinaryWriter(AStream: TStream): IFluentBinaryWriter;
begin
  Result := TFluentBinaryWriter.Create(AStream);
end;

Further, all functions of the fluid interface should return an instance of the class that called this function.

For example, the WriteString function writes a string to a stream (TBytesStream), and returns an instance of the class that called this function
function TFluentBinaryWriter.WriteString(Value: string): IFluentBinaryWriter;
begin 
  fBinaryWriter.Write(Value); // TBinaryWriter
  Result := Self; 
end;

That's all! Actually, this could be finished, but there is one very interesting implementation!

Option two - more complicated

CreateFluentStringWriter(Stream)
  ['Привет ']
  ['Мир']
  ['!'];

Here we go for a little trick. Declare the Attrib Property
property Attrib[Value: string]: IFluentStringWriter read AddString; default;

and in the AddString function, we write the requested string to the stream and return the instance of the class that called this function as the result
function TFluentValueWriter.AddString(Value: string): IFluentValueWriter;
begin
  fBinaryWriter.Write(Value); // TBinaryWriter
  Result := Self;
end;

PS

Using a fluid interface is very wide, and coupled with anonymous procedures, you can achieve very compact and self-documenting code!

Also popular now: