Project Architecture

by October 4, 2008 11:13 AM

I read and loved the series of posts called The Onion Architecture by Jeffrey Palermo. As he put it:

The main premise is that it controls coupling. The fundamental rule is that all code can depend on layers more central, but code cannot depend on layers further out from the core. In other words, all coupling is toward the center. This architecture is unashamedly biased toward object-oriented programming, and it puts objects before all others.

Sweet! Everything a good architecture astronaut such as myself would love. Well, I thought I’d see how well it performed down here where the oxygen is breathable. I’m currently working on a side project for a buddy at work and thought that it would be the perfect test bed as there isn’t a hard deadline for it.

So, here is our “Agenda Management System”. Basically it’s going to expose city council voting records in new and interesting ways.

VS Solution

This is the actual solution. Two of the projects you see exist in every project I create no matter what the chosen architecture is: _build and Tests. _build contains deploy scripts and all of my project dependencies that aren’t “out of the box”. The Tests project contains all of my unit tests (there aren’t many – yes, I suck at this still). The other three projects make up the “onion”.

image

The most interesting parts of the solution to me are the dependencies. You can see here that Core doesn’t reference anything. That means everything my domain objects and services could possibly need have to live within the Core project. Sounds reasonable until you realize they will at some point need data from the database and to log information. The details of those concerns aren’t “domain” type things of course so they live in the infrastructure project. But Core doesn’t reference Infrastructure! Oh my.

This is where the Dependency Inversion principle comes into play. Basically, anything the domain layer could need that isn’t a “domain” type of concern is split into a contract and implementation. The contract (interface) lives within Core and the implementation lives within Infrastructure. The two are tied together only once at application startup.

Full Solution

Hopefully the image to the left isn’t too tiny to see, but basically there are three players required to make this work smoothly. The class IoC in Core is a static container for the interface of an inversion of control container that will resolve interfaces for me. The InversionOfControlContainer in Infrastructure is the implementation of the container defined in Core. At application startup in the Global.asax, I tie the two together.

So in Global.asax.cs you’ll see this:

protected void Application_Start()
{
IoC.Initialize(new InversionOfControlContainer());

You can probably imagine that all I'm doing in "Initialize" is setting a private static variable that will be referenced throughout the rest of the application’s lifetime. For example, a method on IoC is:

public static T Resolve<T>() { return iocContainer.Resolve<T>(); }

And I use IoC like this:

IoC.Resolve<IUnitOfWork>().Begin();

Of course, note that in this situation, both the interface IUnitOfWork and it's implementation are in Infrastructure, but the use of IoC is the point :)

Well, hopefully that conveys my implementation of The Onion Architecture. I must say, this is something that I’m finding extremely pleasant to work with. Due to the fact that Core doesn’t reference Infrastructure, I’m forced to find solutions strictly in terms of my domain and the repositories. Very cool stuff indeed!

Happy coding!

Tags: , ,