Thursday, January 07, 2010

Practical Php Patterns: Abstract Factory

This is the first installment of the Practical Php Patterns series, which would touch the majority of the known design patterns, with a special look at their application in a php context. A running code sample will be provided for each part of this series, along with the theory and the terminology of each pattern.

The patterns that will be discussed first, following the original GoF Design Patterns book approach, are the creational ones. Creating object graphs is an essential skill in object-oriented development and correctly addressing the bootstrap of the application and the object instantiation is part of the programming's complexity.

The first pattern we will introduce is the Abstract Factory one, also known as Provider or simply as Factory, in its variant which does not include explicit interfaces.
The major problem that creational patterns try to solve is that objects need collaborators: we often pass them in the constructor of a Client class to aid decoupling, as every class should know only what it really needs to get its job done. With the verb know I mean that they just know that the other part exist at all.
The fundamental principle of asking for things (Dependency Injection) substitutes the naive approach of looking for things or creating them.
A Client is simply the generic name of an high-level class which makes use of the collaborators, and occurs frequently in the design patterns Ubiquitous Language. These generic names are known as participants in a pattern, and allow developers to discuss a pattern without referring to a particular implementation.

Dependency Injection prescribes to ask for collaborators in the constructor of a Client, or via setters that accepts the collaborator as a parameter to store it for later use. Most of the times collaborators are created at the startup of the application/script, before their Client, to satisfy the dependency.
The fallacy here (which is not really a fallacy, since it works most of the time) is evident when the collaborators assume shorter lifecycles. Often objects are created as a result of business logic (a Post or Forum instance, for example, in the middle of a php script), and by the way with a shorter lifecycle of the object that creates them. As another example, they can be lazily created only when necessary.
In php's case, lazy creation is mandatory because there is no need to create all kinds of helper objects on every single http request. You certainly do not expect to define all your buttons, links and inputs at the startup in a single object graph: their creation is regulated by an analysis of the request parameters and of the database state.

Though, you may want to govern which kind of objects are created: if the names of the ConcreteProduct classes are hardcoded in the Client, you lose the flexibility of Dependency Injection, which provide advantages like real unit testing and decoupled design.
The AbstractFactory solution consists in encapsulating the creation process behind an AbstractFactory interface, which may be implemented by how many different ConcreteFactory classes are needed. One of this ConcreteFactory is then injected in the Client that will call its methods to create the objects, when ready.

Pattern participants:
  • AbstractProduct: the interface for the collaborator
  • ConcreteProduct: an implementation of the collaborator
  • AbstractFactory: the interface for the factory that builds an AbstractProduct
  • ConcreteFactory: an implementation of the AbstractFactory, to be injected in the Client
  • Client: the final user class of the collaborator
I will finally let the code speak now.
<?php
/**
 * SECTION 1: a WidgetHelper interface and two different implementations.
 * Normally we would inject the chosen WidgetHelper to the Client class, but
 * creating all possible helpers renders the constructor enormous, whilst we
 * are not even sure that they would be actually used.
 *
 * This class purpose is to generate blinking text in spite of all
 * usability recommendations. This is the AbstractProduct.
 */
interface WidgetHelper
{
    /**
     * @return string
     */
    public function generateHtml($text);
}

/**
 * Implementation that generates html tied to a javascript library.
 * This is one ConcreteProduct.
 */
class JavascriptWidgetHelper implements WidgetHelper
{
    public function generateHtml($text)
    {
        return '<div dojoType="...">' . $text . '</div>';
    }
}

/**
 * Implementation that generates html that loads a flash object.
 * This is one ConcreteProduct.
 */
class FlashWidgetHelper implements WidgetHelper
{
    public function generateHtml($text)
    {
        return '<object>
        <param name="text">' . $text . '</param>
        </object>';
    }
}

/**
 * SECTION 2: since we are not going to pass the instances of WidgetHelper to
 * the Client class (because they do not exist yet), we need an interface
 * for the creator of these WidgetHelpers, which results in an Abstract Factory.
 * This is the collaborator which would be injected in the client.
 */
