Domain-Driven Design – Understanding DDD with Hibernate ORM

domain-driven-design

I've reading about Domain Driven Design and Anemic models.

I generally work with an ORM such as Hibernate, and I'm struggling to understand in DDD what a business model can and can't do.

For example, if I have a Customer object, I would need to pass this off to a Service class in order to have it persisted to the database as it's not advised that you inject your ORM classes (repositories) into the domain model, I'm fine with this.

The issue comes when I want to check that a Customer object is valid, some recommend that the Customer object must know this, but in order to know it needs to query your datasource to check for other matching customers (i.e. via the email address).

It seems that behaviour needs to be on the Customer object itself, but what do you do when the behaviour requires data from the database? Do you pass that behaviour off to a Domain Service class?

EDIT:

Or, to put it another way, lets say we have a Customer and Film, on the Customer object we have a behaviour watch(Film). There's a business rule that states that a customer can only watch one new film per month. I would place a rule in the watch(Film) method to handle this. The problem is that the Customer object would need to access the datasource to get a list of all films the user has watched, determine how many have been watched and also check to see if the current film is one of them, and if so allow it to be watched as it's not a new film to the Customer, how would it do that?

a) when you create the Customer object, create properties to store a list of films watched this month
b) create a Service class to handle this rule so it can query the data source on the fly rather than having the data leaded eagerly?

With option a), I'd be concerned about bloating the Customer object will data that is only required for a single specific use case, and it seems sensible to me to only grab the data required when it's actually required.

This is a hypothetical situation, I'm trying to understand how to apply domain driven design.

Best Answer

Your understanding of the problem in terms of DDD is being obfuscated by your focus on your data model (database) instead of the behavior of the system (domain).

To reiterate, the purpose of DDD is to model the behavior of a system such that the result is a useful abstraction of its functional requirements. What the above means is that a properly designed domain is modeled according to the behavior of the system, not the data. The single biggest pitfall developers run into when embarking on DDD is to start by using a data model as a domain model, because the data is hardly ever a good starting point when trying to model a system’s functional requirements.

What does the above mean? It means that you need to slice up your data model vertically according to behavior. In practical terms, it means that it is unlikely that there will be a domain entity named Customer. The reason is because Customer doesn’t denote much behavior and likely contains too much knowledge. What do your Customers do? Buy things? Buyer. View things (this one’s for you)? Viewer. Manage a website account? AccountManager. You get the idea.

The point is that the properties of the above domain entities do not necessarily map directly to a single database table (and in some cases use fields from the same table). Each Buyer might have a collection of previous OrderReceipts. Each Viewer has a collection of Screenings containing details like MovieId, Location, Datetime, DeviceId, etc for each time they watched something. And AccountManager might have Username and Password. And ALL of the above might have the same CustomerId.

The most important thing to understand about the above entities is that each one represents the single and unambiguous authority responsible for protecting invariants that may apply to the data for which it holds. Follow that rule and you are golden.

In your case, a Viewer is just an aggregate responsible for protecting your viewership rules. It contains just enough extra data necessary to enforce your business rules. In this case a collection of Screening value objects from the last month (or maybe even less data ScreeningCount). Does that make sense?