Dealing with Dependencies

Share this article

Compositional programming style

In the object oriented programming style, it’s preferable to split functionality out to multiple objects, that can work together to solve a single task. Taken to the extreme, this results in more, but smaller, classes and generally relies less on inheritance and more on composition. In lack of better words, I’ll call this compositional programming style. It’s a style which is usually more prevalent with experienced programmers.

For someone coming from an imperative style of programming, this style can appear abstract and confusing, but the benefits are in the flexibility of the code. If different objects are related through composition, parts can be replaced, without changing the code. This makes it easier to reuse components, and to hook into the code, by providing a wrapper here or there. This is especially useful during testing, since it becomes easier to mock out external dependencies (Such as a database or an smtp server).

There is, however, a dark side to composition — dependencies.

So what is a dependency?

For the sake of this post, I’ll use a rather naïve example. Assume, that we were building an addressbook application. This would feature an entity of type Person. In our code, we might have a class for accessing an underlying table in the database. Initially, it might look like this:


class PersonGateway {
  protected $db;
  function __construct() {
    $this->db = new PDO("mysql:host=localhost;dbname=addressbook", "root", "secret");
  }
  function getPerson($id) {
    $stmt = $this->db->prepare("select * from persons where id = :id");
    $stmt->execute(array(':id' => $id));
    return $stmt->fetch();
  }
}

However, we also need an entity of type Address, and since this also needs access to the database, we’ll now end up with two connections, if we implement it in the same way. What we need, is a single database object, which our two gateway classes can share. This kind of object is called a dependency[1] — The gateway classes are called dependants.

Notes:
[1] It was pointed out to me in the comments, that I’m using dependency in a slightly different meaning here, than it is used in UML. The kind of dependency, I’m talking about, is working on an object instance level — not the class level. See honeymonster’s nice explanation.

Would you pass me that dependency, please?

There are roughly speaking just two ways, that a dependency can be satisfied. Either the dependency is obtained through a global symbol[2] or it is passed in from the outside. Global symbols are the least abstract method and therefore often appeals to lesser experienced programmers. However, their concreteness also makes them very inflexible. Global symbols are generally hard or impossible to change at runtime, so a lot of the benefits of aggregation is lost. Further, globals hide side-effects, making them ideal vessels for introducing hard-to-spot bugs into your application. For these reasons, we’ll pass in the dependencies, making our gateway look like this:


class PersonGateway {
  protected $db;
  function __construct($db) {
    $this->db = $db;
  }
  ...
}

Notes:
[2] To global symbols, I count global variables, constants or any kind of static member (Including the infamous Singleton)

Leaky dependencies

As a general rule, dependency pasing is a good tool. In our above example, we could easily replace the database with a mock, if we wanted to test it. It does come at a management cost however. Presumably we would now go and write some application, which relies on our gateway. Some place down the road, we figure that we need to add an identitymap to the gateway. As the compositional style prescribes, we provide these as external dependencies, but to do so, we change the constructor of the gateway.

We now have to go back and edit all places, where the gateway is instantiated and provide the new dependencies. This is not good — The user shouldn’t be bothered with interface changes, just because we are redefining the internal behaviour of our component. And there’s another problem too. The user now has to be aware of cryptic sounding classes, which aren’t really any concern of his. We have a lack of encapsulation.

Writing a container

There are different ways of solving this problem, without resolving to global symbols, but what they all have in common, is that they hide the constructor away in a factory. In doing so, the dependencies can be resolved in one place, hidden away from the user, who couldn’t care less about the ugly details. For our example, the container might look like this:


class Container {
  function new_PDO() {
    return new PDO("mysql:host=localhost;dbname=addressbook", "root", "secret");
  }
  function new_PersonGateway() {
    return new PersonGateway($this->new_PDO(), $this->new_IdentityMap());
  }
  function new_AddressGateway() {
    return new AddressGateway($this->new_PDO(), $this->new_IdentityMap());
  }
}

But wait a second. This container is creating two database connections, when we already decided that we’d want just one. We do however want two distinct instances of identymap, since they should track different types.

