The N-layer myth and basic Dependency Injection

Dividing an application in N layers is considered a standard and a best practice. It is often thought that this automatically creates a decoupled application. However, just creating layers doesn’t make your code loosely coupled.

A typical N-layer application

Let’s take a simple layered application:

image

1. A typical N-layer architecture

In the above image you can see how the application is structured. The responsibilities for every layer are:

  • UI layer: This can be a WPF-app, a console-app, a web application, etc. It defines the user interface and no logic should be in this layer.
  • Domain Layer: It coordinates the interactions between UI, Model and DAL. It includes classes such as TaskService.
  • DAL: Responsible for saving and retrieving stored instances. A typical class would be a TaskRepository.
  • Model: A layer that spans all three layers. This usually consists of POCO-objects. The Task-class is an example.

One might think that separating the application into these layers guarantees loose coupling. In a few moments I’ll show you why that’s not necessarily true. First, let’s look at how these layers are usually tied together, from the bottom up:

Model

This layer holds the basic entities. This is the Task-entity, a simple POCO-class:

public class Task
{
    public int ID {get; set;}
    public string Name { get; set; }
    public string Description { get; set; }
    public DateTime DueDate { get; set; }
}

DAL

In the Data Access Layer typically there’s a repository class which allows access to the underlying data store. In this example, I will be using Entity Framework. The actual technology is not important, you could swap it out with whatever data storage technique you’re using. I chose Entity Framework because it makes the code samples very concise. The repository has two methods: one to retrieve a Task by ID and another one which accepts an arbitrary where-clause.

public class TaskRepository : DbContext
{
    DbSet<Task> Tasks { get; set; }

    public Task find(int ID) {
        return Tasks.Find(ID);
    }

    public IEnumerable<Task> find(Func<Task, bool> where) {
        return Tasks.Where(where);
    }
}

Domain

The domain ties together all the other layers. For the tasks we have a TaskService. This class exposes a method to retrieve all Tasks that are due today:

public class TaskService
{
    private TaskRepository repo;
    public TaskService()
    {
        repo = new TaskRepository();
    }
    public List<Task> GetAllDueTasks()
    {
        return repo.find(task => task.DueDate.Date == DateTime.Today).ToList();
    }
}

UI Layer

For the UI layer I chose an ASP.NET MVC application. I chose this because it makes the example represent a real-world scenario more closely. I will not enter into detail on how MVC works, I will only show you the controller part. If you don’t know MVC, for now you can just assume that the controller handles an HTTP-request. Let’s see what the controller does in order to visualize the tasks that are due today:

public class TaskController : Controller
{
    public ActionResult DueTasks()
    {
        TaskService service = new TaskService();
        List<Task> duetasks = service.GetAllDueTasks();
        return View(duetasks);
    }
}

Result

The above structure is very typical and by some considered a best practice. However, there are a few problems. Let’s take a look at figure 1 again and examine the dependency graph. You can see that all the dependencies point downward. Now, let’s see whether the current dependency graph is desirable.

One of the principles of loose coupling is that you need to be able to use each component in isolation. Is this possible for all our components?
Certainly, you would need to develop alternatives for their dependencies, but this should be doable without modifying the existing component. So let’s take a look at each component:

  • User Interface: With the current dependency graph, it certainly is possible to swap out the UI for another one. We just create a new project (WPF, Console, …), add references to Domain and Model and we are good to go. We didn’t need to modify existing code. So far, the dependency graph is OK.
  • Domain and Model: Swapping out these layers doesn’t really make sense. Since it’s the core of the project, swapping it out would basically mean creating a new project.
  • DAL: Replacing a DAL is typically why people advocate loose coupling. (“What if need to switch Database providers?”) Although this usually doesn’t happen, it still is a good practice to decouple the Domain from the DAL. If we remove the DAL from the solution, we will run into a problem. The problem is that our Domain-layer has a hard reference to our TaskRepository. If we want to swap out the DAL, we’ll have to modify the Domain-layer.

