<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Dave Gardner - PHP Developer &#187; Architecture</title>
	<atom:link href="http://www.davegardner.me.uk/blog/category/architecture/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.davegardner.me.uk/blog</link>
	<description>Just behind the bleeding edge of PHP.</description>
	<lastBuildDate>Fri, 02 Jul 2010 08:25:35 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>PHP and Cassandra</title>
		<link>http://www.davegardner.me.uk/blog/2010/07/02/php-and-cassandra/</link>
		<comments>http://www.davegardner.me.uk/blog/2010/07/02/php-and-cassandra/#comments</comments>
		<pubDate>Fri, 02 Jul 2010 08:25:35 +0000</pubDate>
		<dc:creator>Dave</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[cassandra]]></category>
		<category><![CDATA[nosql]]></category>
		<category><![CDATA[phplondon]]></category>

		<guid isPermaLink="false">http://www.davegardner.me.uk/blog/?p=105</guid>
		<description><![CDATA[Yesterday (1st July) I presented for the first time at the PHP London user group. It was a gentle introduction; a five minute &#8220;lightening&#8221; talk slot. I spoke about Cassandra, giving a short introduction to using it with PHP.

To summarise my main points from the talk (perhaps something I should have done in the talk!)

Cassandra [...]]]></description>
			<content:encoded><![CDATA[<p>Yesterday (1st July) I presented for the first time at the <a href="http://www.phplondon.org/" target="_blank">PHP London user group</a>. It was a gentle introduction; a five minute &#8220;lightening&#8221; talk slot. I spoke about <a href="http://cassandra.apache.org/" target="_blank">Cassandra</a>, giving a short introduction to using it with PHP.</p>
<div id="__ss_4664596" style="margin: 20px 0pt; width: 425px;"><object id="__sse4664596" classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="425" height="355" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="allowFullScreen" value="true" /><param name="allowScriptAccess" value="always" /><param name="src" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=cassandphp-phplondon-100702015458-phpapp02&amp;stripped_title=php-and-cassandra" /><param name="name" value="__sse4664596" /><param name="allowfullscreen" value="true" /><embed id="__sse4664596" type="application/x-shockwave-flash" width="425" height="355" src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=cassandphp-phplondon-100702015458-phpapp02&amp;stripped_title=php-and-cassandra" name="__sse4664596" allowscriptaccess="always" allowfullscreen="true"></embed></object></div>
<p>To summarise my main points from the talk (perhaps something I should have done <em>in</em> the talk!)</p>
<ul>
<li>Cassandra is a &#8220;highly scalable second-generation distributed database&#8221;</li>
<li>It can be considered a schema-less database insofar that each row can have different columns</li>
<li>Cassandra is designed to be both fault tolerant and horizontally scalable &#8211; both read and write throughput go up linearly as more boxes are added to the cluster</li>
<li>I think the best way of accessing Cassandra from PHP is directly via the <a href="http://wiki.apache.org/cassandra/API" target="_blank">Thrift API</a>. This allows a beginner to learn about the core functionality of Cassandra including its limitations</li>
<li>Cassandra has Hadoop support which means that Hadoop Map Reduce jobs (a scalable, distributed mechanism for processing data) can read and write to Cassandra*</li>
<li>Cassandra does not have any query language (as opposed to MySQL or <a href="http://www.mongodb.org/" target="_blank">MongoDB</a> which both allow you to query data in different ways)</li>
<li>When designing your data model, I think its easiest to try to forget about SQL and concentrate on how Cassandra works (don&#8217;t design a relational schema and then &#8220;port&#8221; it over)</li>
</ul>
<p>* As of version 0.7!</p>
<p>Overall, I think Cassandra is a very useful tool. Whether it fits your use case or not is another matter!</p>
<p>If you&#8217;re interested in learning more about using Cassandra in a PHP project, I recommend the following starting points:</p>
<ol>
<li>Using Cassandra with PHP<br />
<a href="https://wiki.fourkitchens.com/display/PF/Using+Cassandra+with+PHP" target="_blank">https://wiki.fourkitchens.com/display/PF/Using+Cassandra+with+PHP</a></li>
<li>WTF is a SuperColumn? An Intro to the Cassandra Data Model<br />
<a href="http://arin.me/blog/wtf-is-a-supercolumn-cassandra-data-model" target="_blank">http://arin.me/blog/wtf-is-a-supercolumn-cassandra-data-model</a></li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://www.davegardner.me.uk/blog/2010/07/02/php-and-cassandra/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Caching dependency-injected objects</title>
		<link>http://www.davegardner.me.uk/blog/2010/03/22/caching-dependency-injected-objects-with-php/</link>
		<comments>http://www.davegardner.me.uk/blog/2010/03/22/caching-dependency-injected-objects-with-php/#comments</comments>
		<pubDate>Mon, 22 Mar 2010 09:38:49 +0000</pubDate>
		<dc:creator>Dave</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[caching]]></category>
		<category><![CDATA[dependencyinjection]]></category>
		<category><![CDATA[di]]></category>
		<category><![CDATA[memcache]]></category>
		<category><![CDATA[sleep]]></category>
		<category><![CDATA[wakeup]]></category>

		<guid isPermaLink="false">http://www.davegardner.me.uk/blog/?p=89</guid>
		<description><![CDATA[This blog posts talks about cacheing and retrieving objects in PHP, for example by using Memcache, where the objects themselves have a number of dependencies. It includes using the PHP magic methods __sleep and __wakeup to manage serialisation. It also discusses mechanisms for reinjecting dependencies on wakeup, including a mechanism that keeps the Inversion of Control (IoC) principle central to most DI "containers".]]></description>
			<content:encoded><![CDATA[<p>This blog posts talks about caching and retrieving objects in PHP (eg: via <a href="http://php.net/manual/en/book.memcache.php" target="_blank">Memcache</a>) where the objects themselves have a number of <strong>injected dependencies</strong>. It includes using the PHP magic methods __sleep and __wakeup to manage <a href="http://uk.php.net/manual/en/function.serialize.php" target="_blank">serialisation</a>. It also discusses mechanisms for re-injecting dependencies on wakeup via a method that maintains <a href="http://en.wikipedia.org/wiki/Inversion_of_control" target="_blank">Inversion of Control</a> (IoC).</p>
<p>This post covers:</p>
<ul>
<li><a href="#sample-system">A sample OOP system that we will discuss</a></li>
<li><a href="#di">The basics of Dependency Injection</a></li>
<li><a href="#putting-objects-to-sleep">Putting objects to sleep</a></li>
<li><a href="#waking-objects-up">Waking objects up</a></li>
</ul>
<h3><a name="sample-system">Sample system</a></h3>
<p>To illustrate the idea, I&#8217;ll use a simple domain model where we have a <strong>userList</strong> object (iterator) containing a number of <strong>user</strong> objects. Each user has an injected <strong>userDao</strong> dependency which is used for lazy-loading <strong>usageHistory</strong>, on request.</p>
<pre class="code">class userList
{
    public function current() { }

    public function key() { }

    public function next() { }

    public function rewind() { }

    public function valid() { }

    public function count() { }
}

class user
{
    private $usageHistory;

    public function __construct($dao, $userDataRow)
    {
        $this-&gt;dao = $dao;
        $this-&gt;usageHistory = NULL;
    }

    public function getUsageHistory()
    {
        if ($this-&gt;usageHistory === NULL)
        {
            $this-&gt;usageHistory = $this-&gt;dao-&gt;lazyLoadHistory($this);
        }
        return $this-&gt;usageHistory;
    }
}

class userDao
{
    public function __construct($database, $cache, $logger)

    public function getList() { }

    public function lazyLoadHistory() { }
}

class usageHistory
{
}</pre>
<h3><a name="di">Dependency Injection</a></h3>
<p>A sample invocation of this simple system might be to ask the DAO for a user list object. To create a DAO object we will almost certainly need to pass in a bunch of dependencies such as database services, caching services and logging services.</p>
<p>I&#8217;m using a DI container to create objects. To get a really quick idea of what these are about you can imagine doing this:</p>
<pre class="code">$diContainer = new diContainer();
$userDao = $diContainer-&gt;getInstance('userDao');</pre>
<p>Instead of this:</p>
<pre class="code">$configuration = new systemConfig();

$database = new mysqlDatabaseConnection($configuration);
$cache = new memcacheConnection($configuration);
$logger = new firebugLogger();

$userDao = new userDao($database, $cache, $logger);
$userList = $userDao-&gt;getList();</pre>
<p>The key idea is that the DI container will build the object graph for you. For each dependency needed it will go away and fetch that, building any other dependencies of those objects and so on recursively up the tree.</p>
<p>I&#8217;m using an annotation system to power <a href="http://www.davegardner.me.uk/blog/2009/11/23/php-dependency-strategies-dependency-injection-and-service-locator/" target="_blank">my own DI container</a>; making the whole process simple and configuration-light.</p>
<h3><a name="putting-objects-to-sleep">Putting objects to sleep</a></h3>
<p>Caching is a very handy tool to improve the performance of applications. Storing objects in a cache (for example Memcache) prevents us having to go to database each time. Memcache is a very simple system; a key-value store. You give it some data (less than 1MB) and it stores it for you until you ask for it again. Storing objects is slightly more complex than simple strings; with objects you need to <strong>serialise</strong> them. Memcache actually does this for you (you don&#8217;t need to call serialize() first).</p>
<p>However caching objects can be problematic. Whenever you start to really use the power of OOP you inevitably end up with complex object graphs. Our <strong>user</strong> object, for example, <em>contains</em> a <strong>userDao</strong> object. This in turn contains a <strong>database</strong> service object, a<strong> cache </strong>service object and a <strong>logging </strong>service object. Some of <em>these</em> objects have their own dependencies! For example the database service object contains a <strong>configuration</strong> object.</p>
<p>The key point here is that by default, when we serialise a user object we will be serialising all the internal properties, including all the dependencies. This is undesirable.</p>
<p>This is where PHP&#8217;s built-in magic <strong>__sleep</strong> method comes to the rescue. Using __sleep we can <em>tell</em> PHP what we<em> do</em> want to store. Let&#8217;s assume our user object has the following properties:</p>
<pre class="code">class user
{
    private $dao;
    private $name;
    private $age;
    private $email;
    private $phoneNumber;
    private $usageHistory;
}</pre>
<p>What we&#8217;ll do is tell PHP what we want to save.</p>
<pre class="code">class user
{
    public function __sleep()
    {
        return array('name', 'age', 'email', 'phoneNumber');
    }
}</pre>
<p>Now we can serialise and/or cache objects without the overhead of complex dependency graphs.</p>
<h3><a name="waking-objects-up">Waking objects up</a></h3>
<p>When it comes to restoring objects, for example via Memcache::get or via unserialize(), we will end up with a user object that has a valid name, age, email and phoneNumber property.  What we won&#8217;t have is the <strong>DAO</strong> dependency or the <strong>usageHistory</strong> property.  It is important to realise that the class constructor will <em>not</em> be called when the object is unserialised.</p>
<p>For pure simplicity we can use PHP&#8217;s built-in magic <strong>__wakeup</strong> method to execute code on unserialisation.</p>
<pre class="code">class user
{
    public function __wakeup()
    {
        $this-&gt;usageHistory = NULL;
        $diContainer = new diContainer();
        $userDao = $diContainer-&gt;getInstance('userDao');
    }
}</pre>
<p>This is handy for ensuring that the usageHistory property is properly set to NULL (so it will lazy-load). The problem with this approach is that we lose the Inversion of Control. Instead of <em>injecting</em> the dependencies, we are instead looking them up; we have a tightly coupled dependency to the DI container. One of the key points of DI is that the objects themselves shouldn&#8217;t really know or care about the DI container.</p>
<p>When constructing objects using the DI container we never directly use the &#8220;new&#8221; keyword to create objects &#8211; instead we rely on the DI container to do this for us. This supplies all dependencies as <strong>parameters</strong>. However we can&#8217;t replace the call to __wakeup; and therefore we can&#8217;t inject dependencies here.</p>
<h3>Restoring dependencies</h3>
<p>To ensure that dependencies are restored correctly I use a &#8220;magic&#8221; method <strong>__restoreDependencies</strong>. Ok so it&#8217;s not actually that magic; PHP doesn&#8217;t call it automatically! However the serialisation/unserialisation in my application is localised within my <strong>cache</strong> object. Therefore what I can do is adjust my cache::get method:</p>
<pre class="code">class cache
{
    public function get($key)
    {
        $value = $this-&gt;memcache-&gt;get($key);
        if (is_object($value) &amp;&amp; $value instanceof cacheable)
        {
            $this-&gt;diContainer-&gt;wakeup($value);
        }
    }
}</pre>
<p>To make life easy I actually use a &#8220;cacheable&#8221; interface that objects must implement in order to be stored in cache. This formality really just ensures that no one tries to cache objects without making sure they think of the implications on dependencies. The cacheable interface simply ensures that an object has a __restoreDependencies() method.</p>
<p>The (bespoke) DI container has a &#8220;wakeup&#8221; method that will:</p>
<p>1. Call the __restoreDependencies() method injecting any required services (dependency objects)</p>
<p>2. If the __restoreDependencies() method returns an array of other objects, call the wakeup() method on those objects as well. This can repeat recursively if required.</p>
<p>The second point here ensures that we can cache an entire <strong>userList </strong>object and wake it up effectively.  The <strong>userList </strong>object&#8217;s __restoreDependencies() method would return an array of all <strong>user </strong>objects that need waking up.</p>
<p>The result is that I can cache complex object graphs <em>without</em> dependencies, but have these dependencies automatically &#8220;fixed&#8221; when objects are retrieved from cache. The objects themselves don&#8217;t really know anything about the process. Instead all they need to do is define a simple interface which defines the required dependencies.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.davegardner.me.uk/blog/2010/03/22/caching-dependency-injected-objects-with-php/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Setting up Git on CentOS 5 server</title>
		<link>http://www.davegardner.me.uk/blog/2010/01/29/setting-up-git-on-centos-5-server/</link>
		<comments>http://www.davegardner.me.uk/blog/2010/01/29/setting-up-git-on-centos-5-server/#comments</comments>
		<pubDate>Fri, 29 Jan 2010 16:42:49 +0000</pubDate>
		<dc:creator>Dave</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[github]]></category>
		<category><![CDATA[scm]]></category>
		<category><![CDATA[svn]]></category>

		<guid isPermaLink="false">http://www.davegardner.me.uk/blog/?p=79</guid>
		<description><![CDATA[I'm currently setting up Git for our company. The reason is that Git is better than X! This post is all about how to get Git setup on CentOS 5 including creating and sharging a repository.]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m currently setting up <a target="_blank" href="http://git-scm.com/">Git</a> for our company. The reason is that <a target="_blank" href="http://whygitisbetterthanx.com/">Git is better than X</a>. This post is all about <strong>how to get Git setup on CentOS 5</strong>. There are other posts on this topic, of course, but this one is better!</p>
<ul>
<li><a href="#intro">Two minute intro to Git</a></li>
<li><a href="#install">Installing Git on CentOS 5</a></li>
<li><a href="#creatingrepo">Creating and sharing a repository</a></li>
<li><a href="#tortoise">Tortoise; the familiar client for Windows</a></li>
<li><a href="#github">Git hub</a></li>
<li><a href="#moreinfo">Finding out more &#8211; useful links</a></li>
</ul>
<h3><a name="intro">Two minute intro to Git</a></h3>
<p>I&#8217;ve come from an SVN background; you checkout a copy of a central repository, make some changes and commit. Git is a slightly different beast in that it is a <em>distributed</em> Source Control Management system. What this means is that you have your <strong>own</strong> local repository where you can happily commit changes (whether online or offline). To share your changes with others, you can then <strong>push</strong> your changes to another repository (either their repository or some central repository if you&#8217;d prefer). Similarly, to work on someone else&#8217;s code, you can create your own <strong>cloned</strong> version of their repository and then <strong>pull</strong> updates as required.</p>
<p>The reason I&#8217;m switching to Git is all about branching &#8211; I find this a real pain in SVN. If you&#8217;re not convinced you can <a target="_blank" href="http://whygitisbetterthanx.com/">click here to find out Git is better</a> than your current SCM.</p>
<h3><a name="install">Installing Git on CentOS 5</a></h3>
<p>Installing Git on CentOS 5 is easy if you make use of the <a target="_blank" href="http://fedoraproject.org/wiki/EPEL">EPEL</a> (Extra Packages for Enterprise Linux) repository. You&#8217;ll know if you&#8217;ve got this installed if the following fails:</p>
<pre class="code">
yum install git
</pre>
<p>To setup EPEL all you need to do is create a file <strong>/etc/yum.repos.d/epel.repo</strong> and then paste in the following:</p>
<pre class="code">
[epel]
name=Extra Packages for Enterprise Linux 5 - $basearch
#baseurl=http://download.fedoraproject.org/pub/epel/5/$basearch
mirrorlist=http://mirrors.fedoraproject.org/mirrorlist?repo=epel-5&amp;arch=$basearch
failovermethod=priority
enabled=1
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL

[epel-debuginfo]
name=Extra Packages for Enterprise Linux 5 - $basearch - Debug
#baseurl=http://download.fedoraproject.org/pub/epel/5/$basearch/debug
mirrorlist=http://mirrors.fedoraproject.org/mirrorlist?repo=epel-debug-5&amp;arch=$basearch
failovermethod=priority
enabled=0
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL
gpgcheck=1

[epel-source]
name=Extra Packages for Enterprise Linux 5 - $basearch - Source
#baseurl=http://download.fedoraproject.org/pub/epel/5/SRPMS
mirrorlist=http://mirrors.fedoraproject.org/mirrorlist?repo=epel-source-5&amp;arch=$basearch
failovermethod=priority
enabled=0
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL
gpgcheck=1
</pre>
<p>Now you can install using:</p>
<pre class="code">
yum install git git-daemon
</pre>
<h3><a name="creatingrepo">Creating and sharing a repository</a></h3>
<p>Creating a repository is easy! Simply create a folder and type <strong>git init</strong>.</p>
<pre class="code">
mkdir newrepo
cd newrepo
git init
</pre>
<p>Once created, we can copy/create our files (think svn import) and then do:</p>
<pre class="code">
git add .
git commit
</pre>
<p>Once you&#8217;ve created a repository, you&#8217;ll probably want to <strong>share it</strong>. This means that other people can pull and push changes. There are a number of ways of accomplishing this (<a target="_blank" href="http://www.jedi.be/blog/2009/05/06/8-ways-to-share-your-git-repository/">this blog post lists 8 possibilities</a>). My usual method for sharing SVN repositories is via Apache; Git supports this as well. I think one of the simplest solutions is to use the Git Deamon. To allow others to pull <strong>and</strong> push you can share your Git repository using the following command:</p>
<pre class="code">
git daemon --reuseaddr --base-path=/path/to/repos --export-all --verbose --enable=receive-pack
</pre>
<p>This command will share <strong>all repositories</strong> found within the folder <strong>/path/to/repos</strong> (so we would have created our &ldquo;newrepo&rdquo; folder within this location). Once shared you can clone the repository using the git resource locator syntax:</p>
<pre class="code">
git clone git://remote.computer.hostname/newrepo
</pre>
<p>Or you can just use the IP address if you&#8217;d prefer.</p>
<p>You should now have a repository setup on a CentOS 5 server which you can clone and then pull/push updates.</p>
<h3><a name="tortoise">Tortoise; the familiar client for Windows</a></h3>
<p>When I&#8217;ve used <a target="_blank" href="http://mercurial.selenic.com/">Mercurial</a> in the past (another distributed SCM), I&#8217;ve actually found the command line tools significantly easier to use than the GUI (Tortoise). However there is a level of familiarity that a TortoiseSVN-like frontend provides.</p>
<p><a href="http://www.davegardner.me.uk/blog/wp-content/uploads/2010/01/tortoisegit.jpg"><img src="http://www.davegardner.me.uk/blog/wp-content/uploads/2010/01/tortoisegit.jpg" alt="Tortoise Git" title="Tortoise Git" width="488" height="607" class="alignnone size-full wp-image-85" /></a></p>
<p><a target="_blank" href="http://code.google.com/p/tortoisegit/">TortoiseGit</a> has all the features you&#8217;d be used to from using TortoiseSVN plus <strong>Pull</strong>, <strong>Push</strong> and all the other Git-specific stuff.</p>
<h3><a name="github">Git hub</a></h3>
<p>It&#8217;s worth making a quick mention of <a target="_blank" href="http://github.com/">Git Hub</a>. According to the website, &ldquo;GitHub is the easiest (and prettiest) way to participate in that collaboration: fork projects, send pull requests, monitor development, all with ease.&rdquo;.</p>
<p>Git Hub provides a handy way of visualising a Git project (listing commits, branches and pretty-printed code). It avoids the need to setup your <em>own</em> central Git repository and mess about setting the server up. A lot of projects seem to be moving this way, for example <a target="_blank" href="http://github.com/symfony/symfony">Symfony</a>.</p>
<h3><a name="moreinfo">Finding out more &#8211; useful links</a></h3>
<h4><a target="_blank" href="http://whygitisbetterthanx.com/">http://whygitisbetterthanx.com/</a></h4>
<p>Some well thought out and concise arguments as to why Git is better than other SCM systems.</p>
<h4><a target="_blank" href="http://gitready.com/">http://gitready.com/</a></h4>
<p>Excellent site &#8211; &ldquo;learn git one commit at a time&rdquo;. Lots of help and advice clearly laid out.</p>
<h4><a target="_blank" href="http://git.or.cz/course/svn.html">http://git.or.cz/course/svn.html</a></h4>
<p>Crash course for SVN users &#8211; really good comparison of SVN commands and the equivalent GIT commands.</p>
<h4><a target="_blank" href="http://www.jedi.be/blog/2009/05/06/8-ways-to-share-your-git-repository/">http://www.jedi.be/blog/2009/05/06/8-ways-to-share-your-git-repository/</a></h4>
<p>8 ways to share your git repository &#8211; file share, Git daemon, plain SSH server, SSH server git-shell, Gitosis, Apache http + gitweb, github.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.davegardner.me.uk/blog/2010/01/29/setting-up-git-on-centos-5-server/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>PHP dependency strategies: dependency injection and service locator</title>
		<link>http://www.davegardner.me.uk/blog/2009/11/23/php-dependency-strategies-dependency-injection-and-service-locator/</link>
		<comments>http://www.davegardner.me.uk/blog/2009/11/23/php-dependency-strategies-dependency-injection-and-service-locator/#comments</comments>
		<pubDate>Mon, 23 Nov 2009 10:49:17 +0000</pubDate>
		<dc:creator>Dave</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[dependencyinjection]]></category>
		<category><![CDATA[di]]></category>
		<category><![CDATA[oop]]></category>
		<category><![CDATA[servicelocator]]></category>

		<guid isPermaLink="false">http://www.davegardner.me.uk/blog/?p=17</guid>
		<description><![CDATA[This post explores three possible strategies that should help create good quality, uncoupled code: Simple Dependency Injection (DI), the Service Locator pattern and a DI framework. This includes a bespoke implementation of a DI framework.]]></description>
			<content:encoded><![CDATA[<p>In this post I&#8217;m hoping to answer my own question: <strong>what strategy shall I use for handling dependencies in my new project?</strong> I&#8217;m going to explore three possible strategies that should help create good quality, uncoupled code:</p>
<ol>
<li><a href="#strategy1">Simple Dependency Injection (DI)</a></li>
<li><a href="#service-locator">The Service Locator pattern</a></li>
<li><a href="#di-framework">A DI framework</a></li>
</ol>
<p>This includes a <a href="#bespoke-service-injector">bespoke implementation of a DI framework for PHP</a> that automatically creates configuration by conducting a simplistic static analysis of code.</p>
<h3>What are dependencies</h3>
<p>Consider the following code. This simple application comprises a simple <strong>event</strong> domain object combined with a <a target="_blank" href="http://java.sun.com/blueprints/corej2eepatterns/Patterns/DataAccessObject.html">Data Access Object</a> (DAO) that deals with persistance.</p>
<h5>event.class.php</h5>
<pre class="code">
class event
{
    private $name;
    private $cost;
    private $eventDate;

    /**
     * @param array $row Information on this event from DAO
     */
    public function __construct($row)
    {
        $this->name = $row['name'];
        $this->cost = new money($row['cost']);
        $this->eventDate = new date($row['date']);
    }

    public function __toString()
    {
        return "EVENT: {$this->name}\nCOST:  {$this->cost}\nDATE:  {$this->eventDate}\n";
    }
}
</pre>
<h5>eventDao.class.php</h5>
<pre class="code">
class eventDao
{
    public function getById($id)
    {
        $db = new database('localhost','mydb','user','password');

        $row = $db->fetchAll(
           "SELECT name, cost, date FROM events WHERE id = ".$db->quote($id);
        );

        return new event($row);
    }
}
</pre>
<p>An <strong>event</strong> object is dependant on a <strong>money</strong> object and a <strong>date</strong> object. It needs to create these to function correctly.</p>
<p>An <strong>eventDao</strong> object is dependant on a <strong>database</strong> object and an <strong>event</strong> object. It needs the database object to get the data and it needs to create and return a new event object.</p>
<h3>Why are depedencies problematic?</h3>
<p>Dependencies are not in themselves problematic. It is going to be impossible to write any useful code that doesn&#8217;t have some dependencies. The problem is how we handle those the dependencies. The code example provided above presents the following problems.</p>
<h5>1. It makes testing impossible</h5>
<p>Writing a <a target="_blank" href="http://en.wikipedia.org/wiki/Unit_testing">unit test</a> for the event object will inevitably end up testing the <strong>money</strong> and <strong>date</strong> objects. When we create a new event object we have no control over the creation of those dependent objects. This means our unit test will cross the class boundary and what we end up with is an <a target="_blank" href="http://en.wikipedia.org/wiki/Integration_testing">integration test</a> rather than a unit test. Instead of testing the logic of the specific, isolated &ldquo;unit&rdquo; (our event object), we are instead testing the event object works in relation to the rest of the program.</p>
<p>While it may not seem immediately obvious why that&#8217;s a problem with fairly trivial dependencies such as a money object, the problem is more obvious when considering the DAO. Here we could not test the <strong>getById</strong> method without inadvertantly testing the <strong>database</strong> object. Without a fully-functioning database, setup with the expected data, our unit test will fail. Again, this isn&#8217;t a unit test, it&#8217;s more likely an intergration test or possibly even a <a target="_blank" href="http://en.wikipedia.org/wiki/System_testing">system test</a>.</p>
<h5>2. The objects are tightly coupled</h5>
<p>The <strong>eventDao</strong> class is tightly coupled to the specific concrete classes <strong>event</strong> and <strong>database</strong>. What if we want to use a different database object on our test environment? We can&#8217;t. Of course there&#8217;s ways round this immediate problem without changing too much at all. We could use global constants DATABASE_NAME, DATABASE_USER etc.. Don&#8217;t even go there! Tight coupling makes for <strong>brittle code</strong>. If you&#8217;re not convinced you can <a target="_blank" href="http://www.ibm.com/developerworks/java/library/j-cq05227/index.html">read this article</a> or spend 10 minutes with Google.</p>
<h5>3. It goes against the <a target="_blank" href="http://en.wikipedia.org/wiki/Don%27t_repeat_yourself">Don&#8217;t Repeat Yourself</a> (DRY) principle</h5>
<p>If we imagine adding some other domain objects and DAOs to our system we will end up repeating the <strong>new database()</strong> line again and again. The same goes for other domain objects that want to represent information internally as a date object.</p>
<h4>An alternative coupling</h4>
<p>Let&#8217;s say you&#8217;ve got this in your DAO instead:</p>
<pre class="code">
        $db = database::getInstance();
</pre>
<p>Same problems! We probably still can&#8217;t test it (unless we have some kind of <em>database::setInstance()</em> method) and it&#8217;s certainly still tightly coupled regardless.</p>
<h3><a name="strategy1">Strategy 1: Dependency Injection</a></h3>
<p>Dependency Injection is very straightforward. In fact it&#8217;s so straightforward you&#8217;ve almost certainly already done it, even if you didn&#8217;t refer to it as DI. Fabien Potencier of Symfony fame <a target="_blank" href="http://fabien.potencier.org/talk/19/decouple-your-code-for-reusability-ipc-2008">explains it expertly in these slides</a>.</p>
<p>To make use of dependency injection, our <strong>eventDao</strong> can be updated to:</p>
<h5>eventDao.class.php</h5>
<pre class="code">
class eventDao
{
    private $db;

    public function __construct($db)
    {
       $this->db = $db;
    }

    public function getById($id)
    {

        $row = $this->db->fetchAll(
           "SELECT name, cost, date FROM events WHERE id = ".$this->db->quote($id);
        );

        return new event($row);
    }
}
</pre>
<pre class="code">
$db = new database('localhost','mydb','user','password');
$dao = new eventDao($db);
$event = $dao->getById(1);
</pre>
<p>We can now <em>test</em> the <strong>getById</strong> method using a <a target="_blank" href="http://www.phpunit.de/manual/current/en/test-doubles.html">mock database object</a> because we are <em>injecting</em> the dependency into the DAO object.</p>
<p>We can&#8217;t, however, isolate testing of the DAO completely because of the <strong>event</strong> dependency. This can be fixed by delegating responsibility for <strong>event</strong> creation to a <a target="_blank" href="http://www.ibm.com/developerworks/library/os-php-designptrns/">Factory</a>.</p>
<h5>eventFactory.class.php</h5>
<pre class="code">
class eventFactory
{
    public function create($row)
    {
        return new event($row);
    }
}
</pre>
<h5>eventDao.class.php</h5>
<pre class="code">
class eventDao
{
    private $db;
    private $eventFactory;

    public function __construct($db, $eventFactory)
    {
       $this->db = $db;
       $this->eventFactory = $eventFactory;
    }

    public function getById($id)
    {

        $row = $this->db->fetchAll(
           "SELECT name, cost, date FROM events WHERE id = ".$this->db->quote($id);
        );

        return $this->eventFactory->create($row);
    }
}
</pre>
<p>Our code is now loosely coupled and we are <a target="_blank" href="http://stackoverflow.com/questions/383947/what-does-it-mean-to-program-to-an-interface">programming to interface</a> (allbeit that I haven&#8217;t actually put any interfaces into the code at this stage!) To <a target="_blank" href="http://stackoverflow.com/questions/383947/what-does-it-mean-to-program-to-an-interface/383954#383954">quote kdgregory from StackOverflow</a>:</p>
<blockquote><p>Programming to an interface is saying &ldquo;I need this functionality and I don&#8217;t care where it comes from.&rdquo;</p></blockquote>
<p>By putting in place a factory for creating objects we can program only to the <em>interface</em> we require. In our <strong>event</strong> class, this means we don&#8217;t have to rely on specific concrete implementations for <strong>date</strong> and <strong>money</strong>, instead we merely require some object that implements <strong>iDate</strong> and <strong>iMoney</strong>, and we can use a factory to <em>make</em> us one of those objects.</p>
<h4>Inversion of Control (IoC)</h4>
<p>It&#8217;s worth noting that by <em>injecting</em> dependencies into the objects we have <em>inverted</em> control, effectively because rather than the procedural/linear style of setting up object and then doing something, we have passed in an object and are executing what almost amounts to a &lsquo;call back&rsquo; on it. The term &ldquo;Inversion of Control&rdquo; seems to come up frequently when reading about DI, although I&#8217;m not sure that it&#8217;s always that clearly explained. Fowler <a target="_blank" href="http://martinfowler.com/bliki/InversionOfControl.html">explains it in this article</a>. There are also some other <a target="_blank" href="http://mikehadlow.blogspot.com/2007/10/what-is-inversion-of-control.html">interesting blog posts on the subject</a>. If you want the short answer on what IoC is, <a target="_blank" href="http://stackoverflow.com/questions/3058/what-is-inversion-of-control/386475#386475">check out this definition.</a></p>
<h4>Object graphs</h4>
<p>Using DI, what we inevitably end up with is a complex <strong>object graph</strong>. An object graph is <a target="_blank" href="http://stackoverflow.com/questions/877157/what-is-an-object-graph-and-how-do-i-serialize-one">simply a set of interconnected objects</a>. In the case of DI, we have lots of interconnected objects since we are passing all our dependencies around as objects &#8211; so we end up with a lot of objects related to a lot of other objects at run time!</p>
<h4>Strengths</h4>
<p>This form of dependency injection is <strong>easy to understand</strong>. We avoid tight coupling, we can test our code and we are programming to interface. All is good!</p>
<h4>Weaknesses</h4>
<p>One of the web apps I work on uses a <a target="_blank" href="http://martinfowler.com/eaaCatalog/frontController.html">Front Controller pattern</a> to handle incoming requests. The bootstrap code looks a bit like this:</p>
<pre class="code">
$fc = new frontController();
$fc->dispatch();
</pre>
<p>If I take the issue of dependency injection to the extreme, slightly insane, but on some level undeniably logical, conclusion, I would have to inject <strong>all</strong> dependencies needed by the <em>entire application</em> into the constructor of the front controller! <a target="_blank" href="http://stackoverflow.com/questions/871405/why-do-i-need-an-ioc-container-as-opposed-to-straightforward-di-code/1532254#1532254">This post by Ben Scheirman</a> on StackOverflow gives another example:</p>
<pre class="code">
var svc = new ShippingService(new ProductLocator(),
   new PricingService(), new InventoryService(),
   new TrackingRepository(new ConfigProvider()),
   new Logger(new EmailLogger(new ConfigProvider())));
</pre>
<p>You get the idea.</p>
<p>We could be pragmatic about this and suggest that individual <a target="_blank" href="http://martinfowler.com/eaaCatalog/pageController.html">page controllers</a> are allowed to be tightly coupled to domain objects. However it merely defers the inevitable. </p>
<p>The problem with this strategy is that if you add a dependency to an object, you then have to add it to all parent objects that <em>use</em> that object. This becomes a recursive task so the change causes a ripple effect to other code. The <a target="_blank" href="http://code.google.com/docreader/#p=google-guice&#038;s=google-guice&#038;t=Motivation">documentation to Google Guice</a> explains it quite well (scroll down to the &ldquo;Dependency Injection&rdquo; section &#8211; due to their clever reader thing I can&#8217;t get an anchor link straight to it!) This problem relates to the inherent complexity involved in creating a large <em>object graph</em>.</p>
<blockquote><p>Unfortunately, now the clients of BillingService need to lookup its dependencies. We can fix some of these by applying the pattern again! Classes that depend on it can accept a BillingService in their constructor. For top-level classes, it&#8217;s useful to have a framework. <strong>Otherwise you&#8217;ll need to construct dependencies recursively when you need to use a service</strong></p></blockquote>
<h3><a name="service-locator">Strategy 2: Service Locator</a></h3>
<p>Martin Fowler explains the idea of a service locator in detail in his <a target="_blank" href="http://martinfowler.com/articles/injection.html#UsingAServiceLocator">article on the subject of DI</a>. I&#8217;m going to explain it in the context of a PHP application.</p>
<p>A service locator is a straight forward system whereby objects can &ldquo;look up&rdquo; any dependencies they need from a central source. This gives the following advantages:</p>
<ul>
<li>It is easy to add a dependency to any object</li>
<li>It is easy to replace which dependency is provided <em>project wide</em>, so we are adhering to the DRY principle</li>
<li>It removes tight coupling between objects</li>
</ul>
<p>The simplest service locator may look like:</p>
<h5>serviceLocator.class.php</h5>
<pre class="code">
class serviceLocator
{
    public static function getDatabase()
    {
        return new database();
    }

    public static function getDateFactory()
    {
        return new dateFactory();
    }

    public static function getMoneyFactory()
    {
        return new moneyFactory();
    }

    public static function getEventFactory()
    {
        return new eventFactory();
    }
}
</pre>
<p>Our DAO now becomes:</p>
<h5>eventDao.class.php</h5>
<pre class="code">
class eventDao
{
    public function getById($id)
    {

        $row = serviceLocator::getDatabase()->fetchAll(
           "SELECT name, cost, date FROM events WHERE id = ".$this->db->quote($id);
        );

        return serviceLocator::getEventFactory()->create($row);
    }
}
</pre>
<p>For testing we&#8217;d need to add in equivalent methods like <strong>serviceLocator::setMoneyFactory</strong> and <strong>serviceLocator::setDatabase</strong>.</p>
<p>We can simplify (or complicate depending on your point of view) our service locator by replacing methods like <strong>serviceLocator::getMoneyFactory()</strong> with a more generic <strong>serviceLocator::getService($serviceName)</strong>. We could then configure the service locator in our bootstrap with calls to <strong>serviceLocator::registerService($serviceName, $object)</strong>. If we really wanted to go to town we could use an XML or YAML file to store the details of the dependencies that the service locator provided. For a working system, we probably would want to go this far.</p>
<p>In terms of coupling, we have replaced the coupling of objects from our very first example (where eventDao was tightly coupled to database and event) with equally tight coupling, albeit this time to a <em>single</em> object &#8211; the service locator object. Whether this is desirable will come down to the details of the application. As Fowler points out in his discussion of locator vs injector:</p>
<blockquote><p>The key difference is that with a Service Locator every user of a service has a dependency to the locator. The locator can hide dependencies to other implementations, but you do need to see the locator. So the decision between locator and injector depends on whether that dependency is a problem.</p></blockquote>
<p>In terms of practical implementations, Mutant PHP has <a target="_blank" href="http://mutantphp.org/blog/2008/06/19/a-service-locator-for-php5/">published an article on this subject</a> which includes a sample service locator class.</p>
<p>The fairly new <a target="_blank" href="http://components.symfony-project.org/dependency-injection/">Symfony Dependency Injection Container</a> appears to be based around the idea of a service locator. I say this because it doesn&#8217;t implement an <em>inversion of control</em> mechanism &#8211; as covered in <a href="#di-framework">strategy 3</a>.</p>
<h4>Strengths</h4>
<p>The service locator provides a <strong>simple</strong> strategy for managing dependencies that is easily understood. It allows for testing and it avoids tight coupling between classes.</p>
<h4>Weaknesses</h4>
<p>The use of a service locator leads to a tight coupling between classes and the service locator itself.</p>
<h3><a name="di-framework">Strategy 3: DI Framework</a></h3>
<p>A dependency injection &ldquo;framework&rdquo; is an alternative strategy for dealing with dependencies to the arguably simpler <a href="#service-locator">service locator</a>. They key idea is to stick with depedency <em>injection</em> (either into the constructor or via a setter), but have some external object (Fowler calls this an &ldquo;assembler&rdquo; in <a target="_blank" href="http://martinfowler.com/articles/injection.html#FormsOfDependencyInjection">his article on the subject</a>) actually deal with managing the dependencies, injecting them into objects as required, without the user having to worry about it.</p>
<p>Now coming from a PHP background, I&#8217;ve searched about for PHP-specific information on DI frameworks. So far, I haven&#8217;t managed to find anything that I feel explains the concept as well as the <a target="_blank" href="http://code.google.com/docreader/#p=google-guice&#038;s=google-guice&#038;t=Motivation">Guice documention</a> does. In terms of responsiblity-driven design, Guice outlines the role of the &ldquo;injector&ldquo; (Fowler&#8217;s &ldquo;assembler&rdquo;):</p>
<blockquote><p>The injector&#8217;s job is to assemble graphs of objects. You request an instance of a given type, and it figures out what to build, resolves dependencies, and wires everything together.</p></blockquote>
<p>This sounds promising, although I&#8217;m not 100% convinced I <em>need</em> a DI framework, I&#8217;m starting to see some advantages. There is an <a target="_blank" href="http://stackoverflow.com/questions/500637/understanding-the-need-for-a-di-framework">interesting discussion on StackOverflow</a> (again!) about the need for a DI framework.</p>
<h4><a name="bespoke-service-injector">A bespoke DI Framework</a></h4>
<p>To help understand the advantages of a DI framework I built my own, which I&#8217;ve rather confusingly called a &ldquo;Service Injector&rdquo;. As Benjamin Eberlei explains in a <a target="_blank" href="http://www.whitewashing.de/blog/articles/117">blog post on the subject of DI</a>:</p>
<blockquote><p>My subjective feeling tells me there are now more PHP DI containers out there than CMS or ORMs implemented in PHP, including two written by myself (an overengineered and a useful one).</p></blockquote>
<p>Having recently read the excellent <a target="_blank" href="http://www.amazon.co.uk/Coders-Work-Reflections-Craft-Programming/dp/1430219483">Coders at Work</a> (go and buy it now if you haven&#8217;t read it), I took some advice from Donald Knuth who said:</p>
<blockquote><p>
The problem is that coding isn&#8217;t fun if all you can do is call things out of a library, if you can&#8217;t write the library yourself.
</p></blockquote>
<p>So I decided to <a href="#source-code">write my own</a>.</p>
<h4>Design motivations</h4>
<p>In Benjamin&#8217;s post, he goes on to say:</p>
<blockquote><p>Its an awesome pattern if used on a larger scale and can (re-) wire a complex business application according to a clients needs without having to change much of the domain code. </p></blockquote>
<p>I think my motivations for DI framework are somewhat different. I don&#8217;t see myself wanting to &ldquo;re-wire&rdquo; an application at a later date.<br />
Ideally I want my logic and wiring to remain clear at the <em>code</em> level; I personally don&#8217;t want to delegate all the wiring to some configurator &#8211; I can see that making any debugging task harder. What I want from a framework is something that will do the hard work for me; something that will supply actual <em>dependencies</em> automatically.</p>
<p>This led me to make the following decisions:</p>
<ul>
<li>I wanted an automated <strong>builder</strong>; something that would look at the code and get the DI framework setup ready to go &#8211; based on class names and interfaces</li>
<li>I wanted to keep <strong>Factory</strong> classes; I think it makes logical sense to have a class who&#8217;s responsibility is to create new objects of type <em>blah</em></li>
</ul>
<h4>A sample application</h4>
<p>At the top level, I can ask the DI framework to create me an object:</p>
<pre class="code">
// setup the service injector
include APP_PATH.'siConfig.php';
$serviceInjector = new serviceInjector();

// ----

// for our test app we'll just pretend we're looking at the details
// of event #1:

$oDao = $serviceInjector->getInstance('eventDao');
$oEvent = $oDao->getById(1);
</pre>
<p>The DAO object is created, along with its dependencies; this all happens simply by annotating the code within the PHPDocumentor style comment blocks:</p>
<pre class="code">
    /**
     * Constructor
     * @param iDatabase $database A service that will allow us to execute SQL
     * @param iEventFactory $eventFactory A service that will create event objects for us
<strong>     * @inject This informs the DI builder to inject constructor parameters on object creation</strong>
     */
    public function __construct(iDatabase $database, iEventFactory $eventFactory)
</pre>
<p>The service injector will find a class that implements iDatabase and iEventFactory and automatically <em>inject</em> these on object creation. The interesting thing is that either of these two services can have their <em>own</em> dependencies. For example, my eventFactory class declaration looks like this:</p>
<pre class="code">
class eventFactory extends factory implements iEventFactory
</pre>
<p>It extends the <a target="_blank" href="http://martinfowler.com/eaaCatalog/layerSupertype.html">Layer Supertype</a> <strong>factory</strong>. The factory base class has a <strong>method</strong> to set its own dependency, again specified via annotation:</p>
<pre class="code">
    /**
     * Set service injector
     * @inject This informs the DI builder to inject method parameters immediately after object creation
     */
    public function setServiceInjector(iServiceInjector $serviceInjector)
    {
        $this->serviceInjector = $serviceInjector;
    }
</pre>
<p>The <em>service injector</em> will happily go away and recursively assemble the required objects and their dependencies.</p>
<h4>The builder</h4>
<p>I have a script that can be executed as part of an automated build process (see my other post) that will create a pure-PHP configuration file for my service injector. It works by conducting a somewhat crude static analysis of the code you tell it to examine. It then works out which classes wire up to which interfaces, what extends what, which methods need parameters injecting and which classes should be shared (rather than a new instance created on every request).</p>
<p>Right now, it works as well as it needs to for the sample application. However it doesn&#8217;t do very well if you have more than one class that implements a given interface, and then you ask the service injector to build you a <em>blah</em> interface &#8211; in this situation it will fail. You&#8217;ll notice that although I&#8217;ve got a lot of interfaces in the sample application, they all have one class that implements the interface. I think this is a worthwhile exercise because it gets you into the mindset that you are programming <em>to</em> interface and thinking about <em>messages</em> that the objects send other objects.</p>
<h4>Pros and cons</h4>
<p>I like how my implementation creates the wiring-up configuration automatically based on the actual code. I also like how the service injector is really focussed on programming to <strong>interface</strong>: a service is simply some object that will provide a set of capabilities and the service injector&#8217;s only job is to inject these objects at run time. It does not deal with injecting strings and other configuration parameters; I think that&#8217;s OK since a string is not a <em>service</em> &#8211; and I set out to build something that would only do that job.</p>
<p>I guess that&#8217;s where my <em>service</em> injector differs from other implementations of <em>dependency</em> injection containers &#8211; I have focussed purely on something that will provide services, not any other types of depdency, such as configuration strings. Perhaps this could be considered a con!</p>
<p>The static analysis in this simple version is fairly rudimentary, although that said it will quite happily analyse the Zend framework source code. I tried this out and then made my date factory ask the service injector for a new Zend_Date object. This all worked fine &#8211; simply by changing one line of code.</p>
<h4><a name="source-code">The source code</a></h4>
<p>So I&#8217;ve written this tool purely as a way to <em>learn</em> about the ideas involved and also to see if I could find a structure that I thought was useful for <em>my</em> application. It&#8217;s been done pretty quickly but if you&#8217;d like to have a closer look you can <a tagret="_blank" href="http://svn.davegardner.me.uk/serviceinjector/trunk/">browse the source code here</a>.</p>
<h4>Other implementations for PHP</h4>
<ul>
<li>Fabien Potencier has written a <a target="_blank" href="http://components.symfony-project.org/dependency-injection/">Dependency Injection Container for the Symfony project</a>, although it will apparently work just as well as a stand-alone component</li>
<li>Benjamin Eberlei has <a target="_blank" href="http://www.whitewashing.de/blog/articles/117">written not one but two!</a></li>
<li>Federico Cargnelutti has <a target="_blank" href="http://framework.zend.com/wiki/display/ZFPROP/Zend_Di+-+Federico+Cargnelutti">proposed</a> and <a target="_blank" href="http://www.fedecarg.com/projects/show/zfdi">is working on Zend_DI</a> &#8211; a DI component for the Zend framework</li>
</ul>
<h3>Conclusions</h3>
<p>Through this process of research I have come to the following conclusions:</p>
<ul>
<li>I prefer DI over a service locator because the individual modules are <em>cleaner</em>; dependencies are passed <em>in</em> rather than the object itself going and asking for them</li>
<li>A DI framework seems the way to go, simply to reduce the complexity involved in manually creating complex object graphs</li>
<li>I like Factory classes because they serve a clear purpose and make code easy to understand</li>
<li>I want a DI framework to be able to work (almost) completely from the source code</li>
</ul>
<p>My next step is to look more closely at existing implementations to see if they could work in a production project.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.davegardner.me.uk/blog/2009/11/23/php-dependency-strategies-dependency-injection-and-service-locator/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>
