DDD - Persistence Model and Domain Model
Asked Answered
H

4

86

I am trying to learn domain-driven design (DDD), and I think I got the basic idea. But there is something confusing me.

In DDD, are the persistence model and domain model different things? I mean, we design our domain and classes with only domain concerns in mind; that's okay. But after that when we are building our repositories or any other data persistence system, should we create another representation of our model to use in persistence layer?

I was thinking our domain model is used in persistence too, meaning our repositories return our domain objects from queries. But today, I read this post, and I'm a little confused:

Just Stop It! The Domain Model Is Not The Persistence Model

If that's true what would be the advantage of having separate persistence objects from domain objects?

Hardeman answered 24/12, 2012 at 19:8 Comment(2)
Here's a post I wrote on this exact topic: enterprisecraftsmanship.com/2016/04/05/…Ionia
@Hardeman The link moved to blog.sapiensworks.com/post/2012/04/07/…Underline
K
124

Just think of it this way, the domain model should be dependent upon nothing and have no infrastructure code within it. The domain model should not be serializable or inherit from some ORM objects or even share them. These are all infrastructure concerns and should be defined separate from the domain model.

But, that is if you're looking for going for pure DDD and your project values scalability and performance over speed of initial development. Many times, mixing infrastructure concerns with your "domain model" can help you achieve great strides in speed at the cost of scalability. The point is, you need to ask yourself, "Are the benefits of pure DDD worth the cost in the speed of development?". If your answer is yes, then here is the answer to your question.

Let's start with an example where your application begins with a domain model and it just so happens that the tables in the database match your domain model exactly. Now, your application grows by leaps and bounds and you begin to experience performance issues when querying the database. You have applied a few well thought out indexes, but your tables are growing so rapidly that it looks like you may need to de-normalize your database just to keep up. So, with the help of a dba, you come up with a new database design that will handle your performance needs, but now the tables are vastly different from the way they were before and now chunks of your domain entities are spread across multiple tables rather than it being one table for each entity.

This is just one example, but it demonstrates why your domain model should be separate from your persistence model. In this example, you don't want to break out the classes of your domain model to match the changes you made to the persistence model design and essentially change the meaning of your domain model. Instead, you want to change the mapping between your new persistence model and the domain model.

There are several benefits to keeping these designs separate such as scalability, performance, and reaction time to emergency db changes, but you should weigh them against the cost and speed of initial development. Generally, the projects that will gain the most benefit from this level of separation are large-scale enterprise applications.

UPDATE FOR COMMENTATORS

In the world of software development, there is Nth number of possible solutions. Because of this, there exists an indirect inverse relationship between flexibility and initial speed of development. As a simple example, I could hard code logic into a class or I could write a class that allows for dynamic logic rules to be passed into it. The former option would have a higher speed of development, but at the price of a lower degree of flexibility. The latter option would have a higher degree of flexibility, but at the cost of a lower speed of development. This holds true within every coding language because there is always Nth number of possible solutions.

Many tools are available that help you increase your initial development speed and flexibility. For example, an ORM tool may increase the speed of development for your database access code while also giving you the flexibility to choose whatever specific database implementations the ORM supports. From your perspective, this is a net gain in both time and flexibility minus the cost of the tool (some of which are free) which may or may not be worth it to you based on the cost of development time relative to the value of the business need.

But, for this conversation in coding styles, which is essentially what Domain Driven Design is, you have to account for the time it took to write that tool you're using. If you were to write that ORM tool or even write your database access logic in such a way that it supports all of the implementations that tool gives you, it would take much longer than if you were to just hard-code the specific implementation you plan on using.

In summary, tools can help you to offset your own time to production and price of flexibility, often by distributing the cost of that time to everyone who purchases the tool. But, any code including the code that utilizes a tool, will remain affected by the speed/flexibility relationship. In this way, Domain Driven Design allows for greater flexibility than if you were entangle your business logic, database access, service access, and UI code all together, but at the cost of time to production. Domain Driven Design serves Enterprise level applications better than small applications because Enterprise level applications tend to have a greater cost for the initial development time in relation to business value and because they are more complex, they are also more subject to change requiring greater flexibility at a reduced cost in time.

