2

Please see the code below:

public interface IUnitOfWorkWrite <TSession> : IDisposable
    {
        TSession Session { get; }
        void Commit();
        void Rollback();
        ITransaction BeginTransaction();
    }
}

This interface is contained in the domain layer. The service layer provides an implementation. Therefore the domain layer is not dependent upon anything except NHibernate i.e. NHibernate has to be installed for Session and ITransaction.

Should the domain layer be dependent on NHibernate in this scenario?

3 Answers 3

5

Should the domain layer be dependent on NHibernate in this scenario?

From a purist perspective: no it should not. The domain layer shouldn't be carrying around a bunch of dependencies on your persistence solution. "UnitOfWork" and "Transaction" are not part of the ubiquitous language of most business domains.

From the onion perspective: your dependency is pointing the wrong way. Instead of adding an NHibernate dependency, you can put an agnostic service provider interface into your module, and then pass an NHibernate implementation of the agnostic interface to the ports that need it.

In practice: I doubt that the DDD police are going to come after you.

Domain Services can access the database

Not quite right. Implementations of Domain Services can access the database. The interface, used by the domain model, just expresses the service in the domain language. The implementation is going to be relying on other application and infrastructure services - ie, other service providers of interfaces that it defines, and it's turtles all the way down.

The thing that actually talks to the NHibernate is probably going to be an infrastructure service.

In other words, your composition root is probably going to look something like

NHibernateThing nhibernate = ...
DomainServiceImpl.Adapter infrastructure = InfrastructureService.using(nhibernate)
DomainService service = DomainServiceImpl.using(infrastructure)

where you are wiring each adapter into the appropriate port in turn.

Reread Parnas; at a fundamental level, NHibernate is the result of a decision, and you want module boundaries in place that separate the pieces that depend on that decision from the pieces that do not. That makes it easier to change when the time comes.

But - you should be balancing this against the risk of change; if NHibernate is always going to be part of your solution, then you shouldn't be investing in decoupling it from your domain.

3
  • The Domain Layer benefits from Dependency Inversion i.e. there are interfaces and the domain layer expects the application service to provide an implementation.
    – w0051977
    Commented Oct 18, 2017 at 14:47
  • Domain Services can access the database so I believe these interfaces have to be contained in the domain layer, though I agree that they are not part of the Ubituous language. What else can I do?
    – w0051977
    Commented Oct 18, 2017 at 14:48
  • +1 for the DDD police reference. I probably take this too seriously.
    – w0051977
    Commented Oct 18, 2017 at 14:49
4

Your domain layer is where you add value to the software you are building. NHibernate is a means to an end. Tying the value of your software to a solution that doesn't really matter is a strategic error. What I mean by that is whoever is paying for this or whoever is using this really doesn't (or shouldn't) care how you read and write data.

The problem comes when you suddenly need to get away from NHibernate. Let's say you find out right before you release that NHibernate has a fundamental security flaw and no fix is in sight? If you've coupled your value (the domain layer) to this package, you're screwed. Or, more likely, some other tool comes out that you'd much prefer to use but the switching cost is too high to justify.

As CatWhisperer mentions in the comments below, there are also other practical reasons not to do this. For one it can complicate mocking and other types of testing. It also means that you are roughly tying your domain model to a persistence model. This makes the software you are creating less reusable in that you are preventing using your domain model with other types of data sources. For example, let's say someone wants to run a Monte Carlo simulation using your domain model. I'm not saying it's necessarily impossible to do this with NHibernate but it's going to add a lot of complexity.

I work with software from a vendor who built a major piece of their implementation using a proprietary feature of an expensive platform. At the time they decided this, it was common to run software in this way so they thought it was fine. Now this platform is a significant portion of the cost of running their software: a huge strategic blunder. Whatever time they think they saved by using this feature is completely overwhelmed by the reality that none of their customers want to pay for this expensive platform. It makes their software more expensive and essentially cuts into their profits because they don't see a dime of that added cost. The cost of removing the dependency is also high. This completely avoidable mistake will cost them many millions of dollars in revenue.

2
  • 1
    I was going to write my own answer, but not a lot of time today, and this is good. I'd like to see added to yours: Another downfall of tying domain layer to data-access is, how do you run what-if/hypothetical scenarios? What if I have a tax application and the CFO want to see how much taxes the company would owe if they business moved X to Y? Very difficult if your domain layer is tied to N Hibernate... then you can only work with the business' actual numbers! Commented Oct 18, 2017 at 20:23
  • 1
    @TheCatWhisperer I added another paragraph that I think addresses your point.
    – JimmyJames
    Commented Oct 18, 2017 at 21:07
-2

If your domain layer is where you are accessing your data via NHibernate then yes it should be dependent on it. If you are calling to another layer to manage the access, then your abstraction is leaky and you have details about data access in places where the shouldn't be.

Layers that aren't accessing data should only be dependent on objects that represent the data and not know anything about how they are accessed. If this is not the case you aren't following the open/closed principle as you have objects with multiple reasons to change.

8
  • Please see my comments below Voice Of Reasons' post. Do you have anything more to add. Thanks.
    – w0051977
    Commented Oct 18, 2017 at 14:49
  • 1
    "If your domain layer is where you are accessing your data via NHibernate then yes it should be dependent on it." This is a weird statement to me. If you are doing persistence in your domain layer, it's not really a really domain layer, it's a domain/persistence layer at best.
    – JimmyJames
    Commented Oct 18, 2017 at 16:54
  • @JimmyJames exactly Commented Oct 18, 2017 at 20:24
  • @JimmyJames, I agree to some extent. However, what about Domain Services like this: zankavtaskin.com/2013/11/…. Rather than having the Domain Layer depend on the data layer; I am using dependency injection
    – w0051977
    Commented Oct 18, 2017 at 21:25
  • 1
    @JimmyJames its not uncommon for projects to name layers to match a pattern and not actually follow that pattern.
    – Ryathal
    Commented Oct 19, 2017 at 11:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.