Symfony2: Top Down Perspective of Service Configuration

One issue many people have with Dependency Injection is the way you can no longer jump to an implementation of a dependency in an IDE and see what it actually does or make changes to it. This is indeed a side effect of moving towards much more loosely coupled code. If you are injecting a dependency and type hinting it with an interface, then you cannot jump straight to the particular implementation without looking at the DI configuration to see what implementation is being used.

This is not a bad thing though in my opinion, it is just part of moving away from coding to an implementation instead coding to an interface. The code you are working on does not know about the details of the implementation only its public methods, so in many ways it helps to, in effect, only know that yourself when working on that class. A big advantage of Dependency Injection is shifting the decision of what implementation to use out of the code and into a separate configuration, which is  why it is a good thing to be ignorant of this configuration when coding.

The inverse way of looking at this issue is that if you are not using Dependency Injection to pull all of this configuration out of the code then you cannot get a top down perspective of how the application is wired together without digging through the code itself. By separating the configuration from the classes themselves  you can more easily get an overview of how all the classes work together in an application.  Once you have made this shift in your way of thinking then it seems less problematic to not be able to jump to the implementation when working in the code.

If you are working with Symfony2 then as well as just looking at the services config files there are some great tools to get an overview of the services.

Out of the box there is a console command that will print out a list of all the services in the service container.

You can also specify a service by id to get more detailed information:

Whilst the console command is certainly helpful, especially for resolving service ids to actual class names, there is more information it would be helpful to be able to view. Johannes M. Schmitt‘s Debugging Bundle provides more useful tools for working with services in Symfony2. Once installed it adds a new section to the web profiler called service container where you can view information about the services being used in your application.

There is an overall graph of the services, this is split into pages since a typical service graph will include a lot of services:

Service Graph

You can also view the services as a list. The list shows what calls were made to include services including where they originated from, the type of injection which took place, e.g. during construction and whether it was constructed for this call or already existed:

Service List

Most helpfully if you are trying to find out more about a particular service, you can search by service name with an auto-complete facility:

Service Id Autocomplete

You can then view the outgoing services for the chosen service, that is the services that are injected into that service and their dependencies:

Outgoing Service Graph

You can also choose to view the incoming services, that is the services that the chosen service is injected into.

Incoming Service

This all helps to visualise the use of the various services and how they interact with each other. This is a much more difficult task when the dependencies are not injected into classes. You may be able to see what dependencies a class has just from the code but you cannot see which other classes use those dependencies as well nor can you easily see what code uses the class you are working in.

Why use a Dependency Injection Container?

In this post I am going to look at the basics of Dependency Injection again and how they tie in with the move to using a Dependency Injection Container. The basics of why injecting an object’s dependencies is a good idea are fairly easy to grasp, how this then leads to the use of a container is not so easily apparent.

Starting Point

So let’s start by introducing the examples to be used. First up we have a controller that validates POST data and if valid sets up a Product object and passes it to a ProductSaver object to deal with persisting it. For the sake of simplicity the validation part is not actually shown:

The ProductSaver object persists the Product, again not actually shown, and then passes the product to an EmailNotifier object:

The EmailNotifier object creates a message notifying of the addition of the Product and sends it via a Mailer object:

First Steps

Let’s say we need to change the address we are sending the email notification to, to do this we will have to edit this code. If we wanted to use it in a different application where the email went to a different address then we would need to maintain two different versions. So let’s move the address out of the class and inject it instead:

So by passing the email address in via the constructor we have now removed the need to have different versions of the class for different addresses. For the other application we want to CC the email to two different addresses, this means that the technique we used above would not work as we can only pass in one email address, instead what we can do is use setter injection and add the addresses to an array:

So now we can add as many CC addresses or even no CC addresses without having to change the class at all. To make it fully clear of any dependencies we could also inject the Mailer object, this is best suited to constructor injection again as it is a required dependency:

It looks like we can do the same with the Mail object but we need to be careful, whilst we can use the same Mailer object each time notify() is called, we actually want a fresh Mail object on each call. So, if we want to remove the Mail object, we would be better using a factory. Whilst many factory examples use a call to a static method to fetch the object we would then be stuck with a particular factory. Instead we can inject the factory into the class leaving us free to choose what factory to inject.

