Peeling Back the Onion Architecture

Download the code for this article.

Updated 14-Oct-2011: I modified the code sample to include controller unit tests and improved the config and logging services.

I recently started a consulting project as an architect on an ASP.NET MVC application and quickly found myself immersed in the world of N* open source tools.  MVC (which stands for Model-View-Controller) lends itself to an Agile development methodology where TDD and BDD (Test-Driven and Behavior-Driven Development) are important components.  Writing applications that are testable requires that you separate business logic from presentation logic so that they can be independently tested.  This is a concept known as separation of concerns (SoC), which, in addition to testability, provides other benefits, such as greater application longevity and maintainability.  The life of an application is extended because loose coupling makes it easer to upgrade or replace components without affecting other parts of the system.

This is where the “Onion Architecture” comes in.  The term was first coined by Jeffery Palermo back in 2008 in a series of blog posts.  It is intended to provide some insurance against the evolution of technology that can make products obsolete not long after they are developed (the technical term is “deprecated”).  A classic example is Microsoft’s data access stack, which tends to change every few years (remember the demise of LINQ to SQL?).  What Jeffery proposed (although he’s not the first) is for the application to reference interfaces so that the concrete implementation can be supplied at runtime.  If, for example, the data access layer is represented by a number of repository interfaces, you can swap out LINQ to SQL with Entity Framework or NHibernate (or your favorite ORM) without breaking other parts of the application.  This same approach is used to decouple things like configuration and logging so they become replaceable components.

onion-arch

In this depiction, the “core” of the onion is the object model, which represents your domain. This layer would contain your POCO entities. Surrounding your domain entities are repository interfaces, which are in turn surrounded by service interfaces.  Representing your repositories and services as interfaces decouples consumers from concrete implementations, enabling you to swap one out for another without affecting consumers, such as client UI’s or tests.  The data access layer is represented in the outer layer as a set of repository classes which implement the repository interfaces.  Similarly the logging component implements a logging interface in the service interfaces layer.

onion-proj

Here is the project structure for a Visual Studio solution I created to demonstrate the Onion Architecture.  I inserted solution folders and aligned project and folder names for ease of use.  Infrastructure.Data uses NHibernate to implement repositories for ICategoryRepository and IProductRepository in Domain.Interfaces.  Infrastructure.Logging uses NLog to implement ILogging in Infrastructure.Interfaces.  The Web.Ui project has a ProductService class that implements IProductService in Services.Interfaces. (In a future post I will incorporate WCF into the project structure, but the Service implementation would go in a Service.Core project, with a Web.Services project for the service host.)

You may be asking, “How are concrete implementations of repositories and services created?” If components in the outer layer were to create instances directly, they would be tightly coupled to those implementations, defeating the whole purpose of the Onion Architecture and jeopardizing the application’s long-term viability.  The answer is Dependency Injection (also known as Inversion of Control, or IoC).  Components on the outer rim of the diagram have constructors that accept service or repository interfaces, and it’s the job of the DI framework to serve up a concrete instance, based on some initial configuration or setup.  For example, the ProductController class in the ASP.NET MVC application has a constructor that accepts an IProductService, which has methods to get categories and products.  The controller doesn’t care about how the interface is implemented and what API the data access component uses.


public class ProductController : Controller
{
    // Services will be injected
    private IProductService _productService;

    public ProductController(IProductService productService)
    {
        _productService = productService;
    }

    //
    // GET: /Product/

    public ActionResult Index()
    {
        // Get products
        var products = _productService.GetProducts

            (selectedCategoryId);

        // Rest of method follows ...
    }
}

There are a number of DI / IoC containers out there.  One of my favorites is Ninject, which can be added using the NuGet package manager and has an extension for ASP.NET MVC applications.  Installing the Ninject.MVC3 package places a bootstrapper class in the App_Start folder.  There is a private RegisterServices method where you can bind local service implementations and load Ninject modules.

private static void RegisterServices(IKernel kernel)
{
    // Bind local services
    kernel.Bind<IProductService>().To<ProductService>();

    // Add data and infrastructure modules
    var modules = new List<INinjectModule>
        {
            new RepositoryModule()
        };
    kernel.Load(modules);
}

