C# – Separating the Domain Model from the Data Model

cdomain-driven-design

I am trying to understand how to separate the domain model from the persistence mode so that the two can vary independently as described here and here

I understand the benefit of mapping the ORM directly to the domain model i.e. speed of development. This would be my normal approach.

Say I wanted to separate the domain model from the data model. I have two questions:

1) My research tells me that the main limitation of doing this is change tracking. How is this a problem? I would map the domain model back to the data model to persist the changes – at that point NHibernate (my ORM) would find the changes.

2) Are there any examples of open source systems or examples that show how to separate the domain model from the data model?

I have read plenty of questions on here (and Stackoverflow) similar to mine e.g. this one. However, none answer my specific questions in my opinion.

Best Answer

To answer #1 - when separating the domain model from the persistence model, change tracking is not a problem. The reason is that change tracking is more of a cross-cutting concern than a domain concern. The concern of a domain model is not to ensure that changes to itself are tracked.

The changes we want to track are typically the ones that we also persist. IOW, if, in the course of some processing, we change a property value and then change it back, there is no change to persist, which means there's also no change to track. So I'd lean toward change tracking as a behavior of the persistence, not the domain.

Edited: Here's a note from Patters, Principles, and Practices of Domain-Driven Design:

Don't put dirty flags on domain objects
It might be tempting to put a flag on a domain object to signify that it has changed. The problem with this is that you are clouding the domain model with persistence concerns. Leave all change tracking to the unit of work and the repository.

For #2 - I don't have an open source example. But to start with, the separation between domain models and persistence models means ensuring that the persistence is abstracted, perhaps using the repository pattern.

If your domain models depend on a 'persistence ignorant' repository abstraction, like

public interface IRepository<T> where T : class
{
    void Add(T item);
    void Update(T item);
    void Delete(T item);
    void Get(RecordId id);
}

Then the implementation of that repository can map that T to and from whatever persistence-specific model is needed, and the domain will never know that the persistence model even exists.

In order for this to happen, the domain needs to define its own repository interface rather than injecting one defined in some persistence library. That leaves the domain persistence agnostic and easier to test, and only the implementation(s) of that repository know about the details of the persistence.