Posts Tagged ‘oop’

Mixins in PHP

Wednesday, August 23rd, 2006

One of the concepts I like in Ruby is the concept of 'mixins'. Mixins are a way of 'mixing in' functionality of other classes.

A kind of 'multiple inheritance' like approach, only without actual inheritance. It is similar to interfaces, but interfaces only tell you that an object must implement certain methods, whereas mixins also provide an implementation.

It's a bit hard to describe in a few sentences, but this article and the pragmatic programmer's guide provide a good explanation. But I'll explain the concept with examples below.

In the past, there have been attempts to apply mixins to PHP, but this, back in 2002, required quite some cumbersome code, due to the limitations that PHP4 had at that time. I was wondering if some of PHP5's new features would make this easier, and I managed to create a mixin solution with only a few lines of code.

I'll start with the example that explains the mixins, and after that, I'll show the code that makes it possible. I'll end this post with a few quirks that I encountered, for which I solicit comments to improve the solution.

Classes to mixin

Let's first create some classes that can be mixed in. I've created two, that each implement some display functionality:

 
  class Alertable
  {
    function alert()
    {
      $str = $this->toString();
      echo '<script language="javascript"> alert(\''.$str.'\'); </script>';
    }
  }
 
  class Blinkable
  {
    function blink()
    {
      echo "<blink>".$this->toString()."</blink>";
    }
  }
 

The classes are plain and simple, they have a single method that contains the display logic. One displays a javascript alert, the other displays a blinking text. The first thing to notice here is the call to $this->toString(). There is no method called toString to be found in the class. This is no problem however, because these classes will never be used directly. They will be mixed in, in another class, and $this will point to the instance of that class after being mixed in. We only require the class that mixes in these methods, to have a toString method.

Applying the mixins

Using the mixins is fairly easy:

 
 
  class Hello extends Object
  {
    var $mixins = array("Alertable", "Blinkable");
 
    function toString()
    {
      return "Hello World";
    }
  }
 
  $o = new Hello();
  $o->alert();
  $o->blink();
 

The class Hello extends 'Object', which is a class I wrote. It makes the mixins possible. I'll get to this class later. But let's first look at the effect of applying the mixin.

In the member variable $mixins, I store an array of classes I want to mix in. Then, I create an instance of the class, and I can call alert() and blink() on this object, as if the methods were part of the Hello class. Notice how this looks quite natural? The user of the class won't notice that these methods are actually defined elsewhere, and the developer of the class has an easy way of reusing functionality.

As with inheritance, the methods are overridable: if I would still define a custom alert() method on the Hello class level, this method would be called instead of the mixin. This makes it possible to override parts of the behaviour of the mixins.

How it works

Let's take a look at how this works. The handling of the mixins is done by the Object class. There are two key elements in this solution. First, I make use of the PHP5 magic method '__call' to intercept calls to the objects, and redirect methods to the mixins when necessary. Second, there is a little known, but for mixins very important, feature in PHP, which is explained in the oop basics of the PHP manual:

"$this is a reference to the calling object (usually the object to which the method belongs, but can be another object, if the method is called statically from the context of a secondary object)."

It is a mystery to me why such a confusing concept is the first thing in the 'basics' page, but it is very useful. What this basically means that $this does not necessarily point to the current object, but to the calling object, as long as the method is called statically. You've noticed the $this reference in the Blinkable class above; What I basically did was make sure that the method in the mixin was called statically and voila, $this points to the object that is using the mixin, and the mixed in class code looks very natural, like it is a part of the class it will be mixed into.

