javadesign-patternsdomain-driven-design

Best practices with a domain object collection in DDD


I have the following class:

public class DomainClass {
    private Integer value;
    private Integer total;
    private Integer month;
    public Double getPercent(){/*Business logic*/}
}

I want to do the same getPercent operation with a list of DomainClass objects without repeat code. I got 2 ideas to handle that but I don't know if they're good ones.

Idea 1 - Create a service and iterate the list:

public class DomainObjectService{
....
public Double getPercent(List<DomainClass> list){
    double value, total;
    for(DomainClass d : list){
        value += d.getValue();
        total += d.getTotal();
    }
    // do percent operation
}

Idea 2 - Query operation at database, fill object and call the business method

public class DomainObjectService{
....
public Double getPercent(){
    double value, total;
    .... query data with sql and set the above variables

    // do percent operation
    return new DomainBusiness(value, total).getPercentage();
}

I'm reading that in DDD a entity should handle itself logic but in this case of a collection operation how it should be treated?

Well, if my DDD base knowledge is wrong. I would like to know good article/books/example of DDD in java.


Solution

  • How do you manage your entities? Do you use any kind of ORM?


    My solution for this kind of operations is to build a class that manages the collection of object. So, for example:

    public class DomainClasses{
       private final List<DomainClass> domainClasses;
    
       ....
    
       public Double getPercent(){
          // manage the percent operation   ...
          // ... on all the members the way ... 
          // ... your business is expected  ...
          // ... to do it on the collection
    
          return something;
       }
    
       // class initialization
    }
    

    In this way you can reuse the getPercent code of each class, but also implement a specific version of it to be used by the collection. Moreover, the collection could access to the package private getters, if any, of DomainClass to make this calculations. In this way you expose nothing else than just the functions that you need to build your domain objects.

    Note: this solution is viable if you manage your persistence without any ORM. Or, if you want to use it, it will require additional work to configure correctly the container class.

    Some links:

    https://www.mehdi-khalili.com/orm-anti-patterns-part-4-persistence-domain-model (I work with a DM separated from the PM)

    https://softwareengineering.stackexchange.com/questions/371344/why-not-use-an-orm-with-ddd (is what I'm doing, translating the Domain objects to DTOs that will be persisted - it's a bit of extra code to write for collections, but once is tested it works, always, and what you get is a domain that has less no interferences from ORM framework)


    Update after question. I use the Memento pattern.

    Storing

    My Domain Class has a function that export all the data in a Memento object. The repository takes a Domain Instance, asks for the Memento and then:

    Reading

    For the reverse, building a Domain instance from the saved data, I do this:

    To protect the Domain classes from being used outside the world of the domain:

    Notes

    Of course is not the perfect solution. The Domain Class has 2 functions that are there to support a non domain requirement. The Memento class could also be sub-classed, and an instance could be used to build the Domain Class (but why? It's much more simpler to build it with the default constructor). But, except this small amount of pollution, the domain stays really clean and I can really concentrate on the domain requirement, without thinking how to manage the persistence.