For more information on the types of dependency injection see my post Symfony2: Dependency Injection Types.

What have we achieved? Well we have made our class look much more complicated, is this really a good thing? Whilst it looks more difficult to maintain and possibly harder to follow, we can now reuse it in different applications with different email addresses and even a different Mailer. This means that we now only need to maintain one version of it and not one for each combination of addresses and Mailer. This means that we have reduced the overall potential maintenance. We have also simplified the role of this class, it now only needs to concern itself with creating the email to send and no longer with whom to send it to and which Mailer to use.

Pushing Creation Upwards

Great then, but where does all the injection of these dependencies go? If we just now tried to use this from our ProductSaver class, we would have problems, as the EmailNotifier is not set up with all its dependencies. To set it up in the ProductSaver we would need to make these changes:

This no longer looks so good, by shifting the set up of the EmailNotifier out of the class itself to the point of creation we have ended up giving the responsibility of setting it up to the ProductSaver. If we didn’t want the EmailNotifer to be concerned with where the email is sent then we definitely don’t want the ProductSaver to be responsible for it. So what do we do? The same as we did in the EmailNotifier, remove the point of creation of its dependencies out of the class:

Whilst we are at it lets move the DataMapper out as well:

Ok problem solved, well sort of. We have pushed the creation up to our controller so that now looks like this:

So I guess we had better repeat the process and push it up out of our controller and into a bootstrap file that sets up our controller. So the controller now looks like this:

With a bootstrap file to set it up:

Great now we can just have a different bootstrap file for each application and set up the configuration of which services we want to use and how to configure them without needing to touch any of the other code.

Managing the Configuration

At the moment this still looks fairly manageable in this way but this is of course a huge simplification. In a real world app, in which we had performed this process of moving the dependencies up through out, the configuration would be much more complicated. For a start we would need to set up the configuration and dependencies of our DataMapper and EmailNotifier. There is also the code that was not shown for the validation of the POST request, we would also need to set up a response to send back to the browser. So the configuration will grow and grow and start to become difficult to maintain itself. That is only for a single action taking place in our application, for the other actions of the controller we may well need to set up other dependencies and configuration. Then there are all the other Controllers and their set ups.

At this point you will probably also have noticed that all the code in the set up is essentially repetitive instantiation of objects and calling of setter methods. Of course, we will want to do something about all this repetition. This is essentially what a Dependency Injection Container (DIC) is, it deals with the instantiation and set up of our dependencies for us and allows us to just specify them in a configuration file.

For the examples, I am going to look at the Symfony2 Dependency Injection Container or Service container as it is also known in the documentation. This is because Symfony2 is the next generation PHP framework which is closest to release and which has a working DIC. In Symfony2 we can set up this configuration using YAML, XML or PHP, I cam going to look at the XML version here. So our set up above could now be done with the following XML file:

We can now get the ProductController from the DIC which will set it up with all of its dependencies:

So the DIC has helped us to clean up the repetition in our setting up of our dependencies. We can now just maintain config files for the DIC for each application.

So having seen loomed at the low level advantages of using DI, we can start to see some of the the application level benefits of using a DIC for DI. We can now avoid any configuration taking place in our code. It is no longer the responsibility or concern of the code but instead a configuration issue. This allows for rapid application development as we can easily reconfigure the framework to suit the current application.

When we do actually want to write some code rather than config files because we want to add a new feature, then we can write a new version of the class that needs the new functionality and just drop it in using the DIC config. Rather than repeat the existing functionality we could decorate the existing class to add this functionality:

We would then not need to change any existing code just the config, these are the changes to the relevant parts:

Other Advantages

Another advantage of using a DIC over writing the object creation code ourselves is that if we were to write the creation of all our controllers then we would be creating a lot of objects that are not used in a request. This is a problem in PHP where everything is created on each request, using a DIC if we request the controller from it then only that controller and its dependencies will be created and not the other controllers. In fact better than this, a good container will use proxies for dependencies and only create them as needed. This means that any objects that are not used due to the execution path of the code are not created, so the cost of creating unused dependencies is avoided.

Other performance measures taken by a DIC such as Symfony2’s include the compilation and caching of the config files so that this is avoided on each request and caching of the actual classes as well. I do not know the internals of Symfony2’s DIC to go into any real details about this though.

Conclusion

To get the benefits of Dependency Injection you need to keep pushing the creation of dependencies up through the code until it reaches the top. Once this is done a Dependency Injection Container helps to manage the resulting complicated configuration code as well providing performance benefits over directly creating the classes.

Disclaimer: As well as the usual issues of error checking and what have you in the code examples, there is the specific issue that having the ProductSaver directly invoke the email sending and logging is not really the best approach. It would instead be preferable to do something such as making the ProductSaver observable and registering logging and email notification as observers or using Symfony2’s event dispatcher.

Symfony2: Checking Coding Standards

Note: the coding standards used by Symfony2 have changed since this post was written, you can read more about this in my post Symfony2: Coding Standards Update

Coding standards are good, they are especially important on large projects with many collaborators such as Symfony2. Obviously very messy code with no consistency is a problem, it is difficult to read, making it hard to maintain.

There is not only one way to write well formatted code and not everyone agrees on which is the best way to format certain things to say the least. This means that it is important to not just write tidy code but code that is consistent with the code of everyone else involved in the project. So projects such as Symfony2 standardise on a particular set of coding standards which you should adhere to if you are contributing to the project or in Symfony2’s case writing third party bundles. You may also want to make sure that any code you write for an application based on Symfony2 meets the same standards.

The Symfony2 coding standard follows the Pear/ZendFramework standards with a few differences. You can read a detailed list of the standards in the contributing section of the documentation.

PHP_CodeSniffer

Whilst a great starting point trying to actually remember all that when coding will be difficult. Fortunately you can use the PHP_CodeSniffer tool to find any where in your code that does not meet the standards.

You can install PHP_CodeSniffer using Pear:

The Symfony2 coding standard is not included, you can obtain it from Git though, the README.md goes through how to install the custom standard.

So if you had a file with the following code in it:

You can then run PHP_CodeSniffer at the command line to get a report of any errors or warnings, against this file:

This outputs the following report:

You can also run PHP_CodeSniffer against directories rather than individual files.

Phing

As well as running PHPCodeSniffer manually you may want to run in from a build tool such Phing you can then run PHPCodeSniffer along with other tools such as PHPUnit, PHPDepend with one CLI command rather than having to run each separately. There is a built in Phing task for PHP_CodeSniffer that you can use for this. The following will provide a full report on my LimeThinkingSpring bundle:

If you also include in the build file other targets for other tests and a target that depends on them:

you can run them altogether with simple command:

If you prefer to use Ant for builds then it does not have a built in task but you can still use an Exec task to call PHP_codeSniffer:

Jenkins

As simple as it is to run the tests using Phing, you still need to remember to do it. If you are using a tool such as Jenkins for Continuous Integration then you can use it to run these sorts of tests automatically when you commit changes to version control.

There are instructions for setting up Hudson with Phing, Jenkins is a fork of Hudson so you will need to make some changes to the instructions. Whilst my preference is for Phing it is currently easier to set up Jenkins for PHP CI using Ant using Sebastian Bergmann’s excellent Template for Jenkins Jobs for PHP Projects.

The most useful way of integrating PHP_CodeSniffer into Jenkins is to have it output a checkstyle report. You can then use the checkstyle Jenkins plugin to display the results in the build report. This includes details of any errors and warnings. It also displays a graph of the number of errors and warnings across builds:

Example of Checkstyle graph in Jenkins

Eclipse Integration

As well as catching any errors by running PHPCodeSniffer against your code it is possible to integrate it into some IDEs to provide real time checking so you can see any violations as you code. Here I will look at implementing it in Eclipse. There is a plugin to integrate PHPCodeSniffer which is part of the PHP Tool Integration project, you can find more information and installation instructions here.

Again you will need to add in the Symfony2 standard, instructions for doing this are in the configuration section.

Now in Eclipse you will get immediate feedback on any coding standards violations. So our code from before will look like this:
Example of Coding Standards violation being highlighted in Eclipse

This allows you to correct any violations as you code rather than afterwards by running the PHP_CodeSniffer later.

Note: at the time of writing Symfony2 is at Release Candidate stage and moving towards a stable release so they are looking for bug fixes only and not Pull Requests with coding standards changes.