Here is the code for my Object class:

 
  /**
    * Generic base class for all objects that want to make use of
    * mixin functionality.
    */
  class Object
  {
    private $_mixinlookup = array();
 
    // The constructor takes a look at the mixins, and creates a lookup
    // array, so upon a method call, we can quickly determine whether the
    // method was mixed in.
    function Object()
    {
      if (is_array($this->mixins))
      {
        foreach($this->mixins as $mixin)
        {
          $methods = get_class_methods($mixin);
          if (is_array($methods))
          {
            foreach($methods as $method) $this->_mixinlookup[$method] = $mixin;
          }
        }
      }
    }
 
    // The __call magic method intercepts any method that does not exist
    // and falls back to one of the mixins if they define the method that is
    // being called.
    function __call($method, $args)
    {
      if (isset($this->_mixinlookup[$method]))
      {
        $elems = array();
        for ($i=0, $_i=count($args); $i<$_i; $i++) $elems[] = "\$args[$i]";
        eval("\$result = ".$this->_mixinlookup[$method]."::"
            .$method."(".implode(',',$elems).");");
        return $result;
      }
      trigger_error('Call to undefined function '.$method, E_USER_WARNING);
    }
  }
 

This code won't win any performance prizes unfortunately, I had to use eval to dynamically call a static method. Other, more efficient ways should work, but I'll explain why they didn't in the 'Quirks' section below. For many types of application however, the performance penalty is low compared to the power of mixins that you get.

Practical application

Now that I've explained the concept of mixins, and how to make it work in PHP5, I'll give some examples of when to use it. In the real world, you probably won't be using Blinkables, but there is a lot of functionality you can think of that can be mixed in to make classes powerful. For example, if you have a custom Collection class, and you create methods to access all its elements, you could easily create mixins such as Sortable, Enumerable and Iterator. These would add sort, enumeration and iteration methods to your object, without cluttering your object with the code.

Also, whenever you find yourself in a situation where you think you need multiple inheritance, rethink the issue and see if mixins are suitable. Often, you'll find that mixins accomplish exactly what you hoped to accomplish if you had multiple inheritance.

Quirks

I promised to end with some quirks I ran into. You can safely skip this section if you're not interested in gory details. :-)

There was actually only one problem that I encountered that lead me to use eval() for the mixin functionality. I've talked about the $this pseudo-variable and how when called statically, $this points to the calling object. Well, even though this is documented in the first part of the oop basics in the PHP manual, it only works in the case where a method is called with the classname::methodname construction. What I would've liked to use, was call_user_func_array or even better, Andrei's Reflection API, which is much more powerful. With the reflection API, the __call method would've looked like this:

 
 
  function __call($method, $args)
  {
    if (method_exists($this, $method))
    {
      return call_user_func_array(array($this, $method), $args);
    }
    if (isset($this->_mixinlookup[$method]))
    {
      $method = new ReflectionMethod($this->_mixinlookup[$method], $method);
      return $method->invoke(NULL, $args);
    }
    trigger_error('Call to undefined function '.$method, E_USER_WARNING);
  }  
 

This would've been more clean, and probably is faster. Now why doesn't this work? First, to call the method statically, I have to pass NULL as first parameter to invoke. This leads to the following error however:

Non-object passed to Invoke()

The reason is that invoke refuses to call my static method if it has not been defined with the 'static' keyword. Easy, you would think, just make your method truly static:

 
  static function blink()
  {
    echo "<blink>".$this->toString()."</blink>";
  }
 

This leads to a different error:

Fatal error: Using $this when not in object context

This kind of invalidates the whole '$this refers to the calling object' part of the documentation. I'm not sure if I should file a bug report for this, comments are appreciated. (I guess that even if it would not throw an error, it probably wouldn't work anyway because $this would be pointing to the ReflectionMethod object instead of my object instance).

Conclusion

I've tried to demonstrate how the powerful concept of Mixins can be applied in PHP. Since it only takes a few lines of code, I guess it would not be hard to make this a standard feature of the PHP language, so I would really like to see true mixin support in PHP6. But if that doesn't happen, I hope to have provided a fairly easy way to apply the concept to your PHP classes anyway.

Feel free to use the code samples in this post, a reference to the post in your code would be appreciated but is not required.

Building proxies, decorators and delegates in PHP5

Monday, July 3rd, 2006

In PHP5, you can define methods in an object for intercepting calls to methods of an object and for intercepting access to object member variables. These methods (__get, __set and __call) enable the implementation of very generic proxies, decorators and delegators.

(For those unfamiliar with these design patterns, the extensive descriptions at wikipedia are worth the read.)

