PHP Liskov Substitution Principle

This PHP programming tutorial focuses on how to utilize the Liskov Substitution Principle (LSP) to develop better OOP applications.

Being a fundamental pillar of Object Oriented Programming, Inheritance is by far the most overrated method for reusing implementations. This happens because for a logical reason: it’s fairly easy to model real world (or virtual) objects which are interrelated by an “ISA” relationship. Add to this the flexibility that most programming languages provide when it comes to creating hierarchies of classes, and you’ll begin to understand why this occurs.

Unfortunately, the easy-going nature of Inheritance comes with a hidden cost that many times we’re reluctant to accept and pay (like bills and taxes). In many cases, the lack of proper planning and analysis leads to encapsulating common functionality in the wrong abstractions (not to mention the fact that Composition is often seen as something that must be avoided by all means, either due to ignorance or plain laziness).

While this may seem a minor issue that has little or no influence in the development of object-oriented applications, the truth is that dealing with a badly-designed hierarchy of objects can make you pull your hair out. Want a quick, succinct example of this? If you start spawning a bunch of subclasses whose behavior is wildly different from the one present in their base parent (or from the interface that they might implement), sooner or later you’ll end up breaking the functionality of the client code, even in the most forgiving cases.

However, not all is bad with Inheritance. When used properly it can be a great ally. The question that comes to mind is: how can you keep away from building derivatives that behave totally different from the chosen abstraction(s)? Here’s exactly where the Liskov Substitution Principle (LSP) comes into play. Its academic definition states the following:

“What is wanted here is something like the following substitution property: If for each object o1 of type S there is an object o2 of type T such that for all programs P defined in terms of T, the behavior of P is unchanged when o1 is substituted for o2 then S is a subtype of T.”

