Как вы управляете своими сущностями? Используете ли вы какой-либо 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 также можно разделить на подклассы, а экземпляр можно использовать для создания класса домена (но почему? Его гораздо проще построить с помощью конструктора по умолчанию). Но, за исключением этого небольшого количества загрязнения, домен остается действительно чистым, и я действительно могу сосредоточиться на требованиях к домену, не думая, как управлять постоянством.