2016-12-28 2 views
0

У меня есть экран, который представляет собой заголовок-деталь, Заголовок - это основная категория задания, а подробности - список вспомогательных категорий задания. Я много читал об Агрегатах и ​​их границах, но я столкнулся с проблемой. Мои требования: - Как смоделировать эти ???DDD: Как правильно настроить агрегаты для экрана основных данных?

  • Должен ли я использовать единый агрегат (который содержит как сущности JobMajorCategory будет корневым агрегат и JobMinorCategory будет сущностью внутри агрегата), так как они будут сохранены в той же транзакции или
  • Два Заполнители (один для JobMajorCategory и другой для JobMinorCategory), потому что нет никакой реальной инвариантом или бизнес-роль между ними

Примечание: - экран имеет кнопку Сохранить, которая сохранит все графа вместе (master + details) в одной транзакции. Кроме того, JobMinorCategory не может жить без родителя. Пожалуйста, посоветуйте мне, как правильно спроектировать эти агрегаты?

+0

Агрегаты имеют мало общего с экранами и кнопками. Я думаю, вы должны сначала сосредоточиться на своей доменной модели и как она ведет себя до визуализации любого типа ui. – henrikmerlander

+0

Да, я знаю, но пользовательский интерфейс, связанный с бизнес-кейсом и моим бизнес-кейсом, сказал, что оба заголовка и детали должны быть сохранены в одной транзакции. – roro2012

+0

«Сохранить» - это операция CRUD, и это то, что помутняет ваше мнение. Если вы только делаете CRUD, вам не нужно беспокоиться о AR, просто моделируйте транзакции и данные в случаях использования пользовательского интерфейса. – plalx

ответ

1

Вы должны посмотреть на создание модели просмотра или эквивалентного DTO, который удовлетворяет вашему пользовательскому интерфейсу. Это позволяет вам сосредоточить свой агрегат на домене, а затем вы можете загрузить представление через перевод совокупности. Я понимаю, что вы говорите, что ваш бизнес-прецедент говорит об аспекте «единой транзакции», но это техническая деталь.

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

Основываясь на том, что вы говорите, вам может понадобиться создать четкую границу между вашим доменом и вашим приложением. Как правило, это делается с помощью сервисов приложений. Эти «говорят» как приложение, так и домен, так что они могут разговаривать с доменом, но только с поверхностными DTO/моделями. Эффективная изоляция вашего домена предотвращает отток в домене, а затем изменения в пользовательском интерфейсе, который будет наиболее определенно изменяться чаще, чем сам домен, имеет изолирующий уровень.

Код и артефакты, которые находятся ближе к пользователю, будут отбираться чаще. Домен посвящен «истинам», которые относятся к тому, как работает бизнес. С этой целью ваш пользовательский интерфейс является только окном в ваш домен - или более соответствующим образом, часто, когда это представление является абстракцией вашего домена.

Редактировать, чтобы конкретно рассмотреть детали вопроса.

В том, что вы описали, я не знаю достаточно о домене, чтобы предоставить полный и точный ответ. Тем не менее, вы на правильном пути. Поскольку JobMinorCategory не может существовать без JobMajorCategory, справедливое предположение, что JobMinorCategory является либо объектом, либо объектом значения (если это просто текст, например, и не имеет другого реляционного влияния на другие JobMinorCategories). Вы можете использовать эту предпосылку для работы в «одной транзакции».

Для аргументации скажите, что у вас есть приложение MVC. Ваше сохранение может быть связано с общим действием «Сохранить».В свою очередь, этот контроллер может затем определить, что делать, исходя из полезной нагрузки. Если вы пометили JobMinorCategory как поставленную в очередь для удаления, на уровне ниже, чем контроллер, вы можете выполнять итерацию по элементам, собирать те, которые должны быть удалены, и регистрировать их для удаления в том, что вы используете для управления вашим подразделением Работа.

Домен не заботится о том, как вы это делаете в пользовательском интерфейсе. Но ваш домен может предоставить средства для удаления JobMajorCategory, который удалит все JobMinorCategories. Когда вы переходите к совокупности, сама по себе, именно там должна жить бизнес-логика. Например, ваша JobMajorCategory должна иметь метод для DeleteJobMinorCategory() и AddJobMinorCategory(). Затем, когда состояние вашего агрегата отражает состояние, в котором вы хотите, вы будете упорствовать в этом агрегате с более высокого уровня. В зависимости от вашей общей архитектуры это может быть из службы домена.

Существует несколько способов сделать это, варьируя по сложности. Не зная больше, я бы предположил, что на бэкэнд вы захотите загрузить свой фактический агрегат и применить изменения в зависимости от действия пользователя. Итак, если вы могли бы проверить вашу модель, чтобы убедиться, что пользователь удалил JobMinorCategory, вы могли бы получить свою доменную службу для получения последней версии Aggregate, вызвать метод RemoveJobMinorCategory() (где будет находиться ваша бизнес-логика) и один раз этот метод завершен, тогда у вас будет доменная служба, сохраняющая измененный агрегат. На основе модели вы можете обнаружить, что это произошло несколько раз - то есть пользователь удалил более одной JobMinorCategory. Это тоже хорошо. Вы просто сделаете несколько вызовов RemoveJobMinorCategory(), а затем сохраните их.

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

Итак, если вы используете что-то вроде Entity Framework (которое содержит единицу работы в контексте), вы должны загрузить свою сущность, применить изменения через методы для объекта (частичные классы - это один из способов сделать это) , а затем сохраняйте его, как только вы закончите. Это позволяет делать столько, сколько вы хотите, в одной транзакции. Как правило, вы захотите ограничить транзакцию одним агрегатом или, по крайней мере, одним ограниченным контекстом.

Создание будет работать точно так же. Вы создаете экземпляр агрегата JobMajorCategory и добавляете объекты JobMinorCategory с помощью методов, которые инкапсулируют логику, связанную с их добавлением. После того, как вы закончите создание и/или изменение, вы совершаете эти изменения.

+0

Привет, Джозеф, Спасибо за вашу помощь. Не могли бы вы сказать, неправильно ли мое первоначальное моделирование или нет. Сначала я создал два агрегата: - Один для заголовка, а другой для деталей. Это верно? – roro2012

+0

Обратите внимание, что нет никаких инвариантных ролей между заголовком и строками, но если я удалю заголовок, все строки будут удалены. – roro2012

+0

, что означает, что второстепенная категория не может жить без их родительской младшей категории. – roro2012

Смежные вопросы