Well, is it just me, or does that sound pretty intimidating? Let’s try with a more comprehensive definition, this time from Robert “Uncle Bob” Martin: (http://www.objectmentor.com/resources/articles/lsp.pdf):

“Functions that use pointers or references to base classes must be able to use objects of derived classes without knowing it.”

Certainly, that’s way easier to undertand! Even though LSP (http://en.wikipedia.org/wiki/Liskov_substitution_principle) is per se fairly technical – you’ll have to get familiar with concepts like pre/post conditions, invariance, co variance and contra variance (for more information on these topics, be sure to check  Giuseppe Castagna’s insightful paper here [http://c2.com/cgi/wiki?ContraVsCoVariance]) – its formulation is aimed at encouraging the creation of programs where subclasses of a certain type must have at least the same functionality as their parent. And if, for some reason, it’s necessary to override one or more methods implemented by the parent in question (which in the real world happens quite frequently), this must be clearly specified and documented.

To sump up, LSP is part of the SOLID principles (http://en.wikipedia.org/wiki/Solid_%28object-oriented_design%29), and as such, deserves an in-depth look. In keeping with this idea, in this two-part tutorial I’ll be demonstrating (with a real-world example other than the classic rectangle/square dilemma that the article’s title stands for) why you should care about it when developing your own OOP PHP applications, and how it can help you be a better, more conscious developer.

 

{mospagebreak title=Implementing a Composite View Rendering Layer} 

One of the best ways to understand the relevance of the Liskov Substitution Principle is by showcasing a case where its unintentional violation makes an application crash noisily. Recently I went through a situation that made me learn this lesson the hard way. Simply put, all that I needed to do was add a small view rendering layer to a client’s existing framework, which in turn allowed them to create master web page layouts and partials (views placed inside of other views) in a straightforward fashion.

I normally use Zend Framework for my work, but given the simplicity of this particular project I thought a good approach to tackle the problem would be to appeal to the functionality of the Composite View pattern. Given that, I started looking into some libraries written in the past and came up with a simple hierarchy of composite classes, whose abstract parent looked like this (edited for the sake of brevity):    

(App/View/AbstractView.php) <?php namespace AppView; abstract class AbstractView
{
    protected $_values = array();
    protected $_template;

    /**
     * Constructor
     */
    public function  __construct($template = null)
    {
        if ($template !== null) {
            $this->setTemplate($template);
        }
    }     /**
     * Set the view template
     */
    public function setTemplate($template)
    {
        $template = 'templates' . DIRECTORY_SEPARATOR . $template;
        if (!file_exists($template) || !is_readable($template)) {
            throw new InvalidArgumentException('The specified template is invalid.');
        }
        $this->_template = $template;
    }     /**
     * Get the view template
     */
    public function getTemplate()
    {
        return $this->_template;
    }     /**
     * Assign a value to the specified field of the view via the corresponding mutator (if it exists);
     * otherwise, assign the value directly to the '$_values' protected array
     */
    public function __set($name, $value)
    {  
        $mutator = 'set' . ucfirst(strtolower($name));
        if (method_exists($this, $mutator) && is_callable(array($this, $mutator))) {
            $this->$mutator($value);
        }
        else {
            $this->_values[$name] = $value;
        }
    }     /**
     * Get the value assigned to the specified field of the view via the corresponding getter (if it exists);
     * otherwise, get the value directly from the '$_values' protected array
     */
    public function __get($name)
    {
        $accessor = 'get' . ucfirst(strtolower($name));
        if (method_exists($this, $accessor) && is_callable(array($this, $accessor))) {
            return $this->$accessor;
        }
        if (isset($this->_values[$name])) {
            return $this->_values[$name];
        }
        throw new InvalidArgumentException('The field ' . $name . ' has not been set for this view yet.');
    }     /**
     * Check if the specified field has been assigned to the view
     */
    public function __isset($name)
    {
        return isset($this->_values[$name]);
    }

    /**
     * Unset the specified field from the view
     */
    public function __unset($name)
    {
        if (isset($this->_values[$name])) {
            unset($this->_values[$name]);
            return true;
        }
        return false;
    }     /**
     * Render the template
     */
    protected function _doRender()
    {
        if ($this->_template !== null) {
            extract($this->_values);
            ob_start();
            include $this->_template;
            return ob_get_clean();
        }
        return '';
    }     /**
     * Get an associative array with the values assigned to the fields of the view
     */
    public function toArray()
    {
        return $this->_values;
    }     abstract public function addView(AbstractView $view);     abstract public function addViews(array $views);
   
    abstract public function removeView(AbstractView $view);
   
    abstract public function render();
}

Even though the implementation of this base class seems to be rather complex, its functionality is simply limited to associating a template file (usually an entire web page or a section of it) to a view object, which can be assigned/removed dynamically a bunch of properties, thanks to the magic of the “__set()”, “__isset()”, “__unset()” and “__get()” PHP methods. Finally, the template can be internally rendered via the protected “_doRender()” method, which uses some output buffering to get the job done with minor hassles.

With this abstraction living comfortably on top of the hierarchy, the next step that I needed to take was to spawn a couple of concrete subclasses, capable of dealing with composite views and partials respectively (notice that set of abstract methods declared by the parent for this purpose). Again, I remembered that the task was pretty easy to accomplish and ended up creating a pair of derivatives, where the implementation of the first one was as follows: 

(App/View/CompositeView.php) <?php namespace AppView; class CompositeView extends AbstractView
{
    protected $_views = array();     /**
     * Add a view
     */
    public function addView(AbstractView $view)
    {
        if (!in_array($view, $this->_views, true)) {
            $this->_views[] = $view;
            return true;
        }
        return false;
    }      /**
     * Add multiple views
     */
    public function addViews(array $views)
    {
        foreach ($views as $view) {
            $this->addView($view);
        }
    }     /**
     * Remove a view
     */
    public function removeView(AbstractView $view)
    {
        $this->_views = array_filter($this->_views, function ($v) use ($view) {
            return $v !== $view;
        });
        return true;
    }     /**
     * Render both the injected views and the current one
     */
    public function render()
    {
        $output = '';
        // render the injected views
        if (!empty($this->_views)) {
            foreach ($this->_views as $_view) {
                $output .= $_view->render();
            }
        }
        // render the current view
        $output .= $this->_doRender();
        return $output;
    }
}

At this point, the scenario was looking even better, as I had managed to set up a composite view class capable of rendering itself along with other views attached via the “addView() and “addViews()” methods. To get things up and running though, I needed to derive yet another subclass, tasked with rendering partials. So, I put my hands back on the keyboard and built the following one:

(App/View/PartialView.php) <?php namespace AppView; class PartialView extends AbstractView
{
    /**
     * Add a view (throws an exception)
     */
    public function addView(AbstractView $view)
    {
        throw new InvalidArgumentException('A partial view cannot aggregate another view.');
    }     /**
     * Add multiple views (throws an exception)
     */
    public function addViews(array $views)
    {
        throw new InvalidArgumentException('A partial view cannot aggregate other views.');
    }     /**
     * Remove a view (throws an exception)
     */
    public function removeView(AbstractView $view)
    {
        throw new InvalidArgumentException('A partial view cannot remove another view.');
    }     /**
     * Render the partial view
     */
    public function render()
    {
        return $this->_doRender();
    }
}

      
At first I felt a little uncomfortable making the “addView()”, “addViews()” and “removeView()” methods of the earlier subclass to throw some exceptions, as this was a clear sign that something wasn’t exactly right – but since the derivative was responsible for rendering partials, I quickly changed my mind and forgot about this potential issue.

With this hierarchy of composite view classes ready to go, the last thing that I needed to do was create a few PHP templates, and check if the classes in question were that functional so that they could fit my client’s requirements. Thus, I defined three trivial templates, which looked like this:

(App/Templates/header.php) <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <title>My sample web page</title>
</head>
<body>
<div id="header">
    <h2><?php echo $content;?></h2>
</div>
 
(App/Templates/body.php) <div id="content">
    <h2><?php echo $content;?></h2>
</div>   (App/Templates/footer.php) <div id="footer">
    <h2><?php echo $content;?></h2>
</div>
</body>
</html>

Finally, after doing some unit testing, the composite view layer was ready for some real action! Since I was feeling a bit smug with the neat results achieved so far, I simply built up a script to put the composite classes to work. The script was similar to the one below (I decided to omit the autoloader’s implementation to keep the whole code uncluttered and easier to read):  

<?php use AppViewCompositeView as CompositeView,
    AppViewPartialView as PartialView; // include the autoloader
require_once 'Autoloader.php';
Autoloader::getInstance(); // create a composite view
$masterLayout = new CompositeView; // create some partials
$header = new PartialView('header.php');
$header->content = 'This is the header section'; $body = new PartialView('body.php');
$body->content = 'This is the body section'; $footer = new PartialView('footer.php');
$footer->content ='This is the footer section'; // add the partials to the composite view
$masterLayout->addViews(array(
    $header,
    $body,
    $footer
)); // render the partials in one go
echo $masterLayout->render();

As seen above, my testing script firstly spawned a composite view object, which was fed in turn with three different partials, containing the “header.php”, “body.php” and “footer.php” templates defined before. After running the pertaining script in the server, it nicely rendered the following output:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <title>My sample web page</title>
</head>
<body>
<div id="header">
    <h2>This is the header section</h2>
</div>
<div id="content">
    <h2>This is the body section</h2>
</div>
<div id="footer">
    <h2>This is the footer section</h2>
</div>
</body>
</html>

That worked like a charm. Even when there was still a little voice in my head warning me that the implementation of the earlier “PartialView” class wasn’t entirely correct, in general I was pretty satisfied with the functionality of my composite view layer. Therefore, I contacted the client with the good news, sent him the source files and finally got my payment.

Everything was goin fine until my client called me back a few weeks later telling me that he also needed to implement a small application for building some web page layouts in an automated way, which would use my composite view layer.

He asked me, "Can this be done in a timely manner?" Of course I answered with a resounding: "yes!" Then I launched my code editor and started writing a simple layout builder class. To my surprise, the task would be a pain, due to the wrong hierarchy of classes built in the past.    

{mospagebreak title=Violating the Liskov Substitution Principle}

Breaking up the law: violating the Liskov Substitution Principle

As I was saying before, once I finished speaking with my eager client, I decided to construct a simple class that allowed him to build sets of ready-to-use web page layouts, which he could use in different shell scripts. So, after thinking about it for a while, I came up with the following layout builder:  

(App/Utility/LayoutBuilder.php) <?php namespace AppUtility;
use AppView; class LayoutBuilder
{
    protected $_views = array();
   
    /**
     * Attach a view
     */
    public function attachView($key, ViewAbstractView $view)
    {
        if (isset($key)) {
            $this->_views[$key] = $view;
        }
        else {
            $this->_views[] = $view;
        }
        return true;
    }     /**
     * Attach multiple views
     */
    public function attachViews(array $views)
    {
        foreach ($views as $key => $view) {
            $this->attachView($key, $view);
        }
    }
   
    /**
     * Get the attached views
     */
    public function getViews()
    {
        return $this->_views;
    }
    
    /**
     * Build the layout(s)
     */
    public function build()
    {
        foreach ($this->_views as $_view) {
            // create a predefined layout with the attached views (customizable)
            $_view->addViews(array(
                new ViewPartialView('header.php'),
                new ViewPartialView('body.php'),
                new ViewPartialView('footer.php')
            ));
        }
    }
}

As you can see, the only responsibility of my layout builder was to store view objects in a protected $_views array, which in turn would be used by its “build()” method for creating a predefined layout with a set of templates (in this case, the class used the ones that you saw before, but it could be anything else).  

At this point, I was pretty happy with this simple builder, so I decided to try out its functionality with the following script:

<?php use AppUtilityLayoutBuilder as LayoutBuilder,
    AppViewCompositeView as CompositeView,
    AppViewPartialView as PartialView; // include the autoloader
require_once 'Autoloader.php';
Autoloader::getInstance(); // create an instance of the layout builder
$layoutBuilder = new LayoutBuilder; // add some views to the layout builder
$layoutBuilder->attachViews(array(
    new PartialView,
    new CompositeView
)); // generate the layouts with the attached views
$layoutBuilder->build();

So far, all was going fine. However, that joyful feeling went suddenly away, as soon as I ran the above script. Surprisingly, instead of seeing a pleasant message in my debugger, I was confronted with the following exception:

Fatal error: Uncaught exception ‘InvalidArgumentException’ with message ‘A partial view cannot aggregate other views.’ in /path/to/App.

What went wrong? After researching for a while, I realized that the following line was the troubling one:

// add some views to the layout builder
$layoutBuilder->attachViews(array(
    new PartialView,
    new CompositeView
));

Effectively (and unintentionally), the layout builder was passed a partial view object, which naturally was unable to add another view at runtime. But hold on a second! If the signature of the builder’s “attachView()” method accepts any type of view (be it a composite or a partial) it means that it should be amended to take only composites, or in the worst case, do the proper checking in the implementation.

Unfortunately, that’s nothing but infringing the “Open/Close” principle (http://en.wikipedia.org/wiki/Open/closed_principle). If client code (in this case my trivial layout builder) consumes instances of the base “AbstractView” class without expecting to receive a single exception, and it suddenly gets one from a derivative (a partial view), this is a clear sign that the latter doesn’t conform to the behavior of its parent. Yes, this is exactly what the Liskov Substitution Principle is aimed at avoiding!

In this particular situation the behavior of a partial view is indeed pretty logical (after all it’s a leaf in a composite implementation); the main issue here is that from the very beginning my nice and sweet composite view layer was seated upon a wrong abstraction. Put in a different way: why should I derivate a partial view from a composite parent, if it won’t have at least the same base behavior? Pretty pointless and problematic, indeed.

The bright side of this story is that I was finally able to define an appropriate hierarchy of composite view classes without violating the LSP, and also got the layout builder to consume only the type of objects that it really needed. Obviously, the solution required to do some refactoring and even define a few additional interfaces, but in the end my client (and myself) were happy with the results.

Of course, if you’re anything like me, at this moment you’ll be wondering what’s the driving logic that stands behind this solution, right? Fear not, as in the final installment of this tutorial I’ll be showing you the highly-improved, refactored version of my composite view rendering layer.

Closing Thoughts

In this first part of this tutorial, I provided you with an introduction to what the Liskov Substitution Principle is, its fundamentals and how its infringement can cause more headaches than one might think. As with other principles of Object Oriented Design, the application of LSP is something that requires a careful balance between the theory behind it and the pragmatism of most programming languages (and of reality itself). But, you should always keep it in mind when designing your own hierarchies of classes.

With that being said, make sure to stop by the final tutorial, as you’ll see how I managed to implement a LSP-compliant solution for my composite view module.

Don’t miss the last part! 

[gp-comments width="770" linklove="off" ]

chat sex hikayeleri Ensest hikaye