Decoupling Interfaces from Implementation – Using Separated Interfaces

Tweet

If you’ve ever faced the same dilemma, surely you’ll grasp the sense of the following description: Cohesion and Decoupling, two seemingly naïve yet fundamental OOP cornerstones responsible for the incessant drumming that crushes the minds of most software developers, often crossing the boundary of what’s a tangible goal into utopia, away from the pragmatism and reality.

I don’t want to sound excessively ominous, but it’s fair to admit that designing cohesive, loosely-coupled systems is anything but a simple experience. In most cases, achieving such pristine features requires a lot of planning at the initial stages and going through the proper refactoring cycles later on as the system evolve and grow over time. Despite this, the OOP paradigm per se provides a set of well-trusted methodologies and principles right out of the box that together facilitate the implementation of cohesive, highly-decoupled components, even if they do have to be eventually refactored during their respective life cycles.

Consider, for instance, the use of a few segregated interfaces along with namespaced classes. When put to work in sync, they help wire up together components that are semantically related to each other, therefore increasing the overall level of cohesion exposed by a system. On the flip side, the definition of the interfaces themselves, either in the form of interface constructs or virtual/abstract classes, makes concrete implementations dependent upon abstractions, hence promoting the decoupling of components in such a way that they can be “rewired” differently at runtime, usually by means of Dependency Injection. When analyzed from a bird’s eye view, it becomes clear that the combined forces of good OOP practices and the proper mixture of design patterns are in most cases an effective solution that allows us to achieve a decent level of Cohesion and Decoupling.

Still, issues may arise when it’s necessary to “redefine” explicitly the way that one component, or even an entire layer, in a multi-tiered design must interplay with others. In a traditional system design, the dependencies between its decoupled components is defined through the respective interfaces, which are usually placed in the same component housing the concrete implementations. There might be a few particular situations where the dependencies must be reversed, in response to specific requirements. In such a case, the inversion in question can be easily accomplished by dropping the interface into one component and the corresponding implementations into a different one.

Considering that the concept may sound rather tangled and twisted at first, this shifting of protocols between components lives and breaths under the umbrella of a basic design pattern known as Separated Interface, which at least to some extent, goes hand in hand with the commandments of the Dependency Inversion Principle. Moreover, because of the pattern’s easy-going nature, it’s feasible to implement it in PHP without much fuss, so in this article I’ll show you how to exploit the benefits that separated interfaces bring to the table in a fairly approachable fashion.

Trespassing in Forbidden Terrain – Calling Data Mapper Logic from a Domain Model

While the logic behind separated interfaces is pretty straightforward to digest, in all cases there must always be a compelling reason that justifies their implementation since the process of inverting the dependencies between components in an application is a far cry from being an arbitrary, whimsical decision.

This raises an interesting question as well: why should one invert component dependencies if, after all, in their current state they work just fine? There may be some situations when the inversion can be used as a mechanism for increasing the level of decoupling between the involved components. In simple terms, by putting an interface in one module and the implementation somewhere else means to define explicitly the protocol that should be used in the outside world for accessing the module in question.

A good way to see the effects of separated interfaces in action is with some testable examples. So, let’s suppose that we have a simple Domain Model which needs to access some logic in the mapping layer. In a classic implementation this would pretty much be viewed as a cardinal sin since a Domain Model by definition must be unaware of any form of persistence down the line. When using a separated interface, though, we can achieve this and still keep the model completely agnostic.

To better understand the inner workings of this process, let’s begin implementing a basic model. Here’s how its first block looks:

<?php
namespace Model;

class AbstractEntity
{
    protected $id;
    
    //set values for protected/private fields via the corresponding mutators
    public function __set($field, $value) {
        $this->checkField($field);
        $mutator = "set" . ucfirst(strtolower($field));
        method_exists($this, $mutator) && 
            is_callable(array($this, $mutator)) 
            ? $this->$mutator($value)
            : $this->$field = $value;
        return $this;                 
    }
      
    // get values from protected/private fields via the corresponding accessors 
    public function __get($field) {
        $this->checkField($field);
        $accessor = "get" . ucfirst(strtolower($field));
        return method_exists($this, $accessor) && 
            is_callable(array($this, $accessor))
            ? $this->$accessor() 
            : $this->$field;
    }
    
    protected function checkField($field) {
        if (!property_exists($this, $field)) {
            throw new InvalidArgumentException(
                "Setting or getting the field '$field'j is not valid for this entity.");
        }
    }
    
