Предположим, что Сотрудник может приобретать продукты, используя своего рода «социальные кредиты», предоставляемые его Работодателем.
У меня есть сущность CreditsAccount, которая содержит сумму кредитов и ссылку на сотрудника, и я хочу смоделировать Purchase как сущность, которая содержит ссылку на CreditsAccount и продукт, который покупается.
Если у меня есть метод PurchaseRepository.save(), как я могу предотвратить сохранение Purchase без вывода из CreditsAccount?
Решение 1
Покупка является субъектом совокупного CreditsAccount, у меня нет PurchaseRepository, но вместо этого есть метод в учетной записи, такой как CreditsAccount.AddPurchase(purchase), который выполняет внутреннее снятие средств. Когда я сохраняю CreditsAccount с CreditsAccountRepository.save(account), я также сохраняю покупку в соответствующей таблице.
Но это означает, что каждый раз, когда я загружаю CreditsAccount для совершения новой покупки, я также должен загружать список покупок в этой учетной записи, верно?
Решение 2
Я создаю новую сущность PurchaseTransaction, которая содержит ссылку на CreditsAccount и Продукт, и предлагаю такой метод, как PurchaseTransaction.commit().
При фиксации он фактически производит снятие средств со связанной учетной записи, основываясь на цене Продукта, и его внутреннее состояние переключается с uncommitted на committed.
Затем у меня есть PurchaseTransactionRepo.save (PurchaseTransaction), который:
В этом случае PurchaseTransactionRepo предлагает только метод записи в базу данных, поскольку на самом деле PurchaseTransaction действительно не принадлежит какой-либо таблице, в то время как PurchaseRepository доступен только для чтения и предлагает только методы для получения «совершенных» покупок.
Что мне не нравится в этом решении, так это наличие репо, которое на самом деле создает своего рода логику проверки состояния PurchaseTransaction (зафиксировано или нет), а также вводит в заблуждение то, что Uncommitted PurchaseTransaction на самом деле не сохраняется.
Можете ли вы предложить мне другие решения, соответствующие концепции DDD?
Некоторый контекст: не настоящее приложение, а упражнение по ката, в котором мне нужно провести рефакторинг с анемичной области на более богатую. В анемичном есть сервис, выводящий счет и сохраняющий покупку за одну транзакцию. Затем я могу получить список покупок с помощью вызова API. Я хочу смоделировать его с помощью богатых сущностей и «принудительно» сделать недопустимые состояния «непостоянными».





Purchase кажется хорошим кандидатом для саги, которую можно рассматривать как сущность, представляющую процесс. Без дополнительного контекста, я бы смоделировал его аналогично тому, как платежи часто обрабатываются в реальном мире (извинения за саму CQRS / антропоморфизацию по принципу актора) и имеет покупки в четырех состояниях: открытые, завершенные, профинансированные, просроченные и завершенные. .
как только покупатель узнает предметы, которые будут приобретены, и их стоимость (а), он может быть завершен, что переводит его в завершенное состояние и предотвращает будущие обновления предметов и стоимости. Сохраняется в этом состоянии.
Затем он пытается зарезервировать кредиты со счета сотрудника с указанием крайнего срока для завершения вывода или исчезновения резервирования. В случае успеха он переходит в состояние «профинансировано» и сохраняется.
У меня, вероятно, было бы какое-то другое сканирование процесса (поскольку мы здесь не занимаемся поиском событий) для покупок, которые финансируются и влияют на фактическое снятие средств, что позволяет получать покупку компонентом выполнения, а также сохранять покупку в состояние "завершено" (есть много вариантов, что делать, если срок покупки истек.
Контекст таков: не настоящее приложение, а упражнение ката, в котором мне нужно провести рефакторинг с анемичной области на более богатую. В анемичном есть сервис, выводящий счет и сохраняющий покупку за одну транзакцию. Затем я могу получить список покупок с помощью вызова API. Я хочу смоделировать его с помощью богатых сущностей и «заставить» недопустимые состояния быть «нестабильными». Ваше решение подходит для реального производственного сервиса, но для простого ката я ищу что-нибудь попроще (если возможно).