Software Alchemist

I am constantly seeking answers and ways of transforming desires into reality by coding

Interface Injection and Symfony2 DIC

| Comments

During the preparation for my recent talk, I had to refresh my knowledge of the theoretical side of Dependency Injection, since I was using it for a while, but found myself not knowing some of the terminology. I found “Dependency Injection” article on Wikipedia.org to very fulfilling. One thing that caught my attention specifically was the types of Dependency Injection, and Wikipedia defines three of them:

  1. Interface Injection (type 1)
  2. Setter Injection (type 2)
  3. Constructor Injection (type 3)

While the last two types are what I use in day-to-day coding, the first type was rather unfamiliar. So I looked it up, and Martin Fowler had a good definition.

Interface Injection - is a technique to define and use interfaces for the injection (Martin Fowler)

Examples on Martin Fowler’s blog are quite complicated and would be more confusing to PHP developers than beneficial. But the general idea, which resonates with my point on Composition over Inheritance, is very simple - allow certain service to be injected into other services, that implement a common interface.

Example use case:

I have an interface ContainerAware, and I want all services that implement that interface to receive instance of Container through its ->setContainer() method. This would be very useful in Symfony2, if you were defining controllers as services and needed container. Right now there is a hard-coded instanceof check deep inside Symfony2’s controller instantiation process, that sets the container on ContainterAware controllers. If Symfony2 DIC component supported the first type of Dependency Injection (Interface Injection), this would not be necessary, and many more interfaces could be defined, removing the verbosity from configuration.

Enough talking, show us some code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?php

namespace Company\ApplicationBundle\Controller;

use Symfony\Component\DependencyInjection\Container;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;

class SimpleController implements ContainerAwareInterface
{
    /**
     * @var Symfony\Component\DependencyInjection\Container
     */
    private $container;

    /**
     * @param Symfony\Component\DependencyInjection\Container $container
     */
    public function setContainer(Container $container)
    {
        $this->container = $container;
    }
    //...
}

note Actually any controller that extends Symfony\Bundle\FrameworkBundle\Controller\Controller implements ContainerAwareInterface, as it inherits it from parent, but for the purposes of this example, I chose code that shows everything explicitly.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?xml version="1.0" ?>

<container xmlns="http://www.symfony-project.org/schema/dic/services"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.symfony-project.org/schema/dic/services http://www.symfony-project.org/schema/dic/services/services-1.0.xsd">

    <interfaces>
        <interface class="Symfony\Component\DependencyInjection\ContainerAwareInterface">
            <call method="setContainer">
                <argument type="service" id="container" />
            </call>
        </interface>
    </interfaces>
</container>

note There is no way to define Interface Injectors in Symfony2 yet, as it doesn’t support the first type of Dependency Injection. This is my proposed way of configuring interface injectors in xml.

All we would need to do now is register our controller within the Symfony2’s DIC component without defining the method call explicitly, since the DIC would know to apply interface injectors to all services, requiring them:

1
2
3
4
5
6
7
8
9
10
<?xml version="1.0" ?>

<container xmlns="http://www.symfony-project.org/schema/dic/services"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.symfony-project.org/schema/dic/services http://www.symfony-project.org/schema/dic/services/services-1.0.xsd">

    <services>
        <service id="index_controller" class="Company\ApplicationBundle\Controller\SimpleController" />
    </services>
</container>

The described approach makes DIC configurations take less space to achieve the same result. Because if you’re implementing a certain interface that defines rules for injection of other services, you usually need to re-use the same services across all instances of the interface, but have to explicitly define the injections every time.

I can see some of the Symfony2s built-in services benefiting from Interface Injection:

I definitely have a lot more classes, that can benefit from it in my problem domain.

So with all that in mind I spent last evening putting together my own implementation of Interface Injection in Symfony2’s DIC component, and you can find it in my Symfony2 for on github.

Please comment with suggestions and/or feedback, very interested in what you think.

Happy Coding!

Symfony2 Controller Testing

| Comments

Having a rich background in different MVC frameworks, one thing that was always unclear was how to test controllers. I think the main reason it wasn’t obvious is because controllers had always been sort of a black magic element in frameworks. There were too many conventions on where on the file system controller should be located, what dependencies it should have knowledge of and those dependencies were always wired with the controller the hard way (view layer).

