Требования приложения и способ его моделирования будут влиять на то, как вы это делаете.
(Примечание: я буду использовать AR для совокупного корня)
В вашем случае, если у вас есть LoanApplication AR , он должен содержать информацию о Заявителе и Свойстве .
Допустим, у каждого Кандидата будет что-то вроде уникального аккаунта , так что вы можете отслеживать, сколько кредитов имеет Кандидат .
В этом сценарии Заявитель будет сущностью и, вероятно, AR . Он будет иметь свой собственный репозиторий: ApplicantRepository . В этом случае необходимо Заявитель AR из вашего LoanApplication AR .
Это означает, что на первом шаге вашего мастера вы можете либо найти Кандидат , используя ApplicantRepository , либо создать новый. В случае создания нового вы можете создать и сохранить его на первом этапе. Позже вы можете ссылаться на Заявителя (по ссылке или по идентификатору) из Заявка на кредит
Если вы не хотите этого, тогда Кандидат может быть объектом значения , и его информация будет храниться в LoadApplication AR .
То же самое относится к свойству : вы можете иметь свойство сущности с PropertyRepository или просто хранить PropertyInfo объект значения до LoadApplication AR .
Еще одна важная вещь: у вас LoanApplication есть жизненный цикл . В зависимости от текущего состояния его инвариант может измениться. Это нормально иметь AR , который будет проходить через разные фазы. Взять хотя бы интернет магазины. Когда вы заказываете что-то, скажем, от Amazon, ваш заказ может быть одобрен или ожидающий рассмотрения (или в других штатах), и это является частью его жизненного цикла . Когда вы хотите завершить заказ, система может запросить платежные реквизиты перед отправкой.
В вашем компьютере вы можете создать жизненный цикл для LoadApplication , имея статус: Ожидание , SubmittedForApproval , Одобрено , Отклонено и т. Д. Также может потребоваться дополнительная информация о том, почему оно было Отклонено и т. Д.
Если вы хотите сохранить информацию о процессе создания LoadApplication , вы можете назначить статус, который отражает тот факт, что вы LoadApplication все еще находятся в процессе создания: В ожидании или InProgress . Таким образом, если ваше приложение падает в середине, оно может возобновить работу, получив LoadApplication и проверив его статус.
Вы можете добавить поведение в LoadApplication AR , связанное с его состоянием (например, оно не разрешает переход к Утвержденному состоянию, если оно не находится в SubmittedForApproval состоянии и не позволят изменить свойство , если оно не находится в состоянии InProgress (вы не хотите изменять свойство или заявителя , когда статус утвержден или отправлен для утверждения).
Реализация сохранения:
Если вы решили, что LoadApplication Aggregate будет содержать три объекта: LoadApplication , Заявитель и Свойство , то все эти объекты сохраняются и загружаются вместе, потому что совокупность является Транзакционной границей . Это руководство может помочь в реализации Save, но это может быть сложно.
Это будет зависеть от нескольких факторов:
Какая у вас база данных (SQL, MongoDB)?
Используете ли вы фреймворк (NHibernate, Mongoose) или нативный API (с использованием необработанного SQL)?
Так как только LoadApplicationRepository сохранит LoadApplication с Заявителем и Свойство , то проблем не будет, даже если Заявитель снова сохраняется в БД, поскольку в него не будет внесено никаких изменений. Вы будете переопределять существующие данные только теми же данными, что не очень круто для производительности, но это не проблема для вашей логики.
С другой стороны, если вы используете ORM, они могут обнаруживать изменения в объектах и генерировать только требуемый запрос для обновления только новых изменений в базе данных. В этом случае, если вы скажете, добавьте Свойство к LoadApplication , если это произойдет, и обновите только Свойство в базе данных.
Например, предположим, что вы используете базу данных SQL с (N) Hibernate или EntityFramewok, ваш ORM будет отслеживать изменения, которые было добавлено свойством, и генерировать SQL для вставки его в таблицу Properties в БД, но выиграл не генерировать вставку обновления для уже существующего заявителя , поскольку оно не изменилось.
Если вы пишете свою собственную логику, используя, например, сырой SQL, то вам придется написать логику, которая отслеживает изменения самостоятельно.
Один из способов - добавить коллекцию изменений в LoanApplicaton AR , которая будет содержать изменения / события (ApplicantAssigned, PropertyAssigned, SomethingChanged и т. Д.), Чтобы их можно было использовать в методе Save для генерации SQL на основе изменений. Когда вы сохраняете агрегат, вы можете очистить изменения.
Вот отличное эссе по моделированию агрегатов:
http://dddcommunity.org/library/vernon_2011/.
Вот пара событий в домене:
https://www.martinfowler.com/eaaDev/DomainEvent.html
https://lostechies.com/jimmybogard/2014/05/13/a-better-domain-events-pattern/