    // sanitize strings assigned to the fields of the entity
    protected function sanitizeString($value, $min = 2, $max = null) {
        if (!is_string($value) 
            || strlen($value) < (integer) $min 
            || ($max) ? strlen($value) > (integer) $max : false) {
            throw new InvalidArgumentException(
                "The value of the field accessed must be a valid string.");
        }
        return htmlspecialchars(trim($value), ENT_QUOTES);
    }
    
    // handle IDs
    public function setId($id)
    {
        if ($this->id !== null) {
            throw new BadMethodCallException(
                "The ID for this entity has been set already.");
        }
        if (!is_int($id) || $id < 1) {
            throw new InvalidArgumentException(
              "The ID of this entity is invalid.");
        }
        $this->id = $id;
        return $this;
    }
    
    public function getId() {
        return $this->id;
    }
}

Considering that the goal here is to implement a rather prototypical model whose core functionality can be easily extended at will, the above AbstractEntity class behaves pretty much like a Layer Supertype which encapsulates logic common to all the domain subclasses that might be incidentally derived further down the road. This includes performing a few basic tasks, such as handling IDs, sanitizing strings, and mapping calls to mutators/accessors through __set() and __get().

With the base class in place, now it’s fairly simple to create additional subclasses that define the data and behavior of concrete domain objects. How about setting a few charged with modeling the classic blog posts/comments relationship?

<?php
namespace Model;

interface PostInterface
{
     public function setId($id);
     public function getId();
     
     public function setTitle($title);
     public function getTitle();
     
     public function setContent($content);
     public function getContent();
     
     public function getComments();
}
<?php
namespace Model;

interface CommentFinderInterface {
    public function findById($id);
    public function findAll(array $conditions = array());
}
<?php
namespace Model;

class Post extends AbstractEntity implements PostInterface
{
    protected $title;
    protected $content;
    protected $comments;
    protected $commentFinder;

    public function __construct($title, $content, CommentFinderInterface $commentFinder)  {
        $this->setTitle($title);
        $this->setContent($content);
        $this->commentFinder = $commentFinder;
    }
    
    public function setTitle($title) {
        $this->title = $this->sanitizeString($title);
        return $this;
    }
    
    public function getTitle() {
        return $this->title;
    }
    
    public function setContent($content) {
        $this->content = $this->sanitizeString($content);
        return $this;
    }
    
    public function getContent() {
        return $this->content;
    }
    
    public function getComments() {
        if ($this->comments === null) {
            $this->comments = $this->commentFinder->findAll(
                array("post_id" => $this->id));
        }
        return $this->comments;
    }
}

While admittedly the logic that drives the Post class is contrived, boiled down to just validating and assigning a few values to the fields of blog post objects, it exposes a detail worth stressing: it gets injected into its constructor an implementation of the previous CommentFinderInterface which is used for pulling in the associated comments for the persistence layer. This shows in a nutshell how to use a separated interface for reversing the dependencies between the model (at least a portion of it) and any other layer which must interact with it. In other words, the model is now a stand-up client module, responsible for defining the abstraction of its own accessing protocol.

This simple change allows us to do all sorts of clever things without feeling a pinch of guilt, including ones that in any other context would be considered blasphemous. For example, we could make the model invoke mapping logic and retrieve the comments from the database while still keeping it unaware of the mapper itself. The model would always see the interface, not the implementer, be it a mapper or anything else.

Of course, before we see how to get the model calling logic in a data mapper, we should create the subclass charged with modeling the aforementioned comments. Here’s the additional derivative, along with the interface that it implements:

<?php
namespace Model;

interface CommentInterface
{
     public function setId($id);
     public function getId();
     
     public function setContent($content);
     public function getContent();
     
     public function setAuthor($author);
     public function getAuthor();
}
<?php
namespace Model;

class Comment extends AbstractEntity implements CommentInterface
{
    protected $content;
    protected $author;

    public function __construct($content, $author) {
        $this->setContent($content);
        $this->setAuthor($author);
    }
    
    public function setContent($content) {
        $this->content = $this->sanitizeString($content);
        return $this;
    }
    
    public function getContent() {
        return $this->content;
    }
    
    public function setAuthor($author) {
        $this->author = $this->sanitizeString($author);
        return $this;
    }
    
    public function getAuthor() {
        return $this->author;
    }
}

There’s no need to peer too deep into the API of the earlier Comment class in order to grasp its underlying logic, as its responsibility is pretty narrow. It just creates comment objects in a valid state, which are hydrated via a couple of scalar fields such as the comment’s content and the corresponding author.

Pulling in Comments from Storage through a Data Mapper

Now it’s time to show off a little as we’ve managed to implement a functional Domain Model which clings off a separated interface and declares explicitly the contract that should be used for pulling in comments from the persistence layer. While this is all well and good, there’s still a missing piece in this puzzle; to get things finally rolling, we need to define at least one single implementer of this interface so that the comments can be injected into the internals of a few post objects.