Environment like that assumes no easy way for controller testing, since you can’t instantiate a controller and some of its primary dependencies to test the interaction - you have to boot the whole framework and write functional tests.

Because of how complicated that process is, people usually don’t unit-test controllers, functional test is the maximum you can get, but usually you don’t get anything at all.

Symfony2 changes that completely.

Initially Symfony2 framework had only conventional controller loading approach. Controller instance still was very lightweight and was not required to extend some parent class in order to work. If your controllers implemented ContainerAware interface, you would have the DIC (dependency injection container) inserted using ContainerAware::setContainer() method, which you could then use to access any service that you registered in DIC.

The proposed method of testing controllers at the time was a black box testing approach, where you test full requests to your application and assert their output like so:

1
2
3
4
5
6
7
8
9
<?php

$client = $this->createClient();
$client->request('GET', '/index');

$response = $client->getResponse();

$this->assertEquals(200, $response->getStatusCode());
$this->assertRegExp('/<h1>My Cool Website<\/h1>/', $response->getContent());

Although this method is easy to read and understand, there are a couple of drawbacks:

  • To execute the test, we need to bootstrap the Kernel
  • This test can only assert response body, which makes it fragile to design changes
  • As a result of all of the above, it runs much slower and does much more than it needs to

In ideal world, I would want to test controller interaction with other services in my application, like so:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<?php

namespace Company\ApplicationBundle\Tests\Controller;

use Company\ApplicationBundle\Controller\IndexController;

class IndexControllerTest extends \PHPUnit_Framework_TestCase
{
    //...
    public function testIndexAction()
    {
        $templating = $this->getMockTemplating();
        $templating->expects($this->once())
            ->method('render')
            ->with('ApplicationBundle:Index:index')
            ->will($this->returnValue('success'))
        ;

        $controller = new IndexController();
        $controller->setTemplating($templating);

        $this->assertEquals('success', $controller->indexAction());
    }

    private function getMockTemplating()
    {
        return $this->getMock('Symfony\Bundle\FrameworkBundle\Templating\Engine', array(), array(), '', false, false);
    }

}

note Controller is just a POPO (plain old PHP object) without any base class that it needs to extend. Symfony2 doesn’t need anything but the class itself for controller to work.

note read more about mock object framework in PHPUnit

Well, the good news is that Symfony2 allows that. Now all your controllers can be services. The old, conventional approach is still supported and is irreplaceable for small application controllers, with no need for unit-testing.

To make the above example controller correctly interact with Symfony2 and work as expected, we need the following.

Create controller class:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<?php

namespace Company\ApplicationBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Templating\Engine;

class IndexController
{
    /**
     * @var Symfony\Bundle\FrameworkBundle\Templating\Engine
     */
    private $templating;

    /**
     * @param Symfony\Bundle\FrameworkBundle\Templating\Engine $templating
     */
    public function setTemplating(Engine $templating)
    {
        $this->templating = $templating;
    }

    /**
     * @return Symfony\Component\HttpFoundation\Response
     */
    public function indexAction()
    {
        return $this->templating->render('ApplicationBundle:Index:index');
    }
}

Create DIC configuration, using the following xml:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?xml version="1.0" ?>

<container xmlns="http://www.symfony-project.org/schema/dic/services"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.symfony-project.org/schema/dic/services http://www.symfony-project.org/schema/dic/services/services-1.0.xsd">

    <services>
        <service id="index_controller" class="Company\ApplicationBundle\Controller\IndexController">
            <call method="setTemplating" />
                <argument type="service" id="templating" />
            </call>
        </service>
    </services>
</container>

Create routing configuration:

1
2
3
4
5
6
7
8
9
10
<?xml version="1.0" encoding="UTF-8" ?>

<routes xmlns="http://www.symfony-project.org/schema/routing"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.symfony-project.org/schema/routing http://www.symfony-project.org/schema/routing/routing-1.0.xsd">

    <route id="index" pattern="/index">
        <default key="_controller">index_controller:indexAction</default>
    </route>
</routes>

note in the above example, we used service_id:action instead of the regular BundleBundle:Controller:action (without the “Action” suffix)