interface WidgetHelperAbstractFactory
{
    /**
     * @return Widget
     */
    public function createWidgetHelper();
}

/**
 * First implementation: creates a Javascript-based helper.
 * This is one ConcreteFactory.
 */
class JavascriptHelperFactory implements WidgetHelperAbstractFactory
{
    public function createWidgetHelper()
    {
        return new JavascriptWidgetHelper();
    }
}

/**
 * Second implementation: creates a Flash-based helper.
 * This is one ConcreteFactory.
 */
class FlashHelperFactory implements WidgetHelperAbstractFactory
{
    public function createWidgetHelper()
    {
        return new FlashWidgetHelper();
    }
}

/**
 * Third implementation: creates a random type of helper.
 * Note that commonly the WidgetHelperAbstractFactory interface will require
 * methods to create all the helpers needed. It's up to the single
 * ConcreteFactory implementation to instantiate a family of objects
 * (flash|javascript html bindings generators) or another,
 * or even a mixture of different families or whatever.
 * Dependency Injection containers take this approach to the extreme,
 * providing automatically configurable factories for every
 * concrete class.
 */
class RandomHelperFactory implements WidgetHelperAbstractFactory
{
    public function createWidgetHelper()
    {
        srand();
        if (rand() > 0.5) {
            return new JavascriptWidgetHelper();
        } else {
            return new FlashWidgetHelper();
        }
    }
}

/**
 * SECTION 3: a Client class that uses an AbstractFactory to create Widget
 * instances whenever it wants.
 * Note that this class only depends on abstractions (AstractFactory and its
 * AbstractProduct). However, since php has no compile-time dependencies,
 * an interface for the Products or the Factories is not mandatory.
 */
class LoginPage
{
    private $_widgetFactory;

    public function __construct(WidgetHelperAbstractFactory $factory)
    {
        $this->_widgetHelperFactory = $factory;
    }

    public function render()
    {
        $userId = uniqid('User ');
        // insert all the logic needed here...
        if (true or $complexBusinessLogicRules) {
            $helper = $this->_widgetHelperFactory->createWidgetHelper();
            return $helper->generateHtml("Welcome, $userId");
        }
    }
}

$page = new LoginPage(new FlashHelperFactory());
echo $page->render(), "\n";
$page = new LoginPage(new JavascriptHelperFactory());
echo $page->render(), "\n";
Often factories in php applications are applications of this pattern without the abstract trait, with a developed dependency towards a ConcreteFactory. With the same pragmatism, different kind of collaborators which are highly related can be placed in the same ConcreteFactory, by adding other creation methods.
I hope you now grasp how to build objects at the right time in your application, as lazily as you want, without depending on concrete classes.
Tomorrow we will discuss another creational pattern, the Builder one.

Don't forget to comment if you like the post or you feel something is missing. Feedback can drive the evolution of this series of articles.

Tuesday, January 05, 2010

New Year's resolution (a bit late)

I think setting smart goals is a good practice in personal and professional development. I decided to share my goals for the solar year 2010 to become accountable for the results I achieve and my potential failures. It's January 5th, but it's better late than ever.
These are my plans for 2010:
  • first, maintaining this blog with a regular posting schedule throughout all the year. I took a pause during the holidays but I intend to post 5-6 new articles a week, whilst the topic of the blog does not change: software development and engineering. Given the 52 weeks contained in an year, this goal results in 285 posts that should fill the 2010 archive.
  • this year I will obtain my bachelor's degree in Computer engineering. I commit to sustain the final test in the July or September sessions.
  • I will get a B2 English language certification, in order to graduate. This is an independent exam, external to my university, required for the degree.
  • finally, I commit to produce a stable release of my personal project, NakedPhp. NakedPhp is a php port of the Naked Objects Framework for Java, which generates a user interface for direct manipulation of objects and classes. Currently the subversion repository has reached the hundredth revision, which is not bad for a solo developer.