In this case in particular, the implementer will be a comment mapper as it reflects most of the use cases that might exist in production. Needless to say that it’s possible to switch over any other form of mediator to the persistence layer, such a web service or even an in-memory cache system. To keep the code samples a bit clearer and easier to follow, though, I’ll stick to a basic data mapper implementation.

Sitting on a decent data mapper between the Domain Model and the database and being capable of at least of performing CRUD operations on a few domain objects is quite a burdening task, as the mapper not only must dissect the bones of objects themselves in order to persist them, but in turn it has to invert the process and reconstitute them on request. This duality of roles makes data mappers complex to set up and in most cases delegated, in the name of mental sanity, to the duties of a third-party library.

Even though, there’s no need to be have such a frantic attitude when it comes to implementing the data mappers since all that we need to do now is create a naïve one that implements the previous CommentFinderInterface so that the corresponding comments can be dragged out from the storage and injected into the internals of the associated post objects. The below one does exactly that:

<?php
namespace Mapper;
use LibraryDatabaseDatabaseAdapterInterface,
    ModelCommentFinderInterface,
    ModelNullComment,
    ModelComment;   

class CommentMapper implements CommentFinderInterface
{
    protected $adapter;
    protected $entityTable = "comments";
    
    public function __construct(DatabaseAdapterInterface $adapter) {
        $this->adapter = $adapter;
    }
    
    public function findById($id) {
        $this->adapter->select($this->entityTable, 
            array("id" => $id));
        if (!$row = $this->adapter->fetch()) {
            return null;    
        }
        return $this->loadComment($row);
    }
    
    public function findAll(array $conditions = array()) {
        $this->adapter->select($this->entityTable, $conditions);
        $rows = $this->adapter->fetchAll();
        return $this->loadComments($rows);
    }
    
    protected function loadComment(array $row) {
        return new Comment($row["content"], $row["author"]);
    }
    
    protected function loadComments(array $rows) {
        $comments = array();
        foreach ($rows as $row) {
            $comments[] = $this->loadComment($row);
        }
        return $comments;
    }
}

For the sake of brevity, I decided to keep the implementation of CommentMapper a simple wrapper around the findById() and findAll() methods. However, if you feel adventurous and want to add some extra methods that allow it to insert, update, and delete comments from the associated table, go ahead and have some fun leveraging your remarkable coding skills.

Naturally, the mapper’s most appealing facet is its expressive, not to say explicit, dependency toward the protocol declared by the model when it comes to retrieving comments from the storage. The actual beauty of this schema is because of the fact that although the dependency is prescriptive, it relies on the abstraction of an interface. This means that neither the model is aware of the mapper nor the mapper has an overall vision of the model. That’s pretty motivational considering that the level of decoupling between the two components have been nicely enhanced by using just a simple abstraction.

Of course, all this talk might sound like just a lot of babbling if I didn’t back it up with a concrete example.

<?php
use LibraryLoaderAutoloader,
    LibraryDatabasePdoAdapter,
    MapperCommentMapper,
    ModelPost,
    ModelComment;
    
require_once __DIR__ . "/Library/Loader/Autoloader.php";
$autoloader = new Autoloader;
$autoloader->register();

$adapter = new PdoAdapter("mysql:dbname=test", "fancyusername",
    "hardtoguesspassword");

$commentMapper = new CommentMapper($adapter);

$post = new Post("A naive sample post", 
    "This is the content of the sample post", 
    $commentMapper);
$post->id = 1;

echo $post->title . " " . $post->content . "<br>";

foreach ($post->comments as $comment) {
    echo $comment->content . " " . $comment->author . "<br>";
}

Is it just me or does passing along the data mapper into a post object look like something that would make me cringe? There’s no reason to panic; both elements have been properly shielded from each other through the contract of a separated interface. Furthermore, since the mapper is merely an element taking advantage of Polymorphism, it’d be really easy to swap out other implementations of the CommentFinderInterface.

In either case, the example should be illustrative enough for understanding what’s behind the rather bullying fences of separated interfaces, and how its implementation in a few specific use cases can be pretty useful when it comes to reversing the dependencies between one or more components while keeping a neat level of decoupling throughout the whole system.

Closing Remarks

If you’re like me, probably the first time you heard something about separated interfaces you thought about them pretty much like another twisted, hard-to-understand pattern, with little or no real application in the real world. Despite such a knee-jerk reaction, the logic that drives separated interfaces is a lot easier to digest than one might think. Plus, the slew of benefits that separated interfaces bring to the table are indeed plethoric as they allow you to set up in a straightforward fashion loosely-coupled client modules which define the contracts that should be used by other packages.

