Subtype Polymorphism – Swapping Implementation at Runtime

How many people doubt the relevance of Inheritance and Polymorphism in Object-Oriented design? Probably very few, most likely because of ignorance or a narrow mindset. But there is one small gotcha here that can’t be easily overlooked. While understanding the logic that pulls on the reins of Inheritance is straightforward, things are more difficult when it comes to digging deep into the nuts and bolts of Polymorphism.

The term Polymorphism is intimidating in its own right, and its academic definition is plagued with several disparate slants which make it even harder to understand what’s actually under its hood. Peripheral concepts such as Parametric Polymorphism and ad-hoc Polymorphism, usually implemented through method overriding/overloading, do have prolific niches in some programming languages, but the last instance should be dropped when it comes to designing extensible systems capable of consuming specific contracts (read abstractions) without having to check if the implementers belong to an expected type.

In short, most of the time any generic reference made to Polymorphism in OOP is implicitly assumed as the ability exposed by a system for defining a set of contracts or interfaces which in turn are honored by different implementations. This kind of “canonical” Polymorphism is commonly known as subtype Polymorphism, as the implementers of the interfaces are considered subtypes of them regardless if there’s an actual hierarchy down the line or not.

As one might expect, understanding the nature of Polymorphism is only half of the learning process; the other half is, of course, demonstrating how to design polymorphic systems that can be accommodated to work in pretty realistic situations, without getting caught in the trap of showcasing just “some nifty didactical code” (in many cases a cheap euphemism for toy code).

In this article I’ll show you how to exploit the virtues that Polymorphism offers through the development of a pluggable cache component. The core functionality can be expanded later to suit your needs through the development of additional cache drivers.

Defining the Component’s Interfaces and Implementations

The menu of available options to choose from when building an extensible caching component is anything but scarce (if you’re skeptical, just peek behind the curtain of some popular frameworks). In this case in particular, though, the component I present here has the nifty ability to swap out different cache drivers at runtime, all without having to amend a single chunk of client code.

So how do we get this going without sweating too much during the development process? Well, the first logical step to take would be …yep, define a segregated cache contract which will be agreed to later by distinct implementations, hence taking advantage of the benefits of Polymorphism.

At its most basic level, the aforementioned contract looks like this:

<?php
namespace LibraryCache;

interface CacheInterface
{
    public function set($id, $data);
    public function get($id);
    public function delete($id);
    public function exists($id);
}

The CacheInterface interface is a skeletal contract that abstracts the behavior of a generic caching element. With the interface in place, it’s easy to create a few concrete cache implementations that adheres to the its contract.

Since I want to keep things concise and easy to assimilate, the cache drivers I set up will be just a skinny duet: the first one uses the file system as the underlying backend for caching/fetching data, while the second one employs the APC extension behind the scenes.

Here’s the file-based cache implementation:

<?php
namespace LibraryCache;

class FileCache implements CacheInterface
{
    const DEFAULT_CACHE_DIRECTORY = 'Cache/';
    private $cacheDir;

    public function __construct($cacheDir = self::DEFAULT_CACHE_DIRECTORY) {
        $this->setCacheDir($cacheDir);
    }
    
    public function setCacheDir($cacheDir) {
        if (!is_dir($cacheDir)) {
            if (!mkdir($cacheDir, 0644)) {
                throw InvalidArgumentException('The cache directory is invalid.');
            }
        }
        $this->cacheDir = $cacheDir;
        return $this;
    }
    
    public function set($id, $data) {
        if (!file_put_contents($this->cacheDir . $id, serialize($data), LOCK_EX)) {
            throw new RuntimeException("Unable to cache the data with ID '$id'.");
        }
        return $this;
    }
    
    public function get($id) {
        if (!$data = unserialize(@file_get_contents($this->cacheDir . $id, false))) {
            throw new RuntimeException("Unable to get the data with ID '$id'.");
        }
        return $data;
    }
    
    public function delete($id) {
        if (!@unlink($this->cacheDir . $id)) {
            throw new RuntimeException("Unable to delete the data with ID '$id'.");
        }
        return $this;
    }
    
    public function exists($id) {
        return file_exists($this->cacheDir . $id);
    }
}

The driving logic of the FileCache class should be easy to understand. By far the most relevant thing here is that it exposes a neat polymorphic behavior as it’s a faithful implementer of the earlier CacheInterface.

Although this ability is sweet and charming, on its own it’s not precisely something I’d sing praise about considering that the goal here is to create a cache component capable of switching back-ends at runtime. Let’s make an extra effort on behalf of an instructive cause and bring to life yet another slim implementer of the CacheInterface.

The implementation below adheres to the interface’s contract, but this time by consuming methods bundled with the APC extension:

<?php
namespace LibraryCache;

class ApcCache implements CacheInterface
{
    public function set($id, $data, $lifeTime = 0) {
        if (!apc_store($id, $data, (int) $lifeTime)) {
            throw new RuntimeException("Unable to cache the data with ID '$id'.");
        }
    }
    
