3

I am trying to implement an Onion architecture for a ASP.Net MVC 5 project. I have seen opinions that services should be injected rather than instantiated even though, correct me if I am wrong, the idea expressed by Jeffery Palermo (http://jeffreypalermo.com/blog/the-onion-architecture-part-3/) was that any outer layer should be able to directly call any inner layer. So my question is

  1. Can the onion architecture work without IOC, and if yes, is it ideal?
  2. Let's say we go with IOC, if the UI should not know about the actual implementation of domain services, should we apply the same principle to the domain models themselves e.g. injecting models into the UI instead of referencing them directly?

I am understand why some solutions apply IOC on domain services but are accessing the domain models directly in the controllers.

Joei Huang
  • 66
  • 5
  • How to inject models into UI? Could you post some code sample? – Yugang Zhou Jan 11 '14 at 10:53
  • 2
    The whole idea of the Onion architecture (aka ports & adapters) is to do Dependency Inversion / IoC, so you can't do it without. – Steven Jan 11 '14 at 12:11
  • @Hippoom this would require us to create interfaces for each domain model, and then inject the concrete implementation using an IOC like Autofac – Joei Huang Jan 12 '14 at 10:38
  • @JoeiHuang No it doesn't. The domain model is concrete. Services, persistence should be abstracted, not the domain concepts and use cases. – MikeSW Jan 12 '14 at 20:25
  • 1
    Related: http://blog.ploeh.dk/2013/12/03/layers-onions-ports-adapters-its-all-the-same – Mark Seemann Mar 11 '14 at 18:30

2 Answers2

3

OA can be thought of as n-tier architecture + Dependency Injection--so you would be hard-pressed to implement OA without IOC.

Regarding outer layers using any inner layer, I personally disagree with Palermo on this point. I think that outer layers should be constrained to working with the next layer in (to restate: outer layers should not be allowed to bypass a layer). I asked him about this on twitter once and he said that it's probably not a good idea for the data access implementation code to work with the presentation layer (remembering that the implementation code is on the outer rim of his architecture).

I think Palermo makes room for bypassing a layer precisely because he wants to be able to manipulate a Domain Models and Domain Services in the Controller. As far as I understand Domain Driven Design, Domain Services are only created when logic does not neatly fit into a Domain Model. If that is the case, then Domain Services and Domain Models are not really 2 separate layers. Rather, it's better to think of them as a single Business Layer. If they are both the same layer, then the question of whether you can use both in a Controller resolves itself. Then you can say without contradiction that outer layers should be constrained to talking to the next layer in the onion.

Chris McKenzie
  • 3,681
  • 3
  • 27
  • 36
  • Thank you for your input Chris. Let's say some of our domain models are rich in logic and do not require services layer, would you always inject domain models into the presentation layer through interfaces and IOC rather than reference the concrete implementation? – Joei Huang Jan 14 '14 at 18:34
  • I'm not a DDD practitioner myself, so it's difficult for me to answer. My gut tells me that I would probably inject an interface to retrieve the domain objects. If you really feel that you don't need that interface, the next question becomes "does your domain model have dependencies?" If so, yes you should inject it. Otherwise your Controller has to know how to construct a Domain Model which means it has to know more than it should about its dependencies. – Chris McKenzie Jan 14 '14 at 19:11
  • The diagram that DK Mulligan uses on his [blog post](http://blog.dkmulligan.com/2013/05/16/onion-architecture/) might be useful. – Chris McKenzie Jan 14 '14 at 19:15
  • I thought the idea of being able to access all inner layers from an outer layer was to limit coupling and flatten the dependency graph. If layer A depends on layer B which depends on layer C, A has a big dependency chain. But if layer A does not really need anything from layer B, but only uses it to indirectly use layer C, then why not make layer A depend only on layer C, which reduces dependency chain. This way, if you ever swap out layer B or change stuff inside it, you will not need to touch layer A or layer C, they will still work. I can't think of any negative to this either. – Didier A. Feb 19 '14 at 17:06
  • I've run into a lot of problems when UI code is bound to entities from the innermost layers of the application. For this reason, I tend to bind my UI code to an API that is designed more around SOA or Functional values than DDD--even when the api is not exposed as a web service. If you're not having those problems, you should keep doing what's easiest to understand and maintain for you and your team. – Chris McKenzie Feb 20 '14 at 19:27
  • I'm still debating about whether it's ok to use core entities from the outer layer. I actually have a question about it: http://stackoverflow.com/questions/21887157/in-an-onion-type-architecture-should-the-entities-cross-the-outer-layer . I'm leaning on what you said, you should map your core entity into an entity that the UI defines or use APIs to modify core entities. But inside the core, I think it's good for decoupling if your out most core layer directly uses your innermost core layer, skipping over middle core layers. – Didier A. Feb 21 '14 at 15:29
1

First, remember that the Onion Architecture (OA) is agnostic to application design styles, so there is nothing stopping you from injecting your domain into the UI. Second, the linked article points out that IoC is core, so you won't want to try to go without it. I'm also surmising you're talking about your domain entities - those things with data/state in your domain.

OA is about shielding your domain (business rules, entities, etc) from the vagaries of infrastructure changes, not the other way around. All you're buying yourself by using interfaces to get to your domain is extra code and indirection. Ask yourself this - If my domain changes (the core of your business), is it realistic to expect my user interface won't? Put another way, if your business rules change, the users are probably going to want to see that reflected in the UI if it involves adding or removing fields or whole lines of business.

Now ask the inverse of that question - If I change from Oracle to NoSQL, will my Domain code change? Injection of your infrastructure laden services is meant to give you the answer "No". This presumably means easier to maintain and more stable code.

So, in conclusion, unless you need to hide logic on your domain entities, or there is a compelling architectural reason against it (e.g., you're flinging these out of your server to a remote client or you want to add UI-specific attributes to your properties to affect validation or label display), you should go ahead and reference your concrete domain entities directly in your "application/UI" layer.

VeteranCoder
  • 444
  • 1
  • 4
  • 12