What proxies, decorators and delegates have in common is that they all change a part of the behaviour of an underlying object by overriding its methods, while forwarding the rest of the calls to the original object.

I wouldn't like this post to be purely theoretical, so let's use a simple example with decorators to demonstrate the concept.

Suppose we have the following class:

 
class HelloWorld
{
  function sayHello()
  {
    return "Hello World";
  }
 
  function doSomethingElse()
  {
  }
}
 
$obj = new HelloWorld();
echo $obj->sayHello();  // "Hello World"

We would also like to create classes that decorate the hello-saying. I want to have a decorator that makes the output bold, and another one that makes the output italic. (You could create a class that extends HelloWorld, but more in this later. For the moment, assume that inheritance is not an option.)

In classic code, if I wanted to decorate the sayHello method, I could create a decorator object that looks like this:

 
 
class BoldHelloWorld
{
  var $m_object = NULL;
 
  function BoldHelloWorld(&$object)
  {
    $this->m_object = $object;
  }
 
  function sayHello()
  {
    return "<strong>".$this->m_object->sayHello()."</strong>";
  }
 
  function doSomethingElse()
  {
    return $this->m_object->doSomethingElse();
  }
}
 
$obj = new BoldHelloWorld(new HelloWorld());
echo $obj->sayHello(); // "<strong>HelloWorld</strong>"

This would work like a charm, but the problem is in the doSomethingElse method. Well, not really a problem, it's just that I have to redefine it to forward the call to the original object. What if we had 5 methods, or 10? All of them would need to be forwarded.

What if there are member variables in place that should be accessible? You'd have to forward those too. (I know, exposing member variables is Evil, but sometimes the object in question is not developed by yourself and you just have to deal with it.)

PHP5 has excellent ways to solve this, and fairly easy too. It allows us to build a generic base class for our decorators that takes care of the whole forwarding problem. (Credit for this class goes to my coworkers Martin and Peter).

 
 
/**
  * AutoForward baseclass for automatic forwarding of
  * method calls and member variables.
  *
  * @author Peter C. Verhage
  * @author Martin Roest
  */
class AutoForward
{
  var $m_object;
 
  /**
   * Constructor.
   *
   * @param Object $object
   */
  function __construct(&$object)
  {
    $this->m_object = $object;
  }
 
  /**
   * Returns the forwarded object.
   */
  function &__getObject()
  {
    return $this->m_object;
  }
 
  /**
   * Forward method calls.
   *
   * @param String $method method name
   * @param Array $args method arguments
   * @return Unknown method return value
   */
  function __call($method, $args)
  {
   return call_user_func_array(array($this->m_object, $method), $args);
  }
 
  /**
   * Forward property set.
   *
   * @param String $name property name
   * @param Unknown $value property value
   */
  function __set($name, $value)
  {
    $this->m_object->$name = $value;
  }
 
  /**
   * Forward property get.
   *
   * @param String $name, property name
   * @return Unknown
   */
  function __get($name)
  {
    return $this->m_object->$name;
  }
}
 

By overriding __set, __get and __call, any methods to an object of the AutoForward class are automatically forwarded to the contained object.

Let's use this class to create our bold and italic decorators:

 
 
class BoldHelloWorld extends AutoForward
{
  function sayHello()
  {
    return "<strong>".$this->m_object->sayHello()."</strong>";
  }
}
 
class ItalicHelloWorld extends AutoForward
{
  function sayHello()
  {
    return "<em>".$this->m_object->sayHello()."</em>";
  }
}
 
$obj = new ItalicHelloWorld(new HelloWorld());
echo $obj->sayHello(); // "<em>Hello World</em>"

Notice how we no longer defined the doSomethingElse method? It is automatically forwarded to the original object. In fact, an object of type ItalicHelloWorld will behave exactly like a HelloWorld object. Any caller wouldn't know the difference. Except ofcourse that sayHello returns a manipulated result.

I promised to explain why inheritance wouldn't be the solution here. By providing both an ItalicHelloWorld and a BoldHelloWorld, I've tried to demonstrate this. What if you needed a string that was both bold and italic? Which of the two would you extend? PHP doesn't have multiple inheritance, so we would be stuck there.