Keon answered 26/12, 2012 at 15:24 Comment(2)
This is a great answer. I'd like to throw in my own two cents - separating the domain model from persistence layer is desired most of the time, especially in enterprise, but, unfortunately, (I think) many enterprises, when they grow, never transition to separating domain from persistence because a lot of domain and business logic seeps into the persistence layer. I am mainly referencing all the extra tooling available that deals directly with the DB and bypasses the application which houses most of the domain logic. One big example is reporting.Bamboozle
@Bamboozle I agree with you for the most part. If an application is not designed with well-defined boundaries (regardless of the app architecture), domain logic may seep into the persistence layer. This is why deciding and adhering to an architecture is important. I disagree that reporting is an example of this. In fact, reporting is usually so different from the main concerns of the application that Martin Fowler decided it needed its own pattern called CQRS or Command Query Responsibility Segregation. Check it out here: martinfowler.com/bliki/CQRS.htmlKeon
V
25

In DDD, are persistence model and domain model different things?

In DDD you have the domain model and the repository. That's it! If inside the repository you will persist the domain model directly OR if you will convert it to a persistence model before persisting it, it's up to you! It's a matter of design, your design. The domain doesn't care about how models are saved. It's an implementation detail of the repository and it doesn't matter for the domain. That's the entire purpose of Repositories: encapsulate persistence logic & details inside it.

But as developers we know it's not always possible to build a domain 100% immune from persistence interference, even they being different things. Here in this post I detail some Pros & Cons of having the domain model completely free and isolated from the persistence model.

Vulpecula answered 24/12, 2015 at 13:25 Comment(1)
I read a lot of articles about DDD but your short description is best of all. Thank you.Orellana
O
18

In DDD, are persistence model and domain model different things?

Yes, but that does not necessarily imply a different set of classes to explicitly represent the persistence model.

If using a relational database for persistence an ORM such as NHibernate can take care of representing the persistence model through mappings to domain classes. In this case there are no explicit persistence model classes. The success of this approach depends on that mapping capabilities of the ORM. NHibernate, for example, can support an intermediate mapping class through component mappings. This allows the use of an explicit persistence model class when the need arises.

If using a document database for persistence, there is usually even less need for a persistence model since the domain model only needs to be serializable in order to be persisted.

Therefore, use an explicit persistence model class when there is a complex mapping that cannot be attained with ORM mappings to the domain model. The difference between the domain model and the persistence model remains regardless of implementation.

Opaline answered 24/12, 2012 at 19:44 Comment(7)
Hmm, so I can use same classes as long as I can handle persistence the right way. When it is not enough, I can rethink and add some new classes instead of domain classes for persistence. Did I get it right?Hardeman
Yes, and persistence-specific classes can come in a variety of flavors. They can either be a simple DTO between the database and the domain or they can be part of an existing mapping infrastructure such as NHibernate.Opaline
I think, it's clear now, thank you very much for your attention and help.Hardeman
I think something must be added here. A domain model should always be concerned with domain BEHAVIOR, while a persistence model, at most, it stores domain object STATE. The persistence models what you want to store from an object and that data will be used to restore the object. You can use the ORM entities as a base for domain entities but then you have to coherce the object to obey ORM needs. Basically, your domain object will have to care for ORM needs too, besides its real purpose. And then you're on a slippery slope.Impiety
@Impiety "Basically, your domain object will have to care for ORM needs too" I'm not following you here, can you provide an example?Default
@Default I suppose things like having a no-args constructor, making some fields non-final, allowing them to be initially null and injected by the ORM tool, handling data persisted with an earlier version of the application, ...Prevaricator
The top answer to this question says the domain model shouldn't be serializable; this one says it totally can be. I think that says it all when it comes to DDD. It's confusing as heck because even people with experience of it can't really agree on how to do things "properly".Patrizio
P
0

Since there are lots of frameworks based on MVC.

I assume you were trying to implement ddd with MVC. The model in MVC should belong to the Infrastructure layer and plays the role of repository inside persistence.

the model in ddd is inside the Domain layer which I prefer to name as aggregate or entity(distinguish with 'Model' with MVC). So the aggregate is actually pure model and event attachment/raise (if it's needed), nothing else.

If that's true what would be the advantage of having separate persistence objects from domain objects?

one of the advantages of ddd is the isolation between layers. for instance, you have multiple data storage/hub like MySQL as the primary database and Elasticserch as the secondary. And you have to sync data between each data storage. Each data storage should have a repository that CURD data and presents it to the user. each repository just needs to focus on CURD and shouldn't present to the user directly(involved in the present layer) but aggregate needs to be there.

The controller and View belong to the Presentation layer. the repository shouldn't be present in view. And all the repository need to implement the same interface which is defined in the Domain layer.

Let's imagine the following scenario: you have to switch the default data storage on another one for a while(i.e. MySQL is during upgrade just get data from Elasticsearch), what you need to do is just shift the default repository from sqlRepository to ElkRepository and no need to change anything inside presentation layer(View template).

Polystyrene answered 13/3, 2023 at 15:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.