The Onion Architecture : part 3

Part 1 - Part 2 - This is part 3. part 4. - My RSS feed

In my previous installments, I described what has become my approach to defining the architecture for an application.  Based on feedback, I've modified my diagrams a bit to reduce ambiguity and emphasize key points.  The goal of part 3 of this series is to compare and contrast the Onion Architecture with traditional layered architecture.  I will flatten the Onion Architecture to see what it looks like compared to traditional layered architecture, and I will force the layered architecture into an onion.  Whereas the shape can be either, the structure of the actual application is radically different from what is commonly known and accepted.  I'll define four tenets of Onion Architecture at the end.

I must stress again:  I am not claiming any breakthroughs in technology or technique.  I have learned from other industry thought leaders like Martin Fowler, Ward Cunningham, Kent Beck, Michael Feathers and others (especially those I've had the privilege to work with here in Austin, TX).  I'm putting forth the Onion Architecture as an architectural pattern by which we can communicate this radically different architectural approach.  Not "radically different as in new".  Different as in not mainstream.

Let's review.  Traditional layered architecture can look somewhat like the diagram depicted on the right.  Each layer communicates with the layer below it.  The UI talks to business logic, but it does not talk directly to data access, WCF, etc.  The layering approach does call out the need to keep certain categories of code out of the UI.  The big downfall is that business logic ends up coupled to infrastructure concerns.  Data Access, I/O, and Web Services are all infrastructure.  Infrastructure is any code that is a commodity and does not give your application a competitive advantage.  This code is most likely to change frequently as the application goes through years of maintenance.  Web services are still fairly new, and the first version in .Net, ASMX, is already deprecated in favor of WCF.  We can be assured that WCF's days are numbered as well, so it is foolish to tightly couple the business logic to WCF.  Data access changes every two years or so, so we definitely don't want to be tightly coupled to it.  For long-life, we would want our business logic to be independent of these infrastructure concerns so that as infrastructure changes, the business logic doesn't have to.

Let's review Onion Architecture.  The object model is in the center with supporting business logic around it.  The direction of coupling is toward the center.  The big difference is that any outer layer can directly call any inner layer.   With traditionally layered architecture, a layer can only call the layer directly beneath it.  This is one of the key points that makes Onion Architecture different from traditional layered architecture.  Infrastructure is pushed out to the edges where no business logic code couples to it.  The code that interacts with the database will implement interfaces in the application core.  The application core is coupled to those interfaces but not the actual data access code.  In this way, we can change code in any outer layer without affecting the application core.  We include tests because any long-lived application needs tests.  Tests sit at the outskirts because the application core doesn't couple to them, but the tests are coupled to the application core.  We could also have another layer of tests around the entire outside when we test the UI and infrastructure code.

This approach to application architecture ensures that the application core doesn't have to change as:  the UI changes, data access changes, web service and messaging infrastructure changes, I/O techniques change.

To the right, I have created a diagram which attempts to show what Onion Architecture would look like when represented as a traditionally layered architecture.  The big difference is that Data Access is a top layer along with UI, I/O, etc.  Another key difference is that the layers above can use any layer beneath them, not just the layer immediately beneath.  Also, business logic is coupled to the object model but not to infrastructure.

To the left here I have attempted to represent traditionally layered architecture using concentric circles.  I have used black lines around the layers to denote that each outer layer only talks to the layer immediately toward the center.  The big kicker here is that we clearly see the application is built around data access and other infrastructure.  Because the application has this coupling, when data access, web services, etc. change, the business logic layer will have to change.  The world view difference is how to handle infrastructure.  Traditional layered architecture couples directly to it.  Onion Architecture pushes it off to the side and defines abstractions (interfaces) to depend on.  Then the infrastructure code also depends on these abstractions (interfaces).  Depending on abstractions is an old principle, but the Onion Architecture puts that concepts right up front. 

 

Key tenets of Onion Architecture:

  • 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

 

I encourage you to use the term "Onion Architecture" when speaking about architectures that adhere to the above four tenets.  I believe that this approach to architecture leads to long-lived systems that are easy to maintain.  Also, in my experience, this architecture yields dividends soon after a project starts since it makes the code a breeze to change.

Although I don't call out an IoC container as a key tenet, when using a mainstream language like Java or C#, an IoC container makes the code fit together very easily.  Some languages have IoC features built-in, so this is not always necessary.  If you are using C#, I highly recommend using Castle Windsor or StructureMap.


Trackbacks

The Onion Architecture : part 3 : Jeffrey Palermo (.com) Posted on 8.04.2008 at 9:34 AM

Pingback from The Onion Architecture : part 3 : Jeffrey Palermo (.com)

The Onion Architecture : part 2 : Jeffrey Palermo (.com) Posted on 8.04.2008 at 9:35 AM

Pingback from The Onion Architecture : part 2 : Jeffrey Palermo (.com)

The Onion Architecture : part 1 : Jeffrey Palermo (.com) Posted on 8.04.2008 at 9:36 AM

Pingback from The Onion Architecture : part 1 : Jeffrey Palermo (.com)

So you want to learn NHibernate - Part 0.5, Prerequisites (or NHibernate = Marijuana.NET) « HSI Developer Blog Posted on 8.04.2008 at 12:34 PM

Pingback from So you want to learn NHibernate - Part 0.5, Prerequisites (or NHibernate = Marijuana.NET) « HSI Developer Blog

Reflective Perspective - Chris Alcock » The Morning Brew #151 Posted on 8.05.2008 at 2:25 AM

Pingback from Reflective Perspective - Chris Alcock » The Morning Brew #151

Dew Drop - August 5, 2008 | Alvin Ashcraft's Morning Dew Posted on 8.05.2008 at 8:08 AM

Pingback from Dew Drop - August 5, 2008 | Alvin Ashcraft's Morning Dew

So you want to learn NHibernate - Part 0.5, Prerequisites (or NHibernate = Marijuana.NET) | The Freak Parade Posted on 8.08.2008 at 5:39 PM

Pingback from So you want to learn NHibernate - Part 0.5, Prerequisites (or NHibernate = Marijuana.NET) | The Freak Parade

Weekly Web Nuggets #24 Posted on 8.08.2008 at 8:33 PM

Probably the biggest news of the week is that SQL Server 2008 RTM'd this week, and is already available on MSDN. A word of warning...if you have Visual Studio 2008 installed, you're better off waiting until Monday when SP1 for Visual Studio 2008 ships

Weekly Links #13 | GrantPalin.com Posted on 8.10.2008 at 11:04 PM

Pingback from Weekly Links #13 | GrantPalin.com

Training module - Layering Posted on 8.15.2008 at 1:48 PM

Training module - Layering

Books and bits » Blog Archive » The Onion Architecture and a layered aproach Posted on 8.16.2008 at 11:16 PM

Pingback from Books and bits » Blog Archive » The Onion Architecture and a layered aproach

The Onion Architecture | Dev @ Work Posted on 8.26.2008 at 12:43 PM

Pingback from The Onion Architecture | Dev @ Work

Revisiting the onion Posted on 8.30.2008 at 8:16 PM

I'm working on a chapter on layering for the upcoming Brownfield book , and for better or for worse

Revisiting the onion Posted on 8.30.2008 at 8:51 PM

I'm working on a chapter on layering for the upcoming Brownfield book , and for better or for worse

Comments

Josh said on 8.05.2008 at 12:02 AM

Your diagram states that the business logic exists in the service class rather than the object model. Leaving your object model to be nothing more than simple DTOs with relationships. It appears this is the case in the codecampserver code.

I like the general idea of this architecture, and I use one close to it myself. But, doesn't all the logic in services clearly smell like an anemic domain model?

ref: martinfowler.com/.../AnemicDomainMod

Gabriel Schenker said on 8.05.2008 at 2:08 AM

congratulations: the post series about the onion architecture are very very well presented. You are able to express with some nice diagrams and well chosen words what are the essentials of DDD in regards of producing reliable and maintainable software

Jeffrey Palermo said on 8.05.2008 at 7:11 AM

@Josh,

Business logic is in the application core. It is distributed across the object model and service classes. Not all business logic can fit in the object model, and the general attempt is to push the business logic as far toward the center as it belongs.

CodeCampServer does not have an anemic domain model. It has appropriate logic in the object model. Since there aren't many rules in CodeCampServer, it's pretty easy to understand. Of course if you find some logic in a service class that has a better fit in an entity, please submit a patch.

Benny Michielsen said on 8.05.2008 at 12:20 PM

Nice series, another very good container is Spring.Net http://www.springframework.net

Greg Young said on 8.05.2008 at 5:43 PM

OK I will bite ..

"I'm putting forth the Onion Architecture as an architectural pattern by which we can communicate this radically different architectural approach. Not "radically different as in new". Different as in not mainstream."

Why don't you just call it what the pattern has already been named? Its a Hexagonal Architecture as put forth by Alistair Cockburn long ago http://alistair.cockburn.us/index.php/Hexagonal_architecture. I have yet to see you differentiate your "onion architecture pattern" from a hexagonal architecture in any way shape or form.

I mean if the goal is to communicate the benefits of the pattern you have done yourself a disservice by calling it your own name. Many of us already know this pattern and simply by using its name you are communicating with us (isn't that why we use patterns in the first place?)

This smells to me like how Microsoft "reinvented" AOP in the policy injection block and gave all of the same concepts new names. Result, there are tens of thousands of pages of literature people will never see on interception strategies because they are not called interceptors.

While the creation of your own pattern name may be good for your own personal interests, either distinguish it from the existing patterns early or just use the original pattern names and become a supporter of them so people can get more information .

Cheers,

Greg

Jeffrey Palermo said on 8.05.2008 at 7:06 PM

@Greg,

I referenced Cockburn's Hexagonal Architecture in Part 1. I am very familiar with it. The ports and adapters concept based on interfaces is similar, but Hexagonal doesn't address how the application is structured. It only addresses how external dependencies connect with the application.

Onion Architecture is much more specific than Hexagonal even though it shares interfaces with dependencies.

Ultimately, if this pattern isn't useful or is a direct duplicate, it will sort itself out. Before part 1, I researched patterns, and Hexagonal was the closest I found, but it only shared one aspect; definitely not what I was looking to communicate.

I will take your advice and write another piece to point out the commonality with Hexagonal as well as call out and describe the tenets which make Onion Architecture unique.

Again, these concepts are widely used in the Alt.Net circle, but up to this point, there hasn't been an architectural pattern that has pulled it all together. I believe you have pulled it all together in your projects, but the dialog has been wanting for a name to describe the whole.

I've been getting lots of feedback about the description helping folks. My blog comment form is getting quite the workout by folks writing in about how they were struggling to understand these concepts and that the Onion Architecture has helped them close the loop.

James Taylor said on 8.05.2008 at 7:15 PM

Interesting architecture. Do you see the business logic being written procedurally or managed in a more declarative fashion? It seems to me that the ability to manage business logic components (business rules) in a declarative way that was accessible to business/domain experts would be key in this kind of approach.

JT

James Taylor

Author, with Neil Raden, of Smart (Enough) Systems

Jeffrey Palermo said on 8.05.2008 at 7:24 PM

@James,

The business logic can be procedurally written inside a method, but this is ultimately an object-oriented architecture, and business logic is spread across the object model as well as service classes whose behavior is defined by interfaces.

If you application needs to externalize business rules, that's fine. This architecture would call for an interface in the application core by which to read in the business rules, which I presume would be stored in some medium supported by externalized infrastructure, like XML files or database tables.

This architecture doesn't speak to what features would be supported. It speaks to direction of coupling, an internal object model, and internal interfaces implemented by external code.

Scott Bellware said on 8.05.2008 at 8:32 PM

Jeff,

> Again, these concepts are widely used in the Alt.Net circle, but

> up to this point, there hasn't been an architectural pattern that

> has pulled it all together.

I think the larger issue here is an ever more common pattern of self-aggrandizement.

Jeffrey Palermo said on 8.06.2008 at 10:58 AM

@Scott Bellware,

not sure I follow you.

Greg Young said on 8.06.2008 at 12:48 PM

@Jeff looking forward to the post

Bret Williams said on 8.06.2008 at 2:46 PM

Hey Jeff...I've been following your Onion posts with much interest. Can you tell us in more detail why it is important to make the Data Access layer external? Is it so that you can have flexibility to plug in another provider if need be? In most large web site the data access layer is integral to entire design and creating indirection layers to access it becomes an academic exercise. Great job on the articles by the way!

Jeffrey Palermo said on 8.07.2008 at 6:53 AM

@Bret,

The data access layer is still a part of the application, but it is outside the application core. Data Access is not business logic. It is interacting with a data storage service called a database. The database is commodity infrastructure that changes frequently (ever 3-5 years), and our application need not be coupled to this instability.

Shadi Marei said on 8.13.2008 at 5:24 AM

How this is different than the 4 layers approach explained in Evan's book? (i.e. UI / Application / Domain / Infra).

Josh Towers said on 8.13.2008 at 4:41 PM

Great posts...my only complaint is the actual name "Onion Architecture." It seems to me that the name should somehow convey the most important part of the architecture: that the domain has no external dependencies. The name "Onion Architecture" in no way conveys the importance of the domain. It simply puts the focus on the fact that there are many layers...which could be widely misused and abused by anyone who has an architecture with layers. Do you really want to pick a name that can be thrown around as easily as "Agile"? :)

Joe Future said on 8.19.2008 at 9:06 AM

As a software tester, I'd love to hear any advice you have on pushing an IoC model with your developers. The immediate reaction I got was along the lines of "you have to write so much more code, it's not worth it". This is a very short-sighted view, of course. When you consider the impact to testability (and stability), maintenance, etc., is this truly cheaper? Do you have any hard data we can use to help sell the paradigm?

web design company said on 8.27.2008 at 11:03 PM

If you can completely split your business logic from your object model then your object model is rubbish.

Jeffrey Palermo said on 8.28.2008 at 8:01 AM

@web design company,

Please post your name in the future.

Regarding your comment, I completely agree. The object model should enforce much of your business logic.

Borek said on 9.05.2008 at 4:27 AM

Similarly to other people who already commented here, I don't understand how the onion architecture is different from a layered architecture with repositories - you have nice structure and no direct dependencies on the data access layer. In fact, I had examined the CodeCampServer before I read these articles and I thought it was quite a nice example of the layered architecture :)

Therefore, if there isn't much difference between onion and layers with repositories, I think the proposed new pattern is just going to be confusing. If you are going to tackle these concerns in your next post about onion, I'll be looking forward to it.

Wade D said on 9.25.2008 at 7:33 PM

Jeff, I know you're an nHibernate user so you recommend Windsor or StructureMap over Spring.Net?

Jeffrey Palermo said on 9.25.2008 at 9:30 PM

@Wade,

I'd recommend any of the 3 IoC containers you listed. IoC containers are commodities these days, and regardless of the one you choose, I'd recommend keeping your code infrastructure-ignorant. Don't tie your code to any IoC container or any other infrastructure.

Also, IoC views are unrelated to NHibernate usage.

Chris said on 10.02.2008 at 3:03 PM

You can tell you really put effort into this third part, great job, and thanks for taking the time to answer everyone's complaints and questions. If anything, Ive got a more applicable understanding of IoC.

I like the idea of this architecture, it puts the business model right at the *bull's eye* of the architecture, instead of having the business chase after the infrastructure.

Wade said on 10.14.2008 at 11:01 AM

Jeff,

Does this architecture separate DAO from web and core projects? How then would data access be achieved?

Randy Klingelheber said on 10.29.2008 at 2:39 AM

Thank you for this article. It is very helpful as I investigate a future architecture for my current project. I am curious about this design, but am having trouble with the separation of data and behavior.

It appears that the application service layer houses the behavior of the application and that the data it operates on lives separately in the center (the object model).

I saw in your explanation to Josh that the responsibilities are distributed throughout the application core which I think I understand and like.

However, in the end, doesn't the UI end up working with an almost pure data object and another object that will act on it (an application service)? It seems like this is a separation of data and it's behavior.

Could you please help me and possibly others understand how encapsulation is not broken in this architecture?

Or is it that it's OK to break encapsulation to achieve small singly responsible objects?

Or, is there another layer that combines the object model with the application services to look like a rich object?

Many thanks.

Jeffrey Palermo said on 10.29.2008 at 7:14 AM

@Randy,

The center of the core is the domain model. Refer to Eric Evan's DDD book for how to ensure your domain objects are rich with behavior and not just data.

The object model at the center is meant to be rich with behavior that surrounds and encapsulates the data.

Ravi said on 11.28.2008 at 1:08 AM

Not sure if this is architecture is any different from the traditional layered architecture. The driving force behind the Onion architecture, as I understand, is for the business logic/object domain to not depend on the infrastructure for ex.dataaccess.

We need to clarify what "depend" means. The dependency that we are talking about in Onion architecture is "where does the interface definitions reside that outer layers need to implement" whereas the dependency in the traditional layered architecture is "what does it take to make the application run".

So if I define and host all the interfaces for my system in the business layer then what is the difference between the 2 architectures since even in Onion architecture you still need your infra services (dataaccess) to be up and running for your system to work?

Obviously in any architecture the business logic does depend on the dataaccess layer to get and put data (no brainer). Question is how is dependecy achieved? Ok, one simple way is to define an interface for dataaccess and code against the interface in the business layer, a logical place to house the interface would be in the business layer assembly or a separate assembly. Now the dataaccess implements the interface. Tommorrow the database technology changes I would simply create another implementation of the interface and allow the business layer to use it using IOC (Another big hue and cry about the coolness of IOC..why make it a design pattern instead simply call it a cool tip...nevermind thats just me.... where instead of hardcoding the reference to the dataccess assembly in the business layer you move it to a config file..how many times havent you saved stuff that could potenially change in the future in a config file?).

With reference to your example where you have the business layer depending on dataaccess, wcf and I/O...I would make the business layer depend (via interface) on the dataaccess layer only and delegate to the dataaccess layer how it communicates to the rest of the world to get the "data" say via database, wcf, i/o, bapi etc, so if wcf changes tommorrow business layer doesnt need to change.

So far I have stuck to the traditional layer architecture (in mind atleast) without having to use anything from the Onion architecture.

The other tenet that is mentioned above is "All application core code can be compiled and run separate from infrastructure".

So if I ask the question, in the traditional layered approach can the application run without the dataacess layer answer is nope.

Again, in the onion architecture approach can the application run without the dataacess layer answer is nope. How are you going to run an application without the help of the infra (database).

According to ’Hexagonal Architecture’’ make use of a mock database...in a complex system where I depend on data from mutilple datasources (ERP, home grown logisitic system, file - csv and text files, multiple sql databases) I am not clear how a mock database is applicable. I cant potenially create a mock database which aggregates all my datasources so that I can run my tests against the business layer without having my dataaccess layer "up and running".

As long as we make sure that the business logic does not seep into other layers is there a difference between the 2 architectures?