Лучшие практики с коллекцией объектов домена в DDD - PullRequest
1 голос
/ 21 апреля 2020

У меня есть следующий класс:

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

Я хочу сделать ту же операцию getPercent со списком объектов DomainClass без повторного кода. У меня есть 2 идеи, чтобы справиться с этим, но я не знаю, хороши ли они.

Идея 1 - Создайте сервис и выполните итерации по списку:

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
}

Идея 2 - Запрос операция в базе данных, заполнение объекта и вызов бизнес-метода

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();
}

Я читаю, что в DDD сущность должна обрабатывать себя как logi c, но в этом случае операции сбора, как это должно быть лечили?

Ну, если мои DDD базовые знания неверны. Я хотел бы знать хорошую статью / книги / пример DDD в java.

1 Ответ

1 голос
/ 21 апреля 2020

Как вы управляете своими сущностями? Используете ли вы какой-либо ORM?


Мое решение для такого рода операций заключается в создании класса, который управляет коллекцией объектов. Так, например:

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
}

Таким образом, вы можете повторно использовать код getPercent каждого класса, а также реализовать его конкретную c версию, которая будет использоваться коллекцией. Более того, коллекция может получить доступ к частным получателям пакета, если таковые имеются, DomainClass для выполнения этих вычислений. Таким образом, вы предоставляете не что иное, как функции, необходимые для создания ваших доменных объектов.

Примечание: это решение является жизнеспособным, если вы управляете своим постоянством без использования ORM. Или, если вы хотите использовать его, потребуется дополнительная работа для правильной настройки класса контейнера.

Некоторые ссылки:

https://www.mehdi-khalili.com/orm-anti-patterns-part-4-persistence-domain-model (я работаю с DM, отделенным от PM)

https://softwareengineering.stackexchange.com/questions/371344/why-not-use-an-orm-with-ddd (это то, что я делаю, перевод объектов Domain в DTO, которые будут сохраняться - это немного дополнительного кода для написания для коллекций, но после тестирования он всегда работает, и вы получаете домен, который имеет меньше помехи от ORM Framework)


Обновление после вопроса. Я использую шаблон Memento .

Хранение

My Domain Class имеет функцию, которая экспортирует все данные в объект Memento. Репозиторий принимает экземпляр домена, запрашивает Memento, а затем:

  • Я создаю SQL вставку / обновление (просто SQL с управлением транзакциями из Spring)
  • You может загружать вашу сущность JPA и обновлять ее информацией Memento (будьте осторожны, но если вы пишете тесты, однажды выполненные, они будут работать всегда - следовательно, тесты важны;))

Чтение

Для обратного, создавая экземпляр Domain из сохраненных данных, я делаю это:

  • на уровне персистентности, где реализован код репозитория, I ' Я расширил мой Memento (давайте назовем его PersistedMemento )
  • , когда мне нужно что-то загрузить, я создаю PersistedMemento и использую его для создания экземпляра Доменный класс
  • В моем доменном классе есть функция, которая позволяет строить объекты из Memento. Примечание: это не всегда может быть необходимо, но в моем случае основной конструктор имеет дополнительные проверки, которые невозможно выполнить, когда объект перестраивается из сохраненного. В любом случае, это упрощает перестройку класса Domain.

Чтобы защитить классы Домена от использования вне мира домена:

  • моим репозиториям требуется существующая транзакция, поэтому они не могут напрямую использоваться где-либо в коде
  • классы Memento имеют защищенные конструкторы, поэтому их можно использовать только в пакете Domain или пакете Repository. PersistedMemento также скрыт в пакете Repository, поэтому создавать экземпляры невозможно.

Примечания

Конечно, это не идеальное решение. Доменный класс имеет 2 функции, которые предназначены для поддержки не доменных требований. Класс Memento также можно разделить на подклассы, а экземпляр можно использовать для создания класса домена (но почему? Его гораздо проще построить с помощью конструктора по умолчанию). Но, за исключением этого небольшого количества загрязнения, домен остается действительно чистым, и я действительно могу сосредоточиться на требованиях к домену, не думая, как управлять постоянством.

...