But not in our example. It would simply be a matter of:

 
 
$obj = new BoldHelloWorld(
new ItalicHelloWorld(
new HelloWorld()));
echo $obj->sayHello(); // "<strong><em>Hello World</em></strong>"

Using this approach, we've worked around the need to have multiple inheritance.

This technique is also useful if you are a fan of Aspect Oriented Programming. You could have an object that implements a certain aspect and applies that to the underlying object. Instead of overriding a single method, you can override __call and implement an aspect.

Let's take security as an example. Suppose we have an object, but we want to secure access to any of its members. We could use the following class:

 
 
class SecurityAspect extends AutoForward
{
  function __call($method, $args)
  {
    if (isAllowed($method))
    {
      return call_user_func_array(array($this->m_object, $method), $args);
    }
    throw new Exception("Caller not allowed to execute $method on this object.");
  }
}
 
$obj = new SecurityAspect(new HelloWorld());
$obj->sayHello(); // throws error if sayHello not allowed

Another aspect that can easily be implemented like this is caching of resource intensive methods. Just add a list of methods to cache, and a member variable to hold results for cached methods.

With this post I've tried to demonstrate the power of PHP5's __call, __get and __set special functions. Java has similar solutions using reflection, but PHP5 makes it much more easy to create constructs like this. This also makes it possible to easily create patterns with small amounts of code.

Feel free to use the code samples in this post. You can link back to this post from your code to explain how the code works, if you like.

I know Kung Fu

Saturday, June 17th, 2006

This week I visited the Holland Open Software Conference. It was a nice conference, I will write a review later.

What I want to talk about now though, is what happened to me during this trip.

Before I begin, you should know that I am a die hard PHP fan, and I have been using PHP for 6.5 years now. If there is one thing that I've learned during this time, it's that PHP rules.

For a few months now however, friend and colleague Peter has been nagging me to check out Ruby. While I have been working mostly in PHP, he has used Ruby for the backend of epointment.com. I had looked at his code before, but it didn't catch on. It eyed weird, had funny-looking constructs (Ruby's lack of braces reminded me of Visual Basic even) and it was surrounded by a lot of hype, which often is a bad sign. It didn't even have a '++' operator. Get real.

Then he gave me this book they call the 'Pickaxe'. I tossed it on my desk, near the rest of the things-to-do-which-never-get-done.

But now I was going to this conference, which was a 2.5 hour train trip on both conference days, so I decided to check out the book to kill time while on the train.

The first day I read about 30 pages into the book, and I was intrigued. I read about how everything is an object, how even primitive types are objects. I read about code blocks (which turned out to be the funny constructs I didn't understand when reading Peter's code earlier), about the ability to redefine operators (which I remember from C++), about its regular expression support and about how Ruby encourages application of OO principles like encapsulation and loose coupling.

I had my laptop with me but no Ruby installed, so I wasn't able to try any of the code, but I was intrigued nevertheless.

At night, I decided to install Ruby so the next day I was able to actually hack away a bit. I read more in the book. I delved into collections, found out how they handle looping and how iterators are an intrinsic feature of the language. Around 100 pages into the book, I was hooked. I was writing classes, trying out all these language features, and it was great fun. I hadn't read nearly all of it yet, but at one point, I needed to get something done in my code, and without looking it up in the book, I just typed what I thought was the right way. I thought 'oh well, let's see what this does' and ran the script; and it simply worked. It didn't even generate a parse error. It was handled exactly the way I had expected it. This happened on 2 more occasions. So Ruby seems to be quite intuitive; if you have an idea of how the language is set up, what its approach to object orientation is, you can almost guess how you should accomplish things. So there I was, enjoying a new language. It felt like the first time I used PHP, back in 1999. Ik was astounded with the ease with which you could write programs (something which I never felt with C, C++ or Java).

I nearly missed my stop, and when I bagged my stuff and stepped out of the train onto a sun-engulfed platform, one thought crossed my mind.

"Whoa, I know Kung Fu".