    public function get($id) {
        if (!$data = apc_fetch($id)) {
            throw new RuntimeException("Unable to get the data with ID '$id'.");
        } 
        return $data;
    }
    
    public function delete($id) {
        if (!apc_delete($id)) {
            throw new RuntimeException("Unable to delete the data with ID '$id'.");
        }
    }
    
    public function exists($id) {
        return apc_exists($id);
    }
}

The ApcCache class isn’t the flashiest APC wrapper you’ll see in your career, it packages all the functionality required for saving, retrieving, and removing data from memory.

Let’s pat ourselves on the back as we’ve managed to implement a lightweight cache module whose concrete back-ends not only can be swapped out easily at runtime thanks to their polymorphic nature, but adding a few more down the road is ridiculously simple. Just write another implementation that adheres to the CacheInterface.

I should stress however that actual subtype Polymorphism has been achieved by implementing a contract defined through an interface construct, which is a pretty ubiquitous approach. Nothing should stop you, however, from being less orthodox and getting the same results by switching over an interface declared as a set of abstract methods pitched inside an abstract class. If you’re feeling adventurous and want to walk that sideways path, the contract and the corresponding implementations could be refactored as follows:

<?php
namespace LibraryCache;

abstract class AbstractCache
{
    abstract public function set($id, $data);
    abstract public function get($id);
    abstract public function delete($id);
    abstract public function exists($id);
}
<?php
namespace LibraryCache;

class FileCache extends AbstractCache
{
	// the same implementation goes here
}
<?php
namespace LibraryCache;

class ApcCache extends AbstractCache
{
	// the same implementation goes here 
}

From top to bottom, this is true a polymorphic approach that fights head to head with the one discussed before. Personally, and this is nothing but speaking for myself, I prefer to use interface constructs for defining contracts and appeal to abstract classes only when it comes to encapsulating a boilerplate implementation shared by a few subtypes. It’s up to you to pick the methodology that will best fit your needs.

At this point I could drop the curtain write some fancy closing comments, babbling on about our impressive coding skills and bragging about the flexibility of or cache component, but that would be plain a disservice. Polymorphism exposes its most seductive facet when there exists some client code capable of consuming several implementations without checking if they’re types of something as long as they adhere to an expected contract. So, let’s unveil that facet by hooking up the cache component to a basic client view class, something that will permit us do some neat HTML caching without much fuss.

Putting the Cache Drivers to Work

Caching HTML output through our sample cache module is so banal, that I’ll save any verbose explanation for some other time. The whole caching process can be reduced to a naïve view class, similar to this one:

<?php
namespace LibraryView;

interface ViewInterface
{
    public function setTemplate($template);
    public function __set($field, $value);
    public function __get($field);
    public function render();
}
<?php
namespace LibraryView;
use LibraryCacheCacheInterface;

class View implements ViewInterface
{
    const DEFAULT_TEMPLATE = 'default';    
    private $template;
    private $fields = array();
    private $cache;

    public function __construct(CacheInterface $cache, $template = self::DEFAULT_TEMPLATE) {
        $this->cache = $cache;
        $this->setTemplate($template);
    }
    
    public function setTemplate($template) {
        $template = $template . '.php';
        if (!is_file($template) || !is_readable($template)) {
            throw new InvalidArgumentException(
                "The template '$template' is invalid.");   
        }
        $this->template = $template;
        return $this;
    }
    
    public function __set($name, $value) {
        $this->fields[$name] = $value;
        return $this;
    }
    
    public function __get($name) {
        if (!isset($this->fields[$name])) {
            throw new InvalidArgumentException(
                "Unable to get the field '$field'.");
        }
        return $this->fields[$name];
    }
    
    public function render() {
        try {
            if (!$this->cache->exists($this->template)) {
                extract($this->fields);
                ob_start();
                include $this->template;
                $this->cache->set($this->template, ob_get_clean());
            }
            return $this->cache->get($this->template);
        }
        catch (RuntimeException $e) {
            throw new Exception($e->getMessage());
        } 
    }
}

The flashiest kid on the block is the class’ constructor, which consumes an implementer of the earlier CacheInterface, and the render() method. Since the responsibility of this last one is caching the view’s template once it’s been pushed through the output buffer, it’d be pretty nice to exploit this ability and cache an entire HTML document.

Let’s say the view’s default template has the following structure:

<!doctype html>
<html>
 <head>
  <meta charset="utf-8">
  <title>The Default Template</title>
 </head>
 <body>
  <header>
   <h1>You are viewing the default page!</h1>
<?php echo $this->header;?>
  </header>
  <section>
<?php echo $this->body;?>
  </section>
  <footer>
<?php echo $this->footer;?>
  </footer>
 </body>
</html>