As with the overwhelming list of design patterns that exist out there, having a blind worshiping attitude about separated interfaces just doesn’t make much sense, hence they should be used with due caution and only if the situation warrants reversing the dependencies between application components. Appeal to your common sense, don’t be whimsy, and use them when you actually think they’re going to have a positive impact in your design.

Image via kuppa / Shutterstock

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.

  • Luis Montealegre

    Hola Alejandro, I really enjoyed your post. I’m curious about the implementation of Model/NullComment in CommentMapper, it’s in the use statement, but I cannot find it in the class. Did you forget to use it?

    • Alex Gervasio

      Hola Luis,
      Glad you enjoyed the post. In fact, the comment mapper’s original implementation did include a null comment entity, but to keep the whole reading a little bit more concise and straight to the point, I agreed with our wise editor to strip it out, and admittedly it was a clever decision.
      In short, the null comment was a typical implementation of the Null Object pattern http://en.wikipedia.org/wiki/Null_Object_pattern, which is a tiny gem that exploits to the fullest the benefits of Polymorphism, by constructing objects that conform to a predefined contract, but don’t house concrete implementations (even though it’s perfectly valid to encapsulate default behavior in null objects also). This not only avoids returning nulls from methods (a pretty clunky practice, mea culpa), but helps to take pressure off client code, as it doesn’t have get into ugly checks when a method doesn’t return a valid domain object.
      I hope that helps. Thanks!

  • Andrei

    Nice article. Where I can find the sources for examples from above. I mean: LibraryLoaderAutoloader, LibraryDatabasePdoAdapter, etc.
    Thanks,

  • Mathieu

    hello,

    nice article, however, I would have prefer AbstractEntity being seperated into a interface EntityInterface and a trait EntityTrait for exemple, that way you can reuse a class from another project / a library by just extending it to implement EntityInterface (same goes for Post)

    for exemple you would have:
    class Post extends SomeOtherPost implements EntityInterface, PostInterface {
    use EntityTrait;
    /** your Post method for this project 8overloading or not method from SomeOtherPost and PostTrait **/
    }

    what do you thimk?

    • Alex Gervasio

      Hi Mathieu,
      Well, it depends on each context in particular. If your entities share a common contract, then defining a unified EntityInterface interface makes perfect sense. If they behave radically different from each other, the creating separated interfaces should be the way to go. Regarding where to drop shared implementation, abstract classes or traits are both valid options, but I would definitively stay away from creating more than one-level deep hierarchies, you know, a post that extends another post seems to be pretty clumsy and error prone, specially when it comes to retaining basetype/subtype substitutability.
      Thanks for the feedback.

  • Goran

    Thank you Alejandro, it’s always nice to see an article from you:)

    If modeled according to DDD, there should be a Post aggregate which includes Post and Comment entities. Clearly in this case, an aggregate root should be the Post entity. But definition of aggregate says there is only one repository per aggregate – repository which operates only with root entity, not other entities. Your example looks like a violation of this rule because it involves two repositories in same aggregate. Maybe we should “hide” this kind of “auxilary” repository from our public api? Clearly, it’s usage makes sense only inside Post entity?

    Regarding implementation, do you have an idea how to inject Comment repository inside Post entity using Doctrine 2 ORM? For example, if I call findAll() via Post repository I will get a collection of Post entities. Entities are constructed by Doctrine, so I can’t use constructor injection. Also, I could iterate over this collection and call something like setCommentRepository() on every entity (inside my custom findAll method) but this would create a performance issue because entities would not be lazy loaded any more.

    • Alex Gervasio

      Hi Goran,
      Glad you found the post to be useful. With reference to your first question, keep in mind the article just showcases an implementation of a comment data mapper, which is in turn invoked by the domain model via a separated interface without breaching the model’s persistence agnosticism. A data mapper isn’t a repository at all. Both are entirely different patterns. Even so, if you’re willing to implement a post repository, one pretty pragmatic way to do so would be by designing it as a wrapper that injects a post and a comment mappers and consume them internally for fetching posts, and optionally for lazy-loading the related comments from the DAL.
      Regarding the second question, I would suggest not messing unnecessarily things up and just use Doctrine’s proxies. Doctrine uses proxies with different aims, but primarily it exploits their functionality for lazy-loading data from the persistence in a fairly straightforward fashion. Make sure to check the official docs here for more info:
      http://docs.doctrine-project.org/projects/doctrine-orm/en/2.0.x/reference/configuration.html
      Thanks for the comments.