It really felt like that. It was as if in a few hours, a whole new approach to programming was uploaded into my brain. In essence it was just a new scripting language I had just learned, but it merged perfectly with everything I ever learned about object oriented programming. I realised why they call it 'Ruby'. It is this clean language that has a pragmatic approach to object orientation that I haven't encountered before in any language.

And then, during the short walk from the station to the conference premises, I was reflecting on what had just happened. In my mind I was already looking at how I could do certain features of ATK more cleanly in Ruby. I was comparing how things are done in PHP and how the same things are done in Ruby. I marvelled at how Ruby fits ATK's "less code" philosophy.

And then I got scared.

What if I can't find any aspect of PHP that is better than Ruby? What if the only reason to still use PHP is 'that it is more widely used'? Surely that will not be the case, right? I have been using PHP for 6.5 years and it has never let me down. I am not crazy, am I? Ruby seems to be this shiny apple, but will eternal damnation come my way if I eat it? is Ruby the Red Pill? Will this be the beginning of the end? Will I switch from PHP to Ruby? This question has been bothering me since I got back from the conference.

After a good night of sleep, I've concluded that I will use both. PHP feels like this jeans that I have been wearing for years. It's worn out, but it's still my favorite jeans. It just has the right fit. I have other newer jeans that are less worn, but they still are not as comfortable as my old one. Although this Ruby jeans feels damn comfy, too.

But my jeans are not mutually exclusive. Neither are Ruby and PHP. So I'm going to use both. I'll use PHP here, and Ruby there. Let's just see what the future will bring. I will consider making a Ruby version of ATK (on top of the Rails framework), so I have two options when developing web applications. I hope to continue to be part of the PHP community for a long time, and I hope I will become part of the Ruby community too. Surely they'll accept me even if I still use PHP a lot.

In any case, one thing this tale has left me with is a deeper resolve for object orientation. I hope that for PHP 6 and 7, they will look more to their sister Ruby than to their predecessors Java and C++. Because Ruby knows how object oriented programming should, and can, be done.

The danger of Fluent interfaces

Friday, December 30th, 2005

After Martin, Mike and Paul have demonstrated the usefulness of Fluent Interfaces, I'd like to take a look at the downside.

Ironically, Martin's original example already demonstrates the problem:

 
customer.newOrder()
                .with(6, "TAL")
                .with(5, "HPK").skippable()
                .with(3, "LGV")
                .priorityRush();
 

newOrder could be implemented in two ways:
a) Create an order and return that new order
b) Add an order to this customer and return the customer

b is the fluid approach, a is more logical. In this example it's a.

This can lead to confusion; the 'with()' method employs method b. If you think that newOrder returns an Order, and hence 'with()' is a method of the Order class, look at 'skippable'. Martin states that order lines are skippable. So what's in front of skippable() is an OrderItem. That means that with() must have returned an OrderItem. If that is true, then with() is a method of OrderLine too!

So this means that in this case, probably both Order and OrderLine have a with() method. Apart from the fact that a method named 'with()' is dangerous as this can mean anything (which might be problematic for the non-fluent programmer), apparently in this case we have to add additional methods (both to Order and OrderLine) in order to be able to use this fluently.

priorityRush further demonstrates this. Where the second with() returned an OrderLine, the third with() now returns the order as priorityRush() is a method of Order.

While this *looks* more readable, it is actually confusing. Or perhaps priorityRush is also a method of OrderLine, that forwards the call to its order. That would only further clutter things up as now OrderLine and Order seem to have a similar API. OrderLine has a priorityRush() method that doesn't belong there, or Order has a skippable() method that doesn't belong there .

It becomes more clear if you write out the API that is needed to create this example:

 
  class Customer
     public Order newOrder()
 
  class Order
    public OrderLine with(int quantity, String code)
    public Order priorityRush()
 
  class OrderLine
    public OrderLine with(int quantity, String code)
    public OrderLine skippable()
    public Order priorityRush()
 

To create such an API only to be able to write more english-like sentences in code is, in my opinion, bad practice.

Only use this when it makes sense. If you like, make an add() method return the added item, so you can write stuff like:

 
  item = table.add(new Item());
  item.setBorder("red");
 

But not for readability purposes.