Дизайн, управляемый доменом, - постепенное сохранение из пользовательского интерфейса - PullRequest
0 голосов
/ 15 апреля 2019

Я новичок в DDD, читаю литературу по нему, но испытываю трудности с применением некоторых понятий. Я представляю упрощенный вид приложения, которое я создаю. Это система подачи заявлений на получение ипотечного кредита. Интерфейс пользователя имеет шаги, аналогичные мастеру для сбора информации, например, шаг 1 - сбор информации о заявителе, шаг 2 - сбор информации о свойствах, шаг 3 - получение решения об утверждении или отклонении. Каждому приложению присваивается уникальный идентификатор на шаге 1. Моя задача состоит в том, чтобы смоделировать пошаговое сохранение с каждого шага. Кредитная заявка - мой совокупный корень. Из того, что я прочитал, у каждого корня есть только один репозиторий, и весь корень должен быть сохранен вместе, чтобы он был действительным. Однако пользовательский интерфейс собирает информацию постепенно, и на каждом шаге сущность приложения действительна - когда я сохраняю данные с шага 1, мой объект заявки на кредит действителен. При сохранении данных из шага 2 объект заявки на кредит остается действительным. Ищете несколько советов о том, как разработать Api и репозиторий здесь? Если agg root действителен на каждом шаге и может быть сохранен небольшими шагами, то какой смысл в одном api save? Должны ли быть 3 отдельных API, доступных для пользовательского интерфейса, и эти 3 API вызывают 3 отдельных класса репо или 1 API вызывают 3 отдельных метода в одном репо? Я использую Entity Framework для сохранения в БД. Спасибо.

1 Ответ

0 голосов
/ 15 апреля 2019

Требования приложения и способ его моделирования будут влиять на то, как вы это делаете.

(Примечание: я буду использовать 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/

...