DDD When should I create a domain object and a persistence object instead of using a persistence object as a domain object?
Asked Answered
B

1

10

As I work with my understanding of Domain Driven Design I find I have a rule that seems to work, though I would like to see if it is overkill and also would like to see other perspectives of the same situation.

My question is this: "When should the domain model and persistence model be contained in separate objects?" My language of choice is Java at the moment and I am using Spring Data's repository model.

I see three main answers to my question.

  1. Always use separate domain objects from persistence objects.
  2. Use separate domain objects only when putting domain methods (behaviors) on persistence objects is not practical.
  3. Use persistence objects as domain objects in all cases.

In order to ask questions about DDD I find that I have to use an example bounded context since I don't yet know enough about DDD to ask in a more abstract way.

Here is my illustrative bounded context: say I have a law codification system with the following business rules:

  1. Each law on the books must be classified.
  2. Each law has an identifier with two parts, a codification number prefix and a codification coassign suffix. (Example: 100-0100, 599-2030).
  3. There are multiple legal jurisdictions that are using the law codification system and they should be able to make their own coassigns but the codification prefixes are global and must be the same across all jurisdictions to facilitate general comparability.
  4. the codification number prefixes are grouped into broad codification categories. Codification categories have a number range, such as 100-199, 200-299, 700-799, etc.

To express this bounded context as a persistence model I have the following:

table: codification
fields: chart_code, prefix, coassign, codification_category

table: codification_chart
fields: chart_code, jurisdiction_description

table: codification_category
fields: category, low_category_number, high_category_number, description

table: global_codification
fields: prefix, coassign, codification_category

I know, I should be starting from the domain model first. I have a persistence model and a domain model

In my domain model I have three domain objects

public Codification {
    private String prefix, coassign;
    codificationCategory codificationCaegory; // an enum type
    public Codification(...) { // set private vars }
    // getters for private variables
}

public CodificationChart {
    private List<Codification> chartCodifications = new ArrayList<>();
    private String chartCode;
    // public constructor to initialize private variables
    // getters for private variables
    public Codification addCodificationToChart(Codification){...}
    public void removeCodificationFromChart(Codification){...}
    public boolean checkCodificationInChart(Codification){...}
}

public enum CodificationCategory {
    CIVIL, CRIMINAL, PROPERTY, CORPORATE, FAMILY, CONSUMER, ETHICS, BANKRUPTCY;
}

ORM Objects:

JPA Mappings of the tables mentioned earlier with the "Entity" suffix added to their table names. 
They are omitted for brevity. 
Each one contains getters and setters like JPA Pojos do. 
If someone asks for the Persistence objects code I will post it.

The only point at which my domain objects know about the persistence model is in my factory object CodificationChartFactory, which has the repository interfaces I am using to interact with the ORM objects mentioned earlier. This factory is the only part of the domain that uses the persistence repositories, thus the only part that interacts with the persistence layer.

Is creating a separate domain model here wasteful effort? I can see how it is possible for me to put my CodificationChart behaviors on a Persistence object. It just somehow feels wrong to put those behaviors on a persistence object who's only job is to retrieve a record from the database.

I definitely stand to be corrected.

Beneficence answered 21/10, 2015 at 20:47 Comment(0)
T
9

Both approaches are correct and are a matter of taste from a design point of view. Some people don't want their domain object to have absolutely anything to do with persistence and do create an extra layer of Entity objects... some people don't think this is a major problem and are happy to go ahead and use the domain objects as the persistence objects.

Personally (and subjectively), I think that using JPA and have an extra layer of Entity objects is the wrong approach. The aim of ORMs like Hibernate is to be a bridge between Object and Relational models (I know it's in the name :). I think a way better approach, in the case one wants to keep things separated, is to use something like mybatis or plain SQL, but definitely not JPA... otherwise it's just adding complexity for the sake of complexity (JPA is not the easiest framework to learn)

I'm happy to live with the mix and annotate my domain objects. As I know it makes the persistence easier to manage... but at the same time, I feel very comfortable with Hibernate/JPA and been using it for 10 years :).

I had a very similar question 3 years ago, which I posted on programmers site - Do ORMs enable the creation of rich domain models?

Thermograph answered 21/10, 2015 at 21:3 Comment(3)
thanks for the perspective. I was a little afraid to mix domain and persistence because I thought other professionals didn't do that. I will try it and see how I like it. I agree that having the separation in the case of using JPA definitely seems like another layer of complexity that is not strictly necessary. I like how you have answered more towards keeping things together. I'd like to see an answer where someone advocates separating them so I can see if there is any good reason to do so in the case of using JPA.Beneficence
This is also exactly where I stand, thanks Augusto for putting it better than I would have :) Also, I don't know a lot about Java but isn't there an alternative to "intrusive" JPA annotations where mapping details would be externalized to some kind of "fluent mapping" file (like good old days XML ORM configuration but in code) ? It would help a lot with persistence ignorance IMO.Prindle
@Prindle Hibernate still supports the XML mappings (many years ago I had colleagues who preferred this approach, so there would be no static association between the production code and the mapping). I don't know of any extension that might allow to define the mapping in a nice DSL... but it might be a matter of building one (unfortunately, it would be ORM specific). Last... I've never seen an application where data access was 100% transparent in Java, it always is a leaky abstraction.Thermograph

© 2022 - 2024 — McMap. All rights reserved.