Reputation: 1452
Jeffrey Palermo pioneered the onion architecture, which I have found a good approach.
http://www.headspring.com/jeffrey/onion-architecture-part-4-after-four-years/
However his statement "Inner layers define interfaces. Outer layers implement interfaces" seems to contradict IoC, if my understanding is correct, which states that Consumer define interface and providers implement it, i.e. the control lies with the consumer not the provider.
This principle makes sense to me, since, imagine you are writing a UI, this principle means you can get on with creating your UI without knowing anything about the services you are going to call since you are in charge of defining the interface that exposes all the functionality your will need.
So to that end Jeffreys statement seems a contradiction and confuses me about where to put contract(interface definitions), because it seems to imply that: Domain Layer MyEntity IMyService Service MyEntityService : IMyService
Since there is no layer beneath Domain, where do I put IMyEntity. Also it means I cannot create a Presentation project until Domain exists and has defined IMyService.
As I side note, where do I place IMyEntityRepository and MyEntityRepository ? Since service relies on IMyEntityRepository and MyEntityRepository relies on IMyEntity
Upvotes: 1
Views: 1695
Reputation: 64561
The interfaces in the onion architecture are the ones that the layer depends on (i.e. consumes), whose implementation indeed is provided by the outer layer.
More specifically, the architecture itself does not say you have to abstract the business logic behind interfaces (which you should probably do anyway, in respect of the dependency inversion principle, but that's another story). What is says is that the dependencies of the layer should be modeled as interfaces so implementations can be provided by the outer layer.
The best example is infrastructure code, and particularly data access. Your business logic needs to load and store data, so it defines an interface that it'll consume. The outer layer will provide an implementation using NHibernate or EF or whatever.
Actually, the low-level layers (from the DIP; i.e. the data access and other commodities) are on the outermost layers of the onion, while the high-level layers (i.e. the business logic) are closer to the center.
See also http://blog.8thlight.com/uncle-bob/2012/08/13/the-clean-architecture.html which replaces the domain, business logic and more business logic terms with entities, use cases and interface adapters which IMO are easier to reason about. The farther you go from the center, the most specific you are to what the user sees and use; the closer to the center the more generic; at the center are those things that are transverse to your enterprise, then the use cases which are specific to your app more don't dictate how they'll be used or in which environment (which DB, which UI, etc.), then you'll make adapters between your use-cases and your technical framework (ASP.NET MVC, WCF, WPF –in a non-web scenario–, EF, NHibernate, etc.)
Upvotes: 0
Reputation: 2181
We've implemented Onion on my project and it's conceptually pretty simple.
This approach allows you to only rely on Contract and the idea is that you can switch Implementation so if you want to move to Entity Framework or something else in the future you only have to reimplement Implementation using that framework.
We also copy the NHibernate DLLs to the configured scanning location and this allows us to make the architecture defensive so that it is difficult to not follow the it because NHibernate is only available where it should be used.
Upvotes: 2
Reputation: 41
I have worked with Jeffrey for many years, and I would say that IoC is integral to making Onion Architecture possible. Interfaces for external dependencies are defined in projects with few (if any) dependencies (in other words, projects at the "center" of the onion). Classes that implement those interfaces that depend on external dependencies are located in projects at the edge / on the surface of the onion. IoC containers, then, are needed to "hook up" the class implementations on the edge of the onion to interfaces at the core of the onion at run-time.
Upvotes: 4
Reputation: 4758
So, where to begin? :-)
Let’s start with the real role of an IOC. According to Wikipedia,
Inversion Of Control is a programming technique in which object coupling is bound at run time by an assembler object and is typically not known at compile time.
In your case, your UI will manipulate services interfaces without knowing the service implementation that will be bound at run time. It’s not up to the consumer to define those service interfaces; they will be defined in the application core of your Onion architecture, but we’ll see that later.
"Inner layers define interfaces. Outer layers implement interfaces", that’s how the Onion Architecture is designed, but do not forget that the outermost layer is the IOC! It’s up to the IOC to bind interfaces with the right implementations at run time!
You’re right saying that your UI won’t work without having at least one implementation available for the interfaces you will manipulate. But in this case, if for any reason you need to build your UI first, consider using a mocking framework!
Your last question is about where you need to place your IMyEntityRepository and MyEntityRepository classes. Well, that’s the easy part ;-) IMyEntityRepository definitely needs to be placed within your Application core. All your entities, service interfaces, repository interfaces and whatever interfaces need to be at the same place. MyEntityRepository implementation should be placed somewhere in your infrastructure layer as his role will be mainly to deal with getting data out of the DB.
Hope that helps!
Upvotes: 5