The RepositoryModule class resides in a separate DependencyResolution assembly, which references the Infrastructure.Data assembly and binds IProductRepository to ProductResository.  The assembly containing the Ninject modules references the Data assembly, so that web client doesn’t have to, keeping the web client ignorant of the actual repository implementation.  Once the bindings are set up, Ninject serves up the appropriate instance wherever the interface is used.


public class RepositoryModule : NinjectModule
{
    public override void Load()
    {
        // Get config service
        var configService = Kernel.Get<IConfigService>();

        // Bind repositories
        Bind<IProductRepository>().To<ProductRepository>()
            .WithConstructorArgument("connectionString", 

            configService.NorthwindConnection);
    }
}

As you can see, dependency injection is the glue that holds everything together.  An integration test, for example, would also use the DI container to get instances of interface implementations, without having to reference assemblies containing those classes.

[TestFixture]
public class RepositoryTests
{
    // Ninject kernel
    private IKernel _ninjectKernel;

    public RepositoryTests()
    {
        // Init Ninject kernel
        _ninjectKernel = new StandardKernel(new RepositoryModule(), new LoggingModule());
    }

    [Test]
    public void Should_Get_All_Categories()
    {
        // Arrange
        var categoriesRep = _ninjectKernel.Get<ICategoryRepository>();

        // Act
        var categories = categoriesRep.GetCategories();

        // Assert
        Assert.That(categories != null);
        Assert.That(categories.Count() > 0);
    }
}

Unit tests would likely combine DI with a mocking tool, such as Moq, as shown here.

[TestFixture]
public class RepositoryTests
{
    // Ninject kernel
    private IKernel _ninjectKernel;

    public RepositoryTests()
    {
        // Init Ninject kernel
        _ninjectKernel = new StandardKernel();
    }

    [TestFixtureSetUp]
    public void FixtureSetup()
    {
        // Init categories
        var categories = new List<Category>
        {
            new Category { CategoryId = 1, CategoryName = "Beverages" },
            new Category { CategoryId = 2, CategoryName = "Condiments" },
            new Category { CategoryId = 1, CategoryName = "Confections" }
        };

        // Set up mock categories repository
        var mockCategoriesRep = new Mock<ICategoryRepository>();
        mockCategoriesRep.Setup(m => m.GetCategories()).Returns(categories);
        _ninjectKernel.Bind<ICategoryRepository>().ToConstant(mockCategories.Object);
    }

    [Test]
    public void Should_Get_All_Categories()
    {
        // Arrange
        var categoriesRep = _ninjectKernel.Get<ICategoryRepository>();

        // Act
        var categories = categoriesRep.GetCategories();

        // Assert
        Assert.That(categories != null);
        Assert.That(categories.Count() == 3);
    }
}

Jeffrey summarizes the key tenets of the Onion Architecture as follows:

    • The application is built around an independent object model.
    • Inner layers define interfaces; outer layers implement interfaces.
    • Direction of coupling is toward the center.
    • All application core code can be compiled and run separate from infrastructure.

The sample application (which you can download here) provides a reference architecture based on these principles.  To use it you’ll need to download our good old friend, the Northwind sample database.  While the Onion Architecture does not propose anything new in terms of object-oriented and domain-driven design patterns, it provides guidance on how to decouple infrastructure from business and presentation logic, without introducing too much complexity or requiring redundant code. Enjoy.

About Tony Sneed

Married with three children.
This entry was posted in Technical and tagged , , , . Bookmark the permalink.

