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). Generally, the context is
* defined through the return value of a called method
* self referential, where the new context is equivalent to the last context
* terminated through the return of a void context.
This style is beneficial due to its ability to provide a more fluid feel to the code.
In a common API, a business class has several methods that return a list according to different criteria. Consultations are close to the following:
$students = new Student();
$studentsRio = $sudents->getByCity('Rio de Janeiro');
/** **/
$list = $students->getEnrolledByCurseCity('IT', 'Rio de Janeiro');
In a real system there are many variations in criteria and the class has growing amount of code and difficulty of use and maintenance.
The proposal is to eliminate the need for a method for each type of query. The only criteria that make up the consultation will be undertaken only once when needed, enabling these search criteria operate independently.
The calls are being carried out as follows:
$students = new Student();
$students->fromCity('Rio de Janeiro')
->inOrder()
->Enrolled()
->inCurse('IT');
To achieve this API you must:
1. chain methods
2. be able to configure the query dynamically
3. identify when configuration ends and then perform the query.
Although there are other techniques to refactor the first API, the use of Fluent Interface is a significant advance to the deployment of Domain Specific Language for User's use.
Method Chaining
The first step is to realize the simplicity of chaining methods. Usually the properties of a class are defined by methods setters that return nothing. The goal is to return the object itself from each of these methods.
This technique by itself only reduces the amount of code since it does not need to repeat the object instance for each setter.
Fluent Interface
Done chaining requires a conceptual change. The main point is that the nomenclature of the methods allow the interface to flow naturally.
Renaming the methods and returning the object itself can make the call in a friendly way:
class Students{
// previously called setFilterCity
public function daCidade($city) {
echo "Students will be filtered through the city $city";
return $this;
}
// previously called setOrderByNome
public function inORder() {
echo "Students will be sorted by name";
return $this;
}
}
$students = new students();
$students->fromCity('Rio de Janeiro')
->inOrder();
Above all it is important to maintain consistency to make it clear what are the classes that work with Method Chaining, avoiding the wait for the developer to return the object itself wrongly.
In these examples will be used as the prefix Catalog attempt to identify these classes. The use of namespaces would be very welcome if the language allowed.
Example code (In J1.6)
So now we can use:
$content = new ContentDSL();
$contentRows = $content->lists()->withTitle('My Title')->published()->getRows();
Another example usign Fluent Interface:
class car {
private $speed;
private $color;
private $doors;
public function setSpeed($speed){
$this->speed = $speed;
return $this;
}
public function setColor($color) {
$this->color = $color;
return $this;
}
public function setDoors($doors) {
$this->doors = $doors;
return $this;
}
}
// Fluent interface
$myCar = new car();
$myCar->setSpeed(100)->setColor('blue')->setDoors(5);
// Example without fluent interface
$myCar2 = new car();
$myCar2->setSpeed(100);
$myCar2->setColor('blue');
$myCar2->setDoors(5)
I will write more about fluent interfaces and how construct complex "gramatics" like:
$rows = $content->lists()->published()->latest()->fromCategory()->withName('Joomla! News")->andContent()->inOrder()->getRows();
About DSL(Domain Specific Language) is a specific language dedicated to a particular problem/domain in our case Content. The idea is create your cals with better names and when you use fluent interface make better code, more legible, etc.
Now Try create there DSL:
- Content
- Category
- Banner
And make a relation of these for example;
// latest content in order of creation from category with name "latest news"
$content->lists()->latest()->fromCategory()->withName('Latest news')->andContent()->inORder->getRows();
// lastest banners in order from category with name "Banners"
$banner->lists()->latest()->fromCategory()->withName('Latest news')->andBanner()->inORder->getRows();
I will make a challenge to you readers think about "how to create various DSL (Domain Specific Language) and how they will relate to". xD
Read more about Fluent Interface and DSL
Tips for challenge: use JQuery Class xD
Tags:
Share
Facebook
You need to be a member of All Together, As A Whole to add comments!
Join All Together, As A Whole