Friday, October 5, 2012

Service Locator vs Dependency Injection

We recently introduced IoC container (Autofac) in our project. And we liked it, we liked it so much that we have started using in more than a few places now. But soon I realized a trap we are falling into, the trap of "Service Locator" pattern. Before I get into nitty-gritty of this trap, let's briefly talk about service locator vs dependency injection

There are two patterns to implement inversion of control. The code snippet below shows the most common and easy pattern - the service locator

public class CreateCusutomerCommand
    private Customer customer;

    public CreateCusutomerCommand(Customer customer)
        this.customer = customer;

    public void Execute()
        var customerPersister = Container.Resolve<IPersistCustomer>();

Here we are using a static Container instance to resolve an instance of IPersistCustomer interface. This pattern slightly modified in the code below become a dependency injection pattern.

public class CreateCusutomerCommand
    private Customer customer;
private IPersistCustomer customerPersister; public CreateCusutomerCommand(Customer customer, IPersistCustomer customerPersister) { this.customer = customer; this.customerPersister = customerPersister; } public void Execute() { customerPersister.Persist(customer); } }

Here we are not using a container to resolve IPersistContainer, instead, we are accepting an instance through constructor. We are declaring IPersistContainer as a dependency and enforcing it be injected through constructor. So why am I saying that service locator pattern is a trap? There are a few reasons that I have experienced myself

  1. The container API (call to container.Resolve<T>()) is referenced all over the places. Container becomes sticky dependency that is difficult to get rid of. 
  2. If you are doing TDD and you want to write tests for CreateCustomerCommand class in the first example then your tests must have the knowledge of the container and what types are registered in the container. 
  3. Tests may have a need to change the behaviour offered by the registered types in the container. 
  4. The only way to do that would be create proxy types and register them again from the tests. 
  5. One of the above would lead to your test project being dependent on container assemblies
If you use dependency injection pattern and wire it up properly (e.g. If I'm building an MVC project and using Autofac, I would use Autofac MVC integration and delegate the controller creation to autofac) then you would rarely need to resolve a type yourself manually. The container API calls are not littered in you code base. 

The most interesting part comes when you are writing tests. It's very easy to write tests against class in the second example. I know that I need to pass in some implementation of IPersistCustomer interface. I can just mock it and there is no other setup required. 
Life has become so easy with this change.

Saturday, August 25, 2012

Analogy - Single Responsibility Principle

"Single Responsibility Principle (SRP)" is one of those software design principles which are difficult to explain to a junior developer. And subjective-ness in the implementation makes it even more difficult. I tend to use analogies from real life to explain software design principles. Sometimes they  work, other times they don't. But in my small little world, they do help me remember these difficult software design principles. So let's build an analogy between SRP and restaurants.

In most restaurants, a waiter would help you choose food and take your order. Some other restaurant staff would serve you food that you ordered. And in the end, when you are done, some other staff would clear your table. This arrangement makes the service very effective and efficient. And this is a direct result of one person specializing in only one thing. Waiter specializes in taking orders and handing them over to kitchen. Some staff specialize in delivering food to tables. And some staff specialize in clearing the table. Because they are specializing in one thing (single responsibility), their job is simple and they are super efficient in completing their job.

If you correlate this to software design, then it's clear how a class that does only one thing is super efficient at doing what it does. Because the class is doing only one thing, you end up writing less code in a class, thus increasing the chances of writing code that is clean, modular etc.

There is an important link between SRP and service efficiency in restaurants. The interaction between different staff memebrs. You get a good service experience at restaurant because the interaction between various staff members is not broken. There is another hidden software design principle there. But that is for some other post.