So as it turns out, classes can be divided into two kinds, based on their uniqueness in the application. There are shared objects, such as the database connection and there are transient objects, such as the identitymap. And further, the gateways them selves are also shared — We wouldn’t want multiple copies of these.

To address this, we’ll split our container up into two different parts: A container and a factory. The container holds the shared instances and provides the public facing interface, while the factory contains methods for creating instances. A simple implementation might look this way:


class Container {
  protected $factory;
  protected $instances = array();
  function __construct($factory) {
    $this->factory = $factory;
  }
  function get($classname) {
    $classname = strtolower($classname);
    if (!isset($this->instances[$classname]) {
      $this->instances[$classname] = $this->create($classname);
    }
    return $this->instances[$classname];
  }
  function create($classname) {
    return $this->factory->{'new_'.$classname}($this);
  }
}
class Factory {
  function new_PDO($container) {
    return new PDO("mysql:host=localhost;dbname=addressbook", "root", "secret");
  }
  function new_PersonGateway($container) {
    return new PersonGateway($container->get('PDO'), $container->create('IdentityMap'));
  }
  function new_AddressGateway($container) {
    return new AddressGateway($container->get('PDO'), $container->create('IdentityMap'));
  }
}

Putting the container to use

There are room for improvements on this, but we already have a very solid container to use. One big advantage of separating the factory from the container, is that it’s trivial to stub out selected classes, during testing. Say I wanted to write a unittest for the PersonGateway class and for this, I wanted to replace the database with a stub. Here’s how:


class TestFactory extends Factory {
  function new_PDO($container) {
    return new MockPdo();
  }
}
class TestOfPersonGateway extends UnitTestCase {
  function setUp() {
    $this->container = new Container(new TestFactory());
  }
  function test_finder_selects_from_database() {
    $statement = new MockPdoStatement();
    $statement->expectOnce("execute");
    $this->container->get('PDO')->expectOnce("prepare");
    $this->container->get('PDO')->setReturnValue("prepare", $statement);
    $gateway = $this->container->get('PersonGateway');
    $gateway->getPerson(42);
  }
}

Since the test case uses a subclass of the real factory, it doesn’t need to be updated each time I decide to change the dependencies of my class. There is no hidden side effects either; The container contains any shared instances, so for each test I get a completely fresh setup.

But that’s not all — Order today, and get a namespace tossed in for free!

PHP 5.3 is scheduled to be out soon and one of the most anticipated improvements is the introduction of namespaces. With just a single global namespace, PHP classes have a tendency to get really long-winded, to avoid nameclashes. Namespaces allows us to use shorter names to address classes, while still avoiding nameclashes.

This feature has been so requested for, that it has been pushed back to PHP 5.3, even though it was originally planned to bew introduced with PHP 6. We don’t need to wait for PHP 5.3 though. With our container above, it’s easy to write a wrapper, which provides a namespace for us:


class Namespace {
  protected $prefix;
  protected $container;
  function __construct($prefix, $container) {
    $this->prefix = rtrim($prefix, '_') . '_';
    $this->container = $container;
  }
  function get($classname) {
    return $this->container->get($this->prefix . $classname);
  }
  function create($classname) {
    return $this->container->create($this->prefix . $classname);
  }
}

Assuming we’ve written a factory already, we can now use the Zend framework, without the extremely long clasnames:


$container = new Namespace("Zend_Cache_Backend", $container);
$memcached = $container->get("Memcached");

Of course real, language supported namespaces also buffer away other symbols than just class names, but in object oriented code, those will be few anyway. The exception is the legacy procedural libraries of PHP, which can’t be avoided. In a recent post, Mike Naberezny described a way to deal with these, in a way quite similar to our container.

This post has been translated into German.

Troels Knak-NielsenTroels Knak-Nielsen
View Author

Troels has been crafting web applications, as a freelancer and while employed by companies of various sizes, since around the time of the IT-bubble burst. Nowadays, he's working on backend systems for a Danish ISP. In his spare time, he develops and maintains Konstrukt, a web application framework for PHP, and is the organizer of a monthly PHP-meetup in Copenhagen.

Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week