Favour Composition over Inheritance

Wednesday, June 4th, 2008

I was just reading through the current issue of php|architect (April 2008) and I noticed a particular piece of code that irked me to the point that I need to write about it. If you’re interested, the article is Exceptional Error Handling. Don’t get me wrong, it’s a well written and informative article, however, one of the listings (Listing 9) has some really hacky code in it. The hack is only in the constructor, but the flaw is in the design. A flaw that can easily be overcome with a piece of sage advice from the Gang of Four: “Favour object composition over class inheritance” [GoF20]

The intention of the code is to have a singleton class that extends PHP’s ArrayObject class. Here’s the code snippet:

class LogService extends ArrayObject
{

    private static $instance;

    public function __construct(Array $loggers = array())
    {
        // examine backtrace to see how the constructor was called
        $backtrace = debug_backtrace();

        // throw exception if we were not called from the
        // getInstance() method of this class
        if ($backtrace[1]['class'] !- __CLASS__ ||
            $backtrace[1]['function'] != 'getInstance'){
            throw new SingletonException('...');
        }

        parent::__construct($loggers);
    }

    public function getInstance(Array $loggers = array())
    {
        if (!self::$instance){
            self::$instance = new LogService($loggers);
        }
        return self::$instance;
    }

    ...
}

NB: i left out the rest of the class and the content of
the exception message because it's not really relevant
to the point at hand.

Can you spot the problem here?

The problem is that this breaks one of the main rules of the singleton pattern — that new instance of the class cannot be created from outside of the class — and then attempts to reconcile it by checking the backtrace and throwing an exception. Since the constructor of the ArrayObject class is defined as public, any child classes of ArrayObject must also have their constructor defined as public. This is because access to a method of a child class cannot be more restrictive than that method in the parent class. The final solution ended up being a hacky mimic of the singleton pattern.

Ockham’s razor (or at least a paraphrased version): “the simplest solution is the best”

Checking the backtrace and throwing an exception is not the simplest solution. The simplest solution is to favour composition over inheritance.

Let’s look a little deeper at the ArrayObject class

ArrayObject

You’ll see that the ArrayObject implements 3 interfaces: IteratorAggregate, ArrayAccess, and Countable. These interfaces are what allow php to treat instances of the ArrayObject as native array, i.e. using it in a foreach loop, accessing elements of the ArrayObject, finding out how many elements are in the ArrayObject, etc.

Let’s see how we can use composition and interfaces to write an equivalent singleton class without the need for the hacky constructor


class LogService implements IteratorAggregate, ArrayAccess, Countable
{

    // the only available instance of this class
    private static $_instance;

    // an instance of ArrayObject. using composition rather than
    // inheritance
    private $_array;

    // private constructor as an optimal solution for the singleton
    // pattern
    private function __construct(Array $loggers = array())
    {
        $this->_array = new ArrayObject($loggers);
    }

    // method required by the IteratorAggregate interface
    public function getIterator()
    {
        return $this->_array->getIterator();
    }

    // method require by the ArrayAccess interface
    public function offsetExists($index)
    {
        return $this->_array->offsetExists($index);
    }

    // method require by the ArrayAccess interface
    public function offsetGet($index)
    {
        return $this->_array->offsetGet($index);
    }

    // method require by the ArrayAccess interface
    public function offsetSet($index, $newval)
    {
        return $this->_array->offsetSet($index, $newval);
    }

    // method require by the ArrayAccess interface
    public function offsetUnset($index)
    {
        return $this->_array->offsetUnset($index);
    }

    // method require by the Countable interface
    public function offsetCount()
    {
        return $this->_array->count();
    }

    public function getInstance(Array $loggers = array())
    {
        if (!self::$_instance){
            self::$_instance = new LogService($loggers);
        }
        return self::$_instance;
    }

    ....

}

In my opinion this is a much more elegant solution, even if it does require a little bit more coding (and very trivial code at that). There’s no way to call the constructor outside of the class and thus no need to manage the possibility of an exception thrown by the constructor. It serves the same purpose as the original code (you could even implement the php’s magic method __call() in the LogService class to essentially proxy method calls to the instance of the ArrayObject) and is more inline with the intention of the Singleton pattern.

What do you think? Which solution would you prefer? What do you think is more important: good design practices or less lines of code?

Oh CRUD… (Part 3)

Tuesday, May 6th, 2008