Now, let’s have some fun and cache the document by feeding the view with an instance of the ApcCache class:

<?php
use LibraryLoaderAutoloader,
    LibraryCacheFileCache,
    LibraryCacheApcCache,
    LibraryViewView;
        
require_once __DIR__ . '/Library/Loader/Autoloader.php';
$autoloader = new Autoloader;
$autoloader->register();

$view = new View(new ApcCache());

$view->header = 'This is my fancy header section';
$view->body = 'This is my fancy body section';
$view->footer = 'This is my fancy footer section';

echo $view->render();

Pretty nice, right? But hang on just a moment! I got so caught up in the moment that I forgot to mention the above snippet will blow up on any system where the APC extension hasn’t been installed (naughty sysadmins!). Does that mean that the beautifully-crafted cache module isn’t reusable anymore?

Here’s precisely where the file-based driver comes to the rescue, which can be dropped into client code without getting a single compliant from it:

<?php
$view = new View(new FileCache());

The above one-liner explicitly declares that the view will be caching its output using the file system instead of shared memory. This switching of cache back-ends on the fly shows in a nutshell why Polymorphism is so crucial when it comes to designing highly-decoupled modules. It allows us to easily rewire things at runtime without rippling fragility/rigidity-related artifacts to other parts of our system.

Closing Remarks

Crushed under a overwhelming pile of formal definitions that make understanding the concept elusive, Polymorphism is really one of those beautiful things in life which, once you do understand it, makes you wonder how you could have gone on for so long without it.

Polymorphic systems are by nature much more orthogonal, easier to extend, and a lot less vulnerable to infringing central paradigms such as the Open/Closed Principle and the wise “Programming to Interfaces” mantra. Although rather primitive, our cache module is a shining example of these virtues in action.

If you haven’t refactored your applications yet so that they can take advantage of the benefits brought to the table by Polymorphism, you’d better hurry up because you’re missing the jackpot!

Image via Fotolia

Free book: Jump Start HTML5 Basics

Grab a free copy of one our latest ebooks! Packed with hints and tips on HTML5's most powerful new features.

  • Jonathan

    Alejandoro,
    Do you have a download copy of the code with the file names and structures?

    • Alex Gervasio

      Hey Jonathan,
      Thanks for stopping by. Unfortunately, there’s no a downloadable package for the source files. Anyway, I guess it’s pretty easy to create the files in question from scratch using
      the code samples. Thanks for the feedback.

  • Kevin

    Alex, your tutorials are the best on the net hands down. You’ve taught me a lot of what I know. Thanks!

    • Alex Gervasio

      Hi Kevin,
      Glad to know the posts have been instructive so far. Thanks for the positive feedback.

  • Fred

    I love these “back to basics” tutorials.
    View render method has line: extract($this->fields);
    So that in template we could also use
    Great theory explanation too. Thanks Alex

    • Fred

      Looks like the PHP was stripped out. Original line was:
      So that in template we could also use: <?php echo $header;?>

    • Alex Gervasio

      Hey Fred,
      Nice you found the article to be instructive. In fact, I’m a strong advocator of digging as deep as possible into the theoretical foundations of OOP, but all without missing the “pragmatic” facet. Quite possibly, the beauty of the whole learning process is that each OOP concept isn’t tied up to a particular programming language, which naturally gives you the freedom to implement it in the one of your choice.
      Regarding what you point out about the “render()” method, you’re right: it’s possible to either use plain variables imported from the variable table, or directly the fields assigned to the view.
      Thanks for the feedback.

  • Charles

    Hi, I usually read these articles late at night, after a day of work and get utterly confused, the second part of the front controller pattern had my head spinning for ages. This article however explained so clearly about polymorphism, I would go as far to say I actually understand it now, an object that conforms to a contract that performs a task no matter what the underlying code. I had never really understood that, it sounds a lot more complicated than it is, and I actually use it a lot already.

    • Alex Gervasio

      Hey Charles,
      Well, I’m glad to know the article has been clear enough to make vanish in thin air any bullying halo surrounding such a fundamental OOP principle :). And honestly, it’s even more satisfactory to see that you’re already enjoying the benefits brought by Polymorphism in your PHP applications. That fact speaks for itself that we’re effectively walking in the right direction, toward a progressive professionalization of the language. Thank for the feedback.

  • Dileepa

    Dear Alex,
    Thank you for your article. My question is whether it is possible to determine at runtime if APC is enabled or not and decide if ApcCache or FileCache should be used without manually changing that 1 line of code? I have noticed a PHP function called class_exists() and I am not sure if that could be used to determine if APC is enabled or not. Please advise thank you.

    • Alex Gervasio

      Hi Dileepa,
      It’s really easy to check if an extension has been installed or not. Just use the “extension_loaded()” PHP function, (personally I would do the check in the ApcCache class’ constructor) and handle the condition in the way that best fits your needs, most likely by throwing an exception. Thanks for the comments.