24 Responses to Peeling Back the Onion Architecture

  1. Pingback: Peeling Back the Onion Architecture | Web, Microsoft, MS Access | Syngu

  2. Thank you, Tony, for a very insightful blog post.

    I found your blog – and this post – just in time when I was pondering about the architecture of a solution with multiple clients (ASP.NET MVC and Windows Phone). Using the above architecture, it should be no problem to integrate another client project. I was wondering, however, how you would centralize validation (using FluentValidation) and reuse view models across multiple clients. How would your solution structure adapt to that?

    I’m looking forward to your next post in this series!

  3. Tony Sneed says:

    Hi Marius,

    To share things like ViewModels across multiple clients, they should be placed in separate assemblies and referenced from those clients. The same would go for things like validation, whether with DataAnnotations or something like FluentValidation.

    In cases where you would want to de-couple the actual implementation, you would factor out an interface and have the consumer reference the assembly, using dependency injection to serve up the concrete implementation – which is what the Onion Architecture is all about. The interfaces are in a separate assembly do that they can be shared among multiple consumers, be they client apps (ASP.NET MVC or Silverlight) or a test harness (NUnit, MSTest).

    Hope this answers your question. :)

    Cheers,
    Tony

  4. Craig says:

    Had a look at your sample app, looks pretty good. There are a few things I do differently and wondering what you think.

    1. I put the mapping code (ie GetProductViewModel) in a separate class. Often this mapping code is pretty complicated for some views and it clutters up the controller. This class can then contain Sql/Linq that is specific for populating the ViewModel rather than putting that code is a server/repository where it will never be used again. Similar to this (not exactly) https://github.com/sharparchitecture/Sharp-Architecture-Cookbook/wiki/Using-Query-Objects

    2. Repositories only contain reusable queries. For example GetProductByCode. They don’t contain general queries for doing things like populating View Models, or else they end up with many queries, and end up as a bit of a query dumping ground.

    3. Persistence is done in a separate class, for example I might have a ProductUpdateCommand class to which I pass the ViewModel. This means controller just has a couple of lines in the Save methods like
    var errors = _productUpdateCommand.Execute(model);
    ModelState.AddErrors(errors);

    These differences are for the purpose of a) Keeping the controllers uncluttered with code, b) Keeping classes purpose clear (not doing everything in the one class).

    • Tony Sneed says:

      Glad you found the sample app helpful, and thanks for the input. The point that stands out for me is that repositories can get too cluttered with generic queries and CRUD operations. What I’ve seen that helps relieve this is to create a generic IRepository class that has the reusable CRUD ops there (such as GetEntityByKey, GetEntities, etc). Keeping that stuff abstracted away with an interface keeps the controllers free of data access code and loosely coupled. Again with the updates, the controllers do not have any code that actually saves entities — all of that is abstracted away. What you could do here, though, is implement the IUnitOfWork pattern for the saves, since those usually go across more than one repository. Check out the DDD book by Eric Evans.

      Cheers,
      Tony

  5. Jared says:

    Tony, thanks so much for the post – this is very helpful. I’m looking forward to diving into your sample project.

  6. Santosh says:

    How to integrate the application Services using WCF,Can you please let me know the Project Structure for the same and also will the interface and Service implementation be in the same projects?

    • Tony Sneed says:

      HI there, I’m going to do another post on integrating services into the onion architecture. However, it’s not hard to do. Interfaces stay in the same place. There would be a Services class lib that referenced the interfaces, and you would use DI to inject dependencies into the services (for ex, repositories) – I have a blog post on that. Then the services lib can be hosted either in the same web app as the asp-mvc project, or in a separate web project.

      Cheers,
      Tony

  7. Jared says:

    I am little confused on why the core doesn’t provide a concrete implementation for the Services classes. I would would think if you provide an interface, how it gets implemented might not change very much between implementations.

    It also seems that Onion Architecture encourages the developer to use anemic data models. Am I right about this? And if I am, why is that?

    Thanks for your help.
    Jared

  8. Tony Sneed says:

    You want to put services in a separate class lib so that they can be loaded into different WCF hosts (web, NT Service, etc). However, that’s just for WCF services. There can be other services that are not exposed via WCF, and you can put those pretty much where it make the most sense. For example, the ASP.NET MVC app can implement a service locally, or it could, as you suggest sit in Core.

    Not sure what you mean by anemic data models. Can you elaborate?

    Tony

    • Daniel says:

      Hi Tony,

      Thanks for a great post. I’m designing the architecture for a new web app and web service based on MVC and EF. One point I’m slightly confused about is the Service implementation. I see you have implemented ProductService which in DDD terminology appears to be an Application Service. This can be implemented as a class in an MVC project or exposed via WCF as you suggest. That all hangs together for me.

      So where do Domain Services belong in your code base? I believe the Onion Architecture calls for them to be part of the core and may contain at least some business logic, more than what DDD usually recommends (as others have pointed out). I like the idea of being able to use the entities as DTOs without generating DTOs and providing mapping etc. so a little more logic in the domain service doesn’t bother me too much. If you had to perform some validation say in the persistence of a new Product where would this validation live in your code base?

      Thanks,
      D.

  9. Jared says:

    Ah, that makes a lot more sense. I haven’t worked WCF outside of web services, but I can see the need to be flexible.

    I probably should have said anemic data models. Martin Fowler refers to them as an anti-pattern here: http://martinfowler.com/bliki/AnemicDomainModel.html. Instead of writing anemic domain models, he encourages developers to build domain specific business logic into domain objects themselves. Service layers are kept very thin. I tend to follow a similar path when I write code, because I feel it makes it easier to follow and maintain business logic over time.

    In your example and in some open source projects like Code Camp Server, its look the domain objects are kept pretty bare while the services carry out a lot of the business logic. Is this by design, and if it is why? To further reduce coupling?

    Thanks again for your help.

    Jared

  10. Hi Jared,

    Great question, and thanks for the link to the Fowler article. I think the main reason for not having behavior in the domain entities is the desire to use them as DTO’s (Data Transfer Objects) rather than true domain models. Rich clients (SL, WPF) would consume DTO’s via a WCF service, in which case any behavior would be irrelevant. So the anemic entities result from turning them into DTO’s instead of actual domain entities. Of course, this is not necessarily ideal. Creating a rich domain model should be done separately from DTO’s. But this results in a bunch of code needed to translate between domain entities and DTO’s. I think many devs combine then to reduce entity redundancy.

    I don’t think one approach is right and the other wrong – it all depends on the complexity of the system you are developing and whether it involves a WCF services layer. With ASP.NET MVC there usually is not a WCF component, while with SL/WPF there usually is.

    Anyways, that’s may take on it.

    Cheers,
    Tony

    • Jared says:

      Thanks for answering my questions. I just recently started looking at Onion Architecture and DDD. I’m very excited about what I see so far. As always, the best part of our industry is that there is always something new to learn:).

      Jared

  11. Took me time to learn all of the comments, however I really enjoyed the article. It proved to be very useful to me and I’m certain to all of the commenters right here! It’s all the time nice when you cannot solely learn, but additionally engaged! I’m certain you had joy scripting this article. Anyway, in my language, there aren’t a lot good source like this.
    http://www.idoc-tlc.com/idoc/index.aspx

  12. Bewnet says:

    Hello Tony,
    I am trying to use Entity Framework for DAL in (AppArch.Infrastructure.Data). EF generated model that matches the model i have in Domain.Entities project. Let’s say there was already two tables called Categories and Products and now EF has generated a corresponding Model. How is the ICategoryRepository / IProductRepository implemented?
    I Suppose those two interfaces will be implemented in AppArch.Infrastructure.Data project.
    Now, you have a model already defined under Domain.Entities where the repository interface is looking for and you have a model generated by EF. Can you please how to implement say IProductRepository? It’s a little confusing to me.

    Thanks,
    Bewnet

    • Tony Sneed says:

      The idea here is to use POCO classes (Plain Old CLR Objects) instead of EF generated classes. There is a T4 template that generates POCO classes based on the Entity Framework Data Model and then sets the generation strategy to remove the generated classes and use the POCO’s instead.

      You can implement the repository interfaces however you wish, according to the needs of your application, but they would return and/or accept the POCO entities. You implement the interfaces in the Data project simply by adding repository classes and inserting code to interact with the object context. The sample project should show an example of doing this.

      Cheers,
      Tony

      • Bewnet says:

        Thanks a lot Tony for both posting this useful blog and your answer as well!
        That said, i have one more question – Even when you generate those POCO classes using T4 template:
        1. You need to have one class – to take advantage of entity framework’s context management and that class has to inherit from ObjectContect – this is dependency.
        2. Can we have those POCO classes on their own project? If i still have them in the same project, that leaves the core of the entire application dependent on EF which i think is something Onion Arch is trying to solve.
        I might be asking obvious questions but, i need your expertise on this.

        Thanks again!
        Bewnet

  13. Bewnet says:

    I got it now, 4.1 has that support. Please ignore my question.

  14. Excellent explanation… I am currently working as an architect and implementing Onion architecture and was in a need to quickly explain to developers how everything works… I used your blog post as one of the best references that clearly explains the concept of the Onion architecture ;) !

  15. Jared says:

    Tony, thanks again for putting this together. With the help of some of other developers at my company, we put together a POC and presentation on Onion Architecture. Your code was instrumental for helping us to get started. You can check out the slides from my presentation here: http://jared-jenkins.com/blog/onion-architecture-presentation/.

    Cheers,
    Jared

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s