Well, somewhat unfortunately, there won’t be a part 3 to this blog post. I ended up pitching the idea to php|architect magazine (http://www.phparch.com) and they will be publishing it in their july 2008 issue. I’ll post any links and relevant data sometime in july. So keep your eyes peeled for that.

In the mean time, check out the current issue of php|architect here

Oh CRUD… (Part 2)

Monday, February 4th, 2008

My last post was basically just an outline of the CRUD processes and a brief touch on the design patterns that will allow us to make dealing with CRUD a thing of the past. If you weren’t already, hopefully by now you are familiar with various design patterns listed in my last post

Let’s start with a basic implementation of the Command Pattern:

Fig. 1A

Command

The Command class is an abstract class (or in this case, it could easily be an interface) that defines the methods which must be implemented by all subclasses. Note that it accepts a Context object as a parameter (I’ll talk more about the Context Object patter below).

Example 1A: A very simple Command class

abstract class Command
{

    /**
     *
     * @var Context
     */
    private $context;

    /**
     * Initializes the Command object. Ensures child classes cannot
     * change its interface
     *
     * @param Context $content
     */
    public final function __construct(Context $context)
    {
    	$this->context = $context;
    }

    /**
     * An abstract function to be implemented by subclasses
     * Processes the context object and returns a status result
     *
     * @return int
     */
    abstract public function execute();

}

Create

The Create class is a subclass of Command. In our simple case, it merely implements the execute() method. It uses the Retrieve class to get an instance of the Object (where Object is a class from your ORM. I’ll talk more about the ORM below) being created, performs operations on the object, and then marks it for insertion into the database. Example 1B is a very simplified version of the Create command, it is bereft of error checking and will require additional work before it is ready to be used; it’s just a snippet to get you started.

Example 1B: A very simple Create command

class Create extends Command
{

    /**
     * processes the context and instantiates, populates, and stores
     * a domain object
     *
     * @return int
     * @throws Exception
     */
    public function execute()
    {

        // get an instance of the object to be created
        $object = Retrieve::newInstance(
                          $this->context->getClassName()
                      );

        // delegate to the context to populate the object
        // with values from the request
        $this->context->populateObject($object);

        // mark the object for insertion into the database
        // note: alternatively, and depending on your ORM,
        //         insert into the database can happen here
        $object->registerNew();

        // put the new object into the context to allow
        // the caller of this method to get access to it
        $this->context->setObject($object);

        // return a status flag based on the execution
        // of this method
        return 1; 

    }

}

Retrieve

The Retrieve Command has the most functionality of the 4 CRUD Commands since it has static methods for returning object instances. In addition to it’s execute method, it has two static methods, newInstance() and findInstance(). The newInstance() method takes a class name as a parameter and uses the native php Reflection classes to return a new instance of the supplied class name. The findInstance() method attempts to use methods on the ORM class to retrieve an object from the database. If no object exists, it returns null, but could alternatively return an instance of the Special Case/Null Object Pattern. The execute method just uses the findInstance() method to attempt to retrieve an object from the database.

Example 1C: A very simple Retrieve command

class Retrieve extends Command
{

    /**
     * use information on the context to retrieve a domain
     * object from the database
     *
     * @return int
     * @throws Exception
     */
    public function execute()
    {

        // get an instance of the object
        // note: where 'find' is a method available on the
        //         ORM classes and used to get info from
        //         the database
        $object = Retrieve::findInstance(
                          $this->context->getClassName(),
                          $this->context->getId(),
                          'find'
                      );

        // mark the object a recieved from the database
        $object->registerClear();

        // put the new object into the context to allow
        // the caller of this method to get access to it
        $this->context->setObject($object);

        // return a status flag based on the execution
        // of this method
        return 1; 

    }

    /**
     * returns an instance of the object that is represented by
     * the supplied class name and unique identifier.
     *
     * @param string $className
     * @param mixed $id
     * @return Object
     * @throws Exception
     */
    public static function findInstance($className,
                                        $id,
                                        $methodName
                                       )
    {
        $method = new ReflectionMethod($className, $methodName);
        $object = $method->invoke(null, $id);
        return $object;
    }

    /**
     * Returns a new instance of the supplied class name
     *
     * @param string $className
     * @return Object
     * @throws Exception
     */
    public static function newInstance($className)
    {
        $class = new ReflectionClass($className);

        if (!$class->isInstantiable()){
            throw new Exception(
                'Class in context object is not instantiable.'
               );
        }

        $object = $class->newInstance();

        if (is_null($object)) {
            throw new Exception('No instance of an object given.');
        }

        return $object;

    }

}

Update

The Update Command is very similar to the Create command. Instead of retrieving a new instance, it attempts to retrieve an instance from the database. It delegates to the context object to update the object properties with values from the database and marks it for update in the database. Based on the code for Create and Retrieve, you should be able to figure out the code required for the Update Command.

Delete

The Delete Command is not unlike the Update command. It retrieves an instance of an object from the database and marks it for deletion. Again, based on the code above, you should be able to figure out the code required for the Delete Command.

Until Next Time…

In my next article, we’ll delve into the Conext Object and ORM classes, tying up all of the loose ends and finishing with a complete CRUD solution.

Oh CRUD…

Wednesday, January 23rd, 2008

If you’ve been doing web programming for even a small amount of time, you’ll already have noticed the massive amount of repetition when creating, retrieving, updating, and deleting (CRUD) rows from a database. They don’t call it crud for nothin’…


crud

noun
1. any substance considered disgustingly foul or unpleasant [syn: filth]


It ends up becoming so tedious that it can lead you to the brink of insanity. This is where object oriented programming and design patterns come to the rescue — keeping you out of a straight jacket and allowing you to get the CRUD out of your life. That way you can spend your time on more interesting and fulfilling pursuits such as developing a time machine, or writing that great Canadian novel.

No matter what programming language you’re using, your CRUD operations are going to be basically the same. You should be able to abstract a common process for each CRUD operation. You’ll notice that even within these processes, certain CRUD operations are used, e.g. both UPDATE and DELETE make use of RETRIEVE.

CREATE:
- get a new instance of the object to be created
- validate the data on the HTTP request
- if the data is valid, populate the object with data on the HTTP request
- store the object in the database

RETRIEVE:
- use the data on the HTTP request to retrieve an instance of the object to be updated from the database

UPDATE:
- use the data on the HTTP request to retrieve an instance of the object to be updated from the database
- if an object exists, validate the data on the HTTP request
- if the data is valid, populate the object with data on the HTTP request
- store the object in the database

DELETE:
- use the data on the HTTP request to retrieve an instance of the object to be updated from the database
- if an object exists, remove if from the database

There are 3 design patterns in particular that you’ll need to be familiar with in order to come up with a slick solution for cleaning up the CRUD:

The goal here is to make the CRUD processes reusable for most common cases and easily extendible for special cases. A great way to make processes reusable is to use the Command pattern. The Gang of Four define the Command pattern as a way to: “[e]ncapsulate a request as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations”. What does this mean for CRUD? Well, it allows us to encapsulate the different CRUD processes in objects: one object for each process. We don’t need to know anything about how the command is called or received, so the CRUD processes can be reused in many different contexts.

Speaking of contexts… this is where the Context Object pattern come into play. In the outline of the CRUD processes (see above), I mentioned that data will be coming from an HTTP request. In most cases, HTTP requests are what you’ll be familiar with. You’ve probably spent a lot of time using $_REQUEST (or $_GET and $_POST)? There are some cases where data won’t be coming in through an HTTP request, such as, if your php app is used on/called from the command line or if the data you’re receiving is tied into a different protocol, such as SOAP.[1] Context objects are used to encapsulate the request data so that the Commands can work with a common interface, i.e. treat all requests as though they are the same, regardless of how the request data is received by the application.

The last, and arguably the most important aspect of CRUD operations, is your ORM. There is no CRUD unless there is something to apply CRUD to. It’s your ORM that supplies the objects that will be created, retrieved, updated, and deleted. As far as ORM’s go, you can build your own (depending on the needs/requirements of your application) using any one of the 3 ORM patterns listed above, or you can use a 3rd party tool like Propel. The pro’s and con’s of these options are out of the scope of this article, but if you’ve read this far and still haven’t decided on an ORM, you should probably do that before reading on…

So that’s CRUD in a nutshell. Love it or hate it, you’ll have to deal with it. In my next article, we’ll start dig into the CRUD and see how the different design patterns (described above) work together to form a solid solution. I’ll focus on the Command pattern first and provide some concrete PHP code to help you get started on your implementation. The third and final article will cover the Context Object pattern and your ORM pattern of choice. By the end, you’ll have the skeleton of a CRUD implementation at your finger tips.

Read the Next Article

Footnotes:

[1] although a SOAP request is generally transferred over HTTP, the SOAP data will often be extracted from the HTTP request and put into a SOAP specific object before being passed off for processing.