DDD - применение правил, которые должны знать о множественных корнях - PullRequest
0 голосов
/ 15 октября 2018

Я новичок в DDD и в настоящее время смотрю на перестройку существующего приложения, начав с небольшого подтверждения концепции, пока я все еще нахожу свой путь с DDD.Мои вопросы здесь касаются лишь небольшой части модели предметной области, поэтому в настоящий момент она может показаться слишком упрощенной.

Это приложение для планирования работы медсестер, которые посещают пациентов в их домах.Таким образом, ясно, что «Пациент» - это один AggregateRoot, а «Медсестра» - это другой AggregateRoot.Нет прямой связи между пациентом и медсестрой, за исключением тех случаев, когда медсестре назначено посещение пациента с помощью объекта «Назначение».

Теперь объект назначения может легко принадлежать как пациенту, так и медсестре AR, или даже оба видят, что назначение является связующим звеном между ними.Таким образом, я также назначаю встречу в АР.Итак, первый вопрос:

1) Это моделирование звучит правильно?Первоначально я пытался добавить коллекцию сущностей Назначения в AR каждого пациента / медсестры, но поскольку он действительно принадлежит обоим, имеет смысл быть его собственным AR.Затем я подумывал добавить список идентификаторов встреч под AR медсестры / пациента, чтобы связать их с назначениями, но это означало бы, что транзакция по сохранению встречи должна затрагивать сразу несколько AR, что, как я могу сказать, подсказывает.плохой агрегатный дизайн.

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

2) Как бы вы пошли в соблюдении таких правил, которые касаются нескольких разных AR?Очевидно, что правила можно было бы легко применять, и они были бы самодостаточны, если бы назначения были вложенным набором в рамках АР пациента или медсестры.Это заставляет меня задаться вопросом, правильное ли мое моделирование.

Я много читал о BC и Saga / Process Manager, но для меня это все часть одного BC, поэтому я не уверен, что мне нужновсе, что сложно.Допустимо ли просто иметь CommandHandler, который загружает несколько объектов AR и использует их состояние, чтобы определить, можно ли создать встречу или нет?

Если это так, и связать с Q1 выше (при условии, что я неt хранит список идентификаторов назначений под AR медсестры / пациента), модель считывания - единственный способ легко найти встречи, принадлежащие соответствующей медсестре / пациенту, - так что также допустимо применение бизнес-правил, основанных на состояниичитать модель, а не AR из хранилища?

Надеюсь, это имеет смысл, и заранее спасибо!

Ответы [ 4 ]

0 голосов
/ 28 февраля 2019

Если вы хотите немедленной согласованности, единственный чистый способ - это иметь один большой агрегат в доменной модели.Чтобы избежать несвязанных оптимистичных исключений параллелизма, вы можете попытаться разделить совокупность в реализации репозитория домена.

0 голосов
/ 15 октября 2018

Это моделирование звучит правильно?

Нет (но это не твоя вина - литература отстой).Ваши агрегаты будут представлять информацию, а не людей, которые перемещаются в реальном мире.Графики ротации, дежурные списки, это те вещи, которые могут быть совокупными.

Например:

Медсестра не может быть в нескольких местах одновременно, поэтомумы не можем назначить встречу одновременно с назначением другой медсестры

Это не ограничение для медсестры, это ограничение расписания .

«В 9 утра медсестра (id: 12345) должна посетить пациента (id: 67890)» - запись в расписании.Совершенно просто управлять всеми записями расписания вместе. Представления расписания, возможно, также должны включать дополнительную информацию о медсестре или пациенте, поэтому представление может объединять дополнительную информацию.

Расписание становится собственным "агрегированным" с использованием идентификаторов корреляции.чтобы включить объединения с другой информацией.

Будет ли расписание "NurseSchedule" или общесистемным "расписанием"?

Это, вероятно, что-то специфическое для использованияслучай планирования медсестер.В зависимости от домена данный график может охватывать несколько медсестер и пациентов.

0 голосов
/ 28 февраля 2019

Совокупный корень определяет границу согласованности, которая не должна быть отдельной транзакцией в базе данных.Вопрос о том, должна ли быть одна или несколько транзакций, является проблемой производительности / инфраструктуры и должен решаться при реализации репозитория, а не в модели предметной области.Нельзя даже ожидать, что совокупный корень модели предметной области и модели постоянства совпадают.Если ваш домен требует согласованности во всех посещениях, и вы должны предотвратить любые конфликты, то смоделируйте агрегат синглтона (назовем его «Расписание»), который знает обо всех медсестрах и пациентах и ​​применяет все правила согласованности.

Одной из возможных реализаций репозитория Schedule будет создание сущностей для медсестер и пациентов только для сохранения.Получение агрегата расписания означало бы загрузку всех сущностей «Медсестра» и «Пациент», поэтому некоторые стратегии кэширования могут повысить производительность.Хранение измененного агрегата расписания будет включать оптимистический параллелизм в измененных сущностях медсестры и пациента, что приведет к снижению конфликтов версий.Как вы уже заметили, Saga / менеджер процессов кажется излишним.Я бы даже пошел дальше и сказал, что сага рассеет логику предметной области и начальное намерение.Конечно, если домен не обеспечивает согласованность всех посещений в любое время, то вы имеете дело с возможной согласованностью.Тогда имело бы смысл работать с агрегатами Nurse и Patient на уровне домена и внедрять диспетчер процессов.

0 голосов
/ 15 октября 2018

Допустимо ли просто иметь CommandHandler, который загружает несколько объектов AR и использует их состояние, чтобы определить, можно ли создать встречу или нет?

Нет, нет, если вы хотитеследовать подходу DDD.Агрегат не должен быть меньше транзакции, Агрегат является границей транзакции.

Из того, что я вижу, у вас есть следующие бизнес-инварианты:

  1. медсестра не можетбыть более чем в одном месте одновременно, поэтому мы не можем назначить встречу одновременно с назначением другой медсестры

  2. возможно только одно ожидающее назначениена пациента

Эти два правила могут строго соблюдаться только в том случае, если медсестра и пациент принадлежат к одному и тому же агрегату.То есть, у вас должен быть большой Агрегат, если вы хотите, чтобы оба правила соблюдались, несмотря ни на что.

Но наличие такого большого Агрегата может показаться неправильным.Есть кое-что, что вы можете сделать: компромисс: какое из двух правил может быть применено в конечном итоге последовательным образом?После того, как вы обсудите со специалистами по бизнесу и представите ему / ее последствия для бизнеса, вы выбираете один из них, а затем создаете Saga / Process Manager, который обнаруживает такое недопустимое состояние, исправляет его и / или уведомляет кого-либо о необходимости исправить его вручную.

Если это так, и, связавшись с Q1 выше (при условии, что я не храню список идентификаторов встреч под AR медсестры / пациента), модель чтения - единственный способ легко найти встречи, принадлежащиесоответствующая медсестра / пациент - так допустимо ли также применять бизнес-правила, основанные на состоянии модели чтения, а не AR из хранилища?

Saga / Process manager использует old данных (в конечном итоге непротиворечивые обновленные данные) для отправки правильных команд в агрегаты, точно так же, как в моделях чтения.Таким образом, у вас может быть Saga, поддерживающий приватное состояние (более безопасное / более чистое решение), или разрешите запросить каноническую Readmodel для поиска недопустимых случаев (более быстрое / более грязное решение).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...