Considering the English language certificate as part of the degree, these are my three major projects for the year. I think I can sustain this workload, as I have no strong need to take freelancing gigs for financial reasons in this period, which would consume time I dedicate to open source.
Though, the main issue with goals is not the setting phase, but achieving them: every two months I will post about these goals and the steps I will have taken to reach them.
Happy new year everybody and happy resolution!

Tuesday, December 29, 2009

Packing for Florence

Tomorrow I am leaving for Florence, in the occasion of New Year's Eve. I will be back in 2010 (just a few days :) and I'll return to post regularly on the week of January 4.
Happy partying!

Monday, December 28, 2009

Practical Php Testing exercises

As you probably know there is a Creative Commons licensed ebook available on this blog, Practical Php Testing.
Tomaž Muraus wrote to me yesterday about solving the TDD exercises contained in the various chapters:
I had some time during the past few days so I read your book and solved the exercises found in the book.
I'm pretty sure not all of my solutions are the best and some could probably be improved / changed so I decided to create a Github repository with my solutions (http://github.com/Kami/practical-php-testing-exercise-solutions) so others can fork it and improve / refactor my solutions.
I hope you can find these examples useful, but try not to read a solution before actually trying to solve an exercise. I have not proof read this code but it seems that its quality is good. There is always room for improvement, especially in the stubs section of the tests, and in refactoring of the production code.

Friday, December 25, 2009

Merry Christmas

Saying it with John Lennon, merry Christmas and a happy new year to all the Invisible to the eye readers!

Tuesday, December 22, 2009

Asking the community: a standard for @return array

It would have certainly happened to you to define a phpDocumentor annotation on a function or a method:
<?php
/**
 * @param string $a   name your parameter better than this one
 * @return boolean
 */
function doSomething($a)
{
    // code... 
}
These annotations are parsed by phpDocumentor to automatically produce Api documentation in various formats, such as html and pdf.
It is also true that you can specify a class name as a data type:
<?php
/**
 * @return Zend_Form_Element
 */
function doSomething()
{
    // code... 
}
Since this is a widely employed standard for php frameworks, I decided to rely on @return annotations as the mean to define domain model relationships in my project NakedPhp. This is not different from the relationships phpDocumentor infers to generate links between html documents: for instance the Zend_Form_Element return type definition would be printed as a link to its actual Api documentation html page, to allow fast navigation.
But what happens when you want to specify that a methods return an array or a collection of elements?
<?php
/**
 * @return array
 */
function doSomething()
{
    // code... 
}
Not very clear, as the question that arises is "What is the type of array elements?"
Note that Php is a dynamic language and arrays can be heterogenous, but very often they contain elements of the same type for the sake of consistency; consider for example an array of Zend_Form_Element instances: even if they are different elements they share a common superclass whose methods you can call without fear.
Note also that Php lacks a real collection class or interface, and even if a generic one is provided by a framework, the annotation would not be much clear.
/**
 * @return Doctrine\Common\Collections\Collection
 */
or:
/**
 * @return ArrayObject
 */
At least in the former case you know that there are homogeneous elements in the returned collection, but the situation is the same.
Since arrays and collections are used as dumb containers, the first thing you will do on an array is to iterate on it, and then you will need to know what is the class of the contained elements to find out which methods to call, or which methods accept this kind of elements.
Of course you can do something like this:
/**
 * @return array   of @see Zend_Form_Element
 */
But this is not a standard, and different developers would use different annotations:
/**
 * @return array   this contains Zend_Form_Element instances
 */
/**
 * @return array   of Zend_Form_Element 
 */
These annotations would be parsed by phpDocumentor, but the class name would be mangled in a string and not manageable anymore. It's like scraping a blog versus using a feed.
PHPLint documentation says it recognizes annotations like array[K]E, as in this example:
/**
 * @return array[string]Zend_Form_Element 
 */