N-layer application with basic Dependency Injection

Ideally, what we want is that the domain-layer and the model-layer have no hard dependencies. They should be able to use external facilities, but they should have no knowledge of how those facilities handle requests, they should only know what they do.

This is a basic example of a more desirable dependency graph:

image

2. Inverted dependency graph

As you can see, there’s a slight but important difference: the dependency between the Domain and the DAL has been inverted. Looking at this graph, you can see that now you could swap out the DAL without touching the domain layer.

Now how can we achieve this graph?

Implementing the graph

Implementing the graph is quite easy:

  • Remove the reference from Domain to DAL
  • Create a reference from DAL to domain

This will cause compiler errors of course. The TaskService has a reference to TaskRepository but since the domain has no reference to the DAL, we receive a compiler error. We need to invert the dependency.

Inverting the dependency

To invert the dependency we will execute the following steps:

  1. Create an interface which describes the public interface of a repository
  2. Let the TaskRepository implement this interface
  3. Make sure TaskService references only the Interface
  4. Pass an object that implements the IRepository interface to the TaskService

Since we still need to be able to access the repository, we need to define an Interface in the Domain-layer which defines what a Repository can do:

public interface ITaskRepository
{
    Task find(int ID);
    IEnumerable<Task> find(Func<Task, bool> where)
}

Now we can modify the TaskRepository to implement this Interface:

public class TaskRepository : DbContext, ITaskRepository
{
    DbSet<Task> Tasks { get; set; }

    public Task find(int ID) {
        return Tasks.Find(ID);
    }

    public IEnumerable<Task> find(Func<Task, bool> where)
    {
        return Tasks.Where(where);
    }
}

TaskService had a hard reference to the TaskRepository. Let’s remove this dependency and replace it with the interface:

public class TaskService
{
    private ITaskRepository repo;
    public TaskService(ITaskRepository repository)
    {
        repo = repository;
    }
    public List<Task> GetAllDueTasks()
    {
        return repo.find(task => task.DueDate.Date == DateTime.Today).ToList();
    }
}

Now we are passing an object into the constructor, which must implement the ITaskRepository interface. This is known as Constructor Injection. This is necessary because we don’t want a reference to any specific repository.

This of course affects the UI layer, because now the TaskService does not have a default constructor anymore. To overcome this problem, let’s apply the same steps:

Create an interface:

public interface ITaskService
{
    List<Task> GetAllDueTasks();
}

Inject it into the constructor of the controller:

public class TaskController : Controller
{
    private ITaskService service;
    public TaskController(ITaskService taskservice)
    {
        service = taskservice;
    }
    public ActionResult DueTasks()
    {
        List<Task> duetasks = service.GetAllDueTasks();
        return View(duetasks);
    }
}

Now, the TaskRepository, the TaskService and the TaskController are completely decoupled from each other and only depend on interfaces.

Looking at the current state of the code, you might ask what the real benefit is. After all, there’s still a dependency on the TaskRepository when we want to construct the TaskController, we just moved it to the top of the application.

The benefit is exactly this, instead of having implicit dependencies in the entire application we can now push all the dependencies into one single place and manage them all from a centralized location. This location is usually referred to as the Composition Root. Thinking in terms of the Single Responsibility Principle (every class should have a single responsibility), you could say that we moved the responsibility for managing their dependencies from the TaskController  and the TaskService to another, dedicated class.

Apart from that, we’re also enabling unit tests, we can now create fakes and pass them to the TaskController or the TaskService and test them in isolation.

Implementing the composition root

With everything decoupled, we do need a way of coupling these items at runtime. At runtime, an interface doesn’t do anything for you, so we need concrete implementations.

First I will show a simple (hard coded) implementation.

In this case, since we’re using ASP.NET MVC as the UI application, the construction of the controller will be handled by the framework itself. Using the default configuration, MVC will look for a controller with the name specified in the URL like this:

