It's Thursday - what a day to visit jfoobar!

 

Refactoring your code to Fluent Interface

Language imageWith the introduction of chaining methods together in PHP 5 we now have the opportunity to implement Fluent Interfaces in PHP which opens up an interesting way of writing more readable and smaller code.

Fluent Interfaces are not a new programming construct, they provide us with the ability to directly de-reference an object, PHP developers can build objects using fluent interfaces.

On the first look this might look like abracadabra if you are totally new to the new buzzword "Fluent Interfaces". Fluent interfaces are best described as way of chaining methods of an object together. By having a method return a reference to the object itself, return $this; you chain methods together like this:

$this->methodOne()->methodTwo()->methodThree();

The point of using fluent interfaces is simple; to make your code easier to read (and in the end also easier to maintain). My interest has been triggered by the articles Júlio Pontes has been posting on the All Together As A Whole website. A community initiative to gather community developers together. A full list of the articles written by Júlio can be found at the end of this article.

Let's go into some simple examples. We create a semantic database query, to create an Legible API and reusable piece of code. Today usually developers construct "Models" like the following example:


$studentsModel = JModel::getInstance('students');
$studentsModel->getByCity('São Paulo');
$studentsModel->getEnrolleByCurseCity('Computer Science','São Paulo');

In PHP 4 we where "forced" to build applications this way writing an additional lines of code, which we in the end also need to maintain (remember, 80% of the costs come from maintaining code). The proposed solution is to eliminate the necessity to create many methods for every type of criteria. The criteria only configure our Query with will changing on demand and will be executed one time if you need. So on new API the same code will look like this:


$students = new Students;
$students->fromCity('São Paulo')->Enrolled()->inCurse('Computer Science')->inOrder();

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 the users use. Let us discuss the ingredients for constructing this API:

      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.
      Have possibility to configure on demand.
      Identify/decide when finish to execute Query.

Doing 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 fromCity($city) {
        echo "Students will be filtered through the city $city";

        return $this;
    }

    // previously called setOrderByName
    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 the classes are that work with method chaining, avoiding the wait for the developer to return the object itself wrongly. In these examples the prefix Catalog will be used to identify these classes. The use of name-spaces would be very welcome if the language allowed (and PHP 5.3 does support that, PHP has a bright future :-D).

Example code in Joomla 1.6 would be (be aware we assume the existance of a new ContentDSL class):


$content = new ContentDSL();
$contentRows = $content->lists()->withTitle('My Title')->published()->getRows();
Another example using 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)

Júlio has some more examples about fluent interfaces and how construct complex "gramatics" like:


$rows = $content->lists()->published()->latest()->fromCategory()->withName('Joomla! News")->andContent()->inOrder()->getRows();

Júlio also has been writing about Domain Specific Language (DSL). This is a specific language dedicated to a particular problem/domain, in the example below it refers to content. The idea is create your calls with better names and when you use fluent interface also to make better code, more legible, etc. Let us try to create DSL for 'Content', 'Category' and '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();

// latest banners in order from category with name "Banners"
$banner->lists()->latest()->fromCategory()->withName('Latest news')->andBanner()->inORder->getRows();

Júlio is working on an installable extension where you can put this into practise, keep an eye on hos work on the All Together As A Whole website. Who knows this might sometimes end up in the core of Joomla...

Are there any practical examples out there where we can see Fluent Interfaces in action? At the end of this blog you will find some material that Júlio Pontes has been writing about on the All Together As A Whole website. Implementations can also be found in the Zend framework, see for example a post on the Zend developer zone desrcibing a basic example on Fluent Interfaces within Zend (actually a very good read!). Within Joomla 1.6 the only practical use of Fluent Interfaces I know of is the new JQuery Class (fare from complete usage), but also on additional frameworks like Nooku there is some brief documentation out there describing an example in Nooku 0.7.

Related articles:

  • Introduction article about Fluent Interfaces: http://www.alltogetherasawhole.org/profiles/blogs/fluent-interface
  • Explaining Fluent Interfacing using the new Joomla 1.6 JQuery (not the Javascript library): http://www.alltogetherasawhole.org/profiles/blogs/tutorial-jquery-class
  • A follow up article on Fluent Interfaces, explaining the concept in more detail: http://www.alltogetherasawhole.org/profiles/blogs/refactoring-to-fluent
  • JWidget, a practical example on how to use Fluent Interfaces in Joomla modules: http://www.alltogetherasawhole.org/profiles/blogs/jwidget-1 * Fluent Interfaces in PHP; http://devzone.zend.com/article/1362
  • About the author Wilco Jansen

    Wilco was born in 1967 in the Netherlands where he still lives. After years of being a programmer Wilco has worked as project manager and IT manager. Discovered Joomla! when he was creating his own content management system, and never lost focus after then. Joined core team as development coordinator in May 2006 just helping to make Joomla! even better then it is already. Wilco has been deeply involved in the Joomla project as Google summer of code program manager 2006, 2007 and 2008 editions, co-organizer of the Google Highly Participation contest in 2008, first ever development coordinator, creator of the Joomla bug squad, member of the board of Open source matters, regular speaker on world wide conference advocating Joomla and much, much more. Wilco has a bachelor degree in business and information engineering and studied Master of Science knowledge and information engineering at the Middlesex University in London.

    More about Wilco Jansen

    Like it? Share it!

    There are 0 comments posted.

    Help for creating beautiful comments.

    Enter Your Details:
    Enter Your Comments:
    I'm finished with the form Your form will be checked and you'll get a preview.
moovur promo

Blogging team

We have a team that works on the blogs presented on this site. Below you will find all present members who are actively working on blogs on this site.


Please contact us if you are interested in helping us out with the creation of the blogs.

Post translations

jfoobar has readers from all over the world and in many languages. If you create a translation of one of our posts and link to it than please let us know so we can add a link back to the translation at the original post.

JFoobar friends on Twitter

Follow JFoobar on twitter

Sponsored Links

Latest Comments

Aaron wrote:
2009-12-23 13:19:22 - Genius! Thanks, Wilco. I've been dying to take .
Posted in How to downlo .
Amy Stephen wrote:
2009-12-22 18:39:37 - Happy Birthday to one of Joomla!'s most noble - .
Posted in Mister Joomla .
Antonie de Wilde wrote:
2009-12-22 09:30:26 - Congrats Robin. Have a good day and watch out w .
Posted in Mister Joomla .
Robert wrote:
2009-12-22 08:51:02 - Happy Birthday Robin .
Posted in Mister Joomla .
Arno wrote:
2009-12-22 08:43:28 - Happy Birthday Robin, love your suit, you wife .
Posted in Mister Joomla .
Brian Teeman wrote:
2009-12-22 00:17:41 - Happy Birthday Robin, Welcome to the big four oh .
Posted in Mister Joomla .