They also say that phpDocumentor already support it, but there is no trace of that in its own documentation:
The datatype should be a valid PHP type (int, string, bool, etc), a class name for the type of object returned, or simply "mixed".
The original Naked Objects implementation is written in Java and takes advantage of generics (not available in Php):
/**
 * @return List<FormElement>
 */
When javadoc or Naked Objects parse annotations, they know instantly the collection elements type, thanks to a reasonable standard that imitates the language syntax: I would be glad to do the same in Php, but there is no syntax to refer to.
I turn thus to the community, which comprehends millions of talented developers. My question is: how would you specify @return annotations for containers of elements in a way to include the elements type? I hope to grasp a de facto standard, which I can then require to follow in NakedPhp applications.

Monday, December 21, 2009

The Advent that became Tribulation

There is a nice initiative in the php community whose goal is to put together a set of best practices for php programmers and to having them explained every day of December from experienced developers: the PHP Advent.
However, this year I have been disappointed by the quality of the articles in the advent. First, there is no Add Comment form. What? What advent is this, 1995's one? Are the articles stored as static html files? I remember there were definitely comments in 2007.
After having asked the reason on Twitter, I got this response:
@giorgiosironi we've considered adding it, but like the idea of crosslinking with our authors' blogs when they create an entry. /cc @chwenz
The problem is that there is no duplicate post on the author's blog, at least for the majority of them. The only place where leaving a comment makes sense is on the original article, which admits no feedback.
Now we can start to list what I, and probably many other developers, would have commented on some of the articles.

December 8: Testing with PHPT and xUnit
The author suggests to abandon the standard testing framework for php, PHPUnit, to use PHPT, the testing harness for the php core itself.
PHPT has a very simple plain text interface where you specify text files containing the code to execute and its expected output. Not as variables - as text output, usually of var_dump(). This tool is used to testing php itself because using a real framework with more features, like PHPUnit, means that it will probably break while running the test suite if a regression is introduced in php.
Then what are the reasons to dismiss PHPUnit if you are not developing the php interpreter? The author say "with PHPT you can test for expected fatal errors!". Why I would want an expected fatal error in my application? With a nice blank page shown to the end user? I can't even think of renouncing to PHPUnit.

December 12: JSON Gotchas
Towards the end of the article, the author says something like: You know what is really cool? Passing an anonymous function in a Json string.
var jsonString = "({name: 'value', toString: function() { return this.name; }})";
What's the problem? That this is not Json, it's plain javascript syntax... Json.org says a value is string|number|object|array|true|false|null and an object is something which is enclosed in {}. Do you see anonymous functions in this specification?
This Json string would probably work if passed to eval(), but not to secure Json parsers. The author recognizes that you cannot avoid eval() in this case, but it's not a mystery why: because it's not Json anymore, and calling it Json causes confusion, much like $array = new stdClass(); and other obfuscated code.

December 18: You Don't Need All That
Classes are slow! MVC is even slower! Real men do not use autoloading! We should stick to require_once(). The best part?
Or, put some effort into writing more general, commonly-used classes rather than lots of little ones.
Never, ever, heard of Single Responsibility Principle? Cohesion? Decoupling? That design should not be driven by how fast including source files will be? I actually refactor every class that surpasses 400-500 lines of code.
If you're thinking to follow the advice of discarding autoloading, maybe you'd like to know that PEAR 2 will drop require_once() statements. As for the post, if you do not believe me as a source of information, Roman Borschel, the lead developer of Doctrine 2, says:
@giorgiosironi agreed. complete crap. Another meaningless artificial benchmark. Not even with repro code. that post is a big #fail.
There are very valid posts in this year's PHP Advent, but these hidden "gems" are dangerous and I wonder why no feedback is accepted. Open discussion would benefit the community more than lectures on php practices.

Featured post

A map metaphor for architectural diagrams

It is a (two-dimension) representation of a pipe. The map is not the territory , but in software engineering terms they are models of it....

Popular posts