/{controller/{action}

This means that accessing the URL /Task/DueTasks will execute the method we specified. By default, it will try to use the default constructor. In our case, there isn’t any default available and this will fail. To solve this, we need to plug into the framework by creating a new ControllerFactory:

public class MyControllerFact : DefaultControllerFactory
{
    public override IController CreateController(System.Web.Routing.RequestContext requestContext, string controllerName)
    {
        if (controllerName == "Task")
        {
            return new TaskController(new TaskService(new TaskRepository()));
        }
        else{

            return null;
        }
    }
}

The framework already helps us by parsing the URL and passing the necessary information. Then, instead of letting it handle the construction, we plug in our own implementation. MVC gives us the name of the controller it wants and then lets us decide how we want to construct it. The given implementation is a very crude one and should not be used in a real-world scenario. I’m showing it here so you can see that the dependencies are resolved in a single place. This is the Composition Root.

For completeness sake,I’m also showing you how to plug this class into the MVC framework. You need to register it inside the Application_Start event in the global.asax-file:

protected void Application_Start()
{
    ControllerBuilder.Current.SetControllerFactory(new MyControllerFact());
}

As mentioned before, the benefit is that we are moving the burden of managing dependencies from the classes inside the application towards a centralized class. Replacing the DAL now only requires us to create a new DAL and modify the Composition Root. In this small example, the benefits may not be that obvious, but that’s because we only have a few classes. If you extrapolate this to a complete application, the benefits get a lot more obvious.

Using a DI container

The implementation that I showed in the previous section is admittedly not a very good one. It means that for every controller and dependency you add, you’d have to modify the MyControllerFact, which is not a very maintainable solution. Therefore, I will show you an implementation with a DI Container. A DI Container is a reusable component that provides dependency functionality. There are two steps to using a container:

  • Configuring the container
  • Using the container to resolve dependencies

In the next example I’m going to use the Ninject DI Container. If you want to use a different container you will need to look up the specific API.

Configuring the container

In the configuration step, you basically tell the container what object to construct when asked for a specific interface:

IKernel container = new StandardKernel();
container.Bind<ITaskRepository>().To<TaskRepository>();
container.Bind<ITaskService>().To<TaskService>();
container.Bind<TaskController>().ToSelf();

Here you can see that we tell the container which types it needs to construct when asked for a certain interface.

Using the container to resolve dependencies

Now we can adapt the MyControllerFact to use the container to create controllers:

public class ControllerFact : DefaultControllerFactory
{
    public override IController CreateController(System.Web.Routing.RequestContext requestContext, string controllerName)
    {
        Type controllertype = this.GetControllerType(requestContext, controllerName);
        return (IController)container.Get(controllertype);
    }
}

Other features of DI Containers

Apart from resolving dependencies, a DI Container offers a lot more features. Which features are supported depends on the container you choose:

  • Lifetime management: when configuring the container, you can specify whether to create a new instance or to return the same instance every time. Different containers can have more possibilities (such as one per request or custom lifetimes)
  • Configuration: In this example I showed how to configure the container with the Fluent API. This requires you to recompile the application if you want change the configuration. Some DI containers offer XML configuration or even a combination of both. That way you don’t need to recompile if you want to swap out certain modules.
  • Auto-registration: Closely related to configuration is auto-registration. In the previous example we had to explicitly tell the container which concrete implementation goes with which interface. Auto-registration allows you to do this mapping with convention over configuration. If there’s no concrete class bound, then check if we can find a class that follows a set of conventions.
  • Interception: Since the DI container knows the interfaces, it could possibly wrap the interfaces and intercept all the calls. This can be useful for solving cross-cutting concerns such as logging and security. The concept is the same as an AOP (Aspect Oriented Programming) framework such as PostSharp. The difference is that with a DI container this is a dynamic feature, whereas PostSharp uses post-compilation steps. Interception with DI containers is much more flexible, because it allows you to modify cross cutting concerns at runtime or even through configuration.

Conclusion

Even when using distinct layers it’s very easy to fall into the trap of writing tightly coupled code. Furthermore, the latest IDE’s (such as Visual Studio) are really excellent. This also means that they enable you to create dependencies very easily. In order to avoid this, you should always consider that you’re creating a hard reference when performing either one of the following two actions:

  • Using the new-keyword to create an instance
  • Adding a reference to another library

As a mental rule, I always force myself to think whether it’s really necessary and if there’s an alternative when I want to do either of these actions.

Note: the ideas expressed in this post are loosely based on the introduction from the book “Dependency Injection in .NET” by Mark Seemann. If you want to learn more about Dependency Injection, I would recommend you read this book. It is an amazing source of information, well written and it covers the ins and outs of Dependency Injection as well as several DI Containers.

  • pavan

    Good information.. Thanx.!

  • Weixiao

    Very nice article, I got the key points to introduce these concepts to newbie, thank you.

  • throwexception

    For this to work, don’t you have to add a reference to the DAL in the UI layer? How else can you bind the concrete type TaskRepository to the ITaskRepository?

    • http://www.kenneth-truyers.net/ Kennethtruyers

      Yes, correct. But that’s OK, it’s not like your views are depending on your data-access, it’s your application that’s depending on your DAL, which is fine, because it does actually depend on it. If it is depending on your DAL through your domain it’s just less explicit.

      • Michael S

        When I first saw this architecture in practice, I looked for an article like this. I have used this architecture for a few years, and really like it. One company I was with needed to create mobile site, and with this in place it was a matter of just adding another project that could leverage that services class layer. I proposed this for a new site and was dinged because the DI takes place in the MVC app which means you have to reference the DAL. I like your answer. I am curious if you have used this under different physical deployment scenarios. I have 2 deployment scenarios I am looking at. One is entirely behind a firewall so no issue there. Second scenario is where the ui may have to reside in a DMZ. My prototype now has a RESTful API to wrap the provider layer. I can deploy the same app inside/outside the DMZ. The app running in the DMZ can be configured to hit the RESTful service. Thoughts?

        • http://www.kenneth-truyers.net/ Kennethtruyers

          If your MVC app talks to an abstraction of your service class, it shouldn’t be a problem.

          Say you have an IService-class which your MVC app uses.

          When you deploy your app onto two physical tiers, you can create a ServiceProxy that implements that interface, but instead of calling the actual code, it calls the REST-service. In your composition root, you’d then wire your MVC controller to the proxy.

          When you deploy your app on a single tier, you wire the MVC controllers directly to the service class (which implements the same interface). Obviously under different physical deployment scenarios you need to alter your wiring, but that’s exactly what DI is very good for.

          As for the DI taking place inside the MVC app, in your case you’d have to move that outside of your MVC app, because you obviously do not want a direct dependency on your DAL or Domain layer.

  • David Troyer

    Is it okay for the POCO class (Task) to be coupled across all layers?

    • http://www.kenneth-truyers.net/ Kennethtruyers

      When you have all your references pointing down, there’s really no other solution than that. However, when your references all point to your domain, your Task-class can be part of your domain and then your data and UI layer all just depend on that, which is fine.

      In a CRUD type of application, this probably fine. If you move away from CRUD (typically more complex applications) and move to a more DDD, CQRS-style of application, you probably move away from POCO-classes and put behavior on those classes. In that case it might be a good idea to make them internal.

      • David Troyer

        If I put the Task POCO in the Domain layer, the inverted dependency graph picture would no longer show the relationship of the UI and DAL to the Model? As far as DDD and CQRS, I am reading your Introduction to DDD, CQRS, and Event Sourcing blog. Thx!

  • svenn

    Very good article!
    Thankyou

  • svenn

    Very good article!
    Thankyou