After all of the above is done, we need to inform Symfony2 of our services. To avoid creating a new Dependency Injection extension and creating configuration file entry, we can register our services directly:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php

namespace Company\ApplicationBundle;

use Symfony\Component\HttpKernel\Bundle\Bundle;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;

class ApplicationBundle extends Bundle {
    public function registerExtensions(ContainerBuilder $container) {
        parent::registerExtensions($container);

        // register controllers
        $loader = new XmlFileLoader($container);
        $loader->load(__DIR__.'/Resources/config/controllers.xml');
    }
}

note the above technique was originally invented by Kris Wallsmith in a project we were working on at OpenSky.

Now you’re ready to go. You need to include your bundle level routing file in the application level routing configuration, create the Index directory. The final file structure should look something like this:

Company
| - ApplicationBundle
|   | - Controller
|   |   | - IndexController.php
|   | - Resources
|   |   | - config
|   |   |   | - controller_routing.xml
|   |   |   | - controllers.xml
|   |   | - views
|   |   |   | - Index
|   |   |   |    | - index.php
|   | - ApplicationBundle.php

After all the above steps are completed, you can try it from the browser, by going to:

http://your_application/your_front_controller.php/index

Happy Coding!

NodeJS + MongoDB = TinyURL

| Comments

Last week I started playing with NodeJS

NodeJS is an evented IO for V8 JavaScript. It uses asynchronous processing for all operations. If you want to open file, you pass in the callback function as argument to file open function, which then gets executed when the file is opened and available.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// we will use sys.log for logging
var sys = require('sys');
// send open file command, with callback
fs.open('path/to/file.js', 'w', 0777, function(err, fd) {
  //throw error, if there was one
  if (err) throw err;
  // send write command with opened file, content, starting point, encoding and callback
  fs.write(fd, 'Hello World!', 0, 'utf8', function (err, written) {
    //throw error, if there was one
    if (err) throw err;
    // after successful file write, log number of bytes written
    sys.log('Success! Wrote ' + written + ' bytes');
  });
});

The aforementioned approach leads a much higher number of requests with a much less execution and, most importantly, wait times. And since its all JavaScript, we’re not surprised, because that is how JavaScript essentially works in the browser window. Think about it, the browser needs to re-draw its ui every time you a change occurs, staying responsive to user interactions at the same time, the only way to do this is by executing event/callback loops.

So where would you use NodeJS. In real-time data processing. The perfect example of such usage is HummingBird, which uses NodeJS and MongoDB for producing real-time usage analytics and statistics for Gilt Groupe website, you can fork it on github.

Now I was installing NodeJS under Cygwin which was a bit tricky at first (the python version that comes with Cygwin needed to be “rebased”).

To run a rebase command on Windows, you need to close all Cygwin processes, open C:\cygwin\bin\ash.exe, and run:

1
/usr/bin/rebaseall

In order to compile NodeJS, you would need the following: * python * OpenSSL * Make * libg++ compiler * NodeJS source

After all the above dependencies were installed, cd /path/to/your/nodejs, and run:

1
2
3
./configure
make
make install

To run tests, execute:

1
make test

Now that you have NodeJS installed, the first step is to create a “Hello World!” application, to do this, create example.js with the following content:

1
2
3
4
5
6
7
8
9
// http package is used to create http servers
var http = require('http');
// create server that will write string 'Hello World' with a new line on every request to ip 127.0.0.1, port 8124
http.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end('Hello World\n');
}).listen(8124, "127.0.0.1");
// Log message after createServer is successfully sent
console.log('Server running at //127.0.0.1:8124/');

When the file is created, go to the directory its located and run:

1
node example.js

If everything is correct, you should see something like this:

1
2
$ node example.js
Server running at http://127.0.0.1:8124/

I used NodeJS and MongoDB to create a simple TinyURL application - you give it the url, it shortens it. The shortening algorithm is simple, each new url is assigned an auto-incrementing numeric index, which is then base 36 encoded to produce url key. Whenever url key is received, its base 36 decoded to get the numeric index, which is used to get the target location and send a 301 redirect header.

The application is very simple and lacks any kind of validation or error handling. The source code is open and available on github. Please feel free to fork it and use it. Feedback is much appreciated.