All Together, As A Whole

Independent Developer and Web Site Builders Network

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
Amy Stephen Comment by Amy Stephen on September 28, 2009 at 5:32pm
Wow! You think this way, don't you? I'm thinking you are 100 years beyond many of us.

I have an idea, wonder if you might be interested in this? Most of us (I assume) are vaguely aware about about JQuery - the Joomla! Query Class. Would you be willing to put together a mini-tutorial and post it for folks so that they know how it works and perhaps even share the types of changes we might need to make for our Extensions?

Of course, that would also be very useful to developers and it could also be shared with docs.joomla.org for others. Might get some feedback here and then perhaps share with Chris Davenport or Ian MacLennan (who are in charge of J! documentation).

Understanding where 1.6 is leading will help make clear your ideas about where additional improvements might lead.

I admire your thinking and appreciate you sharing with us.
Stian Didriksen Comment by Stian Didriksen on September 29, 2009 at 3:09pm
Firstly, you're absolutely right on many of your points. But I get a bad feeling whenever I see a property that mix function and data.

function = from,
data/model = category.

fromCategory() is only usable if your app got categories. So if you are getting data from two sources, you'll have to type two different properties. So you can't just put it in a function and do stuff like loops easily.

Like this:
foreach (array('category', 'article', 'tag') as $name)
{
$arr[] = $query->from($name);
}

or more advanced ones:
foreach (array('where' => 'articles', 'distinct' => 'author', 'select' => 'tags') as $function => $context)
{
$query->{$function}($context);
}
$article = $query->fetchRow();

Look, the concepts you draw is on par with where Koowa already is today. I highly recommend you give it a shot, as it'll allow you to skip the step where you need to convince anyone to follow these conventions.

If you're anything like me, I know you're overflowing with lots of other ideas of how to make dynamic, flexible and smarter applications. Don't spend time doing all the hard ground work that's already done, do the things that isn't.

You wont regret it if you give Koowa a go, but I tell you this, if you don't, you have no idea what you're missing out on. Koowa already got persistent model states, object based query class that'll have prepared statements support soon. Automatic filtering of input data on save, based on the metadata in your db table.
And the Mootools sortables script I introduced earlier this week is going to be a part of the framework as well.

Koowa is years ahead of the 1.6, and it'll only continue to race ahead, as the best joomla developers in the world are actively contributing on the project. If you're not even going to give it a shot, I'll be sad to see such talent like yours go to waste, as you're going to do more reinventing than innovating.
Júlio Pontes Comment by Júlio Pontes on September 29, 2009 at 3:35pm
@Stian, if you can see my discussion i will try explain how works my Idea..

Comment

You need to be a member of All Together, As A Whole to add comments!

Join All Together, As A Whole

© 2010   Created by Robert Vining on Ning.   Create a Ning Network!

Badges  |  Report an Issue  |  Privacy  |  Terms of Service

Sign in to chat!