DDD - Является ли модель анемичного домена антипаттерном? Должны ли мы использовать богатые доменные модели? [закрыто]

11

Модель анемичной предметной области была подвергнута давней критике Эвансом и Фаулером , поскольку она явно идет вразрез с объектно-ориентированными принципами и т. Д. Сообщество DDD четко согласуется с этими утверждениями.

Однако в последние годы раздавались голоса, утверждающие, что это вовсе не антипаттерн и что это пример следования принципам SOLID.

Я работал много лет, используя Spring Framework. Каждый проект в каждой компании всегда имел уровень обслуживания, содержащий бизнес-логику, используя репозитории, которые работают на анемичных моделях (сущностях JPA). Более того, большинство образцов, даже официальных от Spring, демонстрируют этот способ работы.

Мои вопросы: анемичная модель предметной области все еще считается антипаттерном? Мы все делали вещи (относительно DDD) неправильно? Не думаете ли вы, что наличие моделей Rich Domain нарушает принципы SOLID?

созависимых
источник
2
« Анемия модель предметной области до сих пор считается антипаттернами? ». По некоторым, да. Другие, в том числе и я, рассматривают его как предпочтительный способ написания кода большую часть времени, но если вам подходит RDM, используйте его. Таким образом, голосование, чтобы закрыть это как чисто основанное на мнении.
Дэвид Арно
1
Это был бы фантастический вопрос для дискуссионного / дискуссионного форума; но в настоящее время нет авторитетного ответа. Мы предпочитаем вопросы, на которые можно ответить, а не просто обсудить.
VoiceOfUnreason

Ответы:

9

ADM - хороший шаблон для решения распределенных сервисов, таких как микросервисы. Он подходит для многих современных бизнес-кейсов.

Рассмотрим, есть ли у нас объект Order Domain. При подходе ООП мы бы добавили Order.Purchase () Order.Cancel () и т. Д. Это будет хорошо работать в настольном приложении, где мы храним заказы в памяти и выполняем несколько операций с одним экземпляром.

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

PurchaseSystemOrder.Purchase()

а также

CancelSystemOrder.Cancel();

Единственное, что эти объекты разделяют, это структура данных свойств.

По мере того, как вы добавляете все больше и больше микросервисов, вы получаете десятки типов ордеров. Он больше не имеет смысла говорить о качестве ордена в качестве объекта домена, несмотря на то, его же концептуальном порядке , который обрабатывается всеми этими системами.

Гораздо разумнее иметь модель Anemic Order, которая просто инкапсулирует только данные и соответственно переименовывает ваши сервисы:

PurchaseService.Purchase(Order order)

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

Фаулер и Ко происходят из монолитной системы, в их мире подход ADM означал бы одно приложение, в котором все эти отдельные службы были бы созданы в памяти, а OrderDTO передавался и мутировал. Это было бы намного хуже, чем помещать методы в модель богатого порядка.

Но в распределенной системе существует много программ, каждая из которых требует только одного метода Order и запускает его по нескольким заказам, загружая каждую, запуская метод, а затем отбрасывая его. Для этого требуется только один Сервис и поток объектов данных.

Полное заполнение богатой модели, беспокоясь о требованиях и зависимостях всех методов только для вызова одного и последующего немедленного отказа от объекта, бессмысленно.

Кроме того, изменение одного из методов потребовало бы обновления всех распределенных компонентов, поскольку все они зависят от модели Rich для своей логики.

У меня нет места в моей базе кода для вещей, которые им не нужны

Ewan
источник
4
Я высказался против, потому что я думаю, что DDD особенно хорошо подходит для микросервисов именно благодаря концепции ограниченного контекста. Я думаю, что проблема с вашим ответом состоит в том, что концепция и класс вашего Заказа будут одинаковыми для каждого микро-сервиса, но я думаю, что это не является ни необходимым, ни точным.
Рибальд Эдди
Я не согласен, ADM может быть DDD, если вы позвоните своему CashSgg-аккаунту PurchaseService и сделаете его частью языка вашего домена
Ewan
можешь уточнить? Я всегда думал, что YMMV, когда ADM и DDD были в базе кода SOLID J2EE или .NET C # MVC EF.
Рибальд Эдди
Я имею в виду, что ограниченный контекст Order, PurchaseSystemOrder.Purchase () будет в значительной степени идентичным коду CashRegister.Purchase (Order order), это просто изменение именования в языке вашего домена. Модель расширенного домена означает, что оба метода - «Покупка» и «Отмена» в одном классе.
Эван
1
@RibaldEddie, в духе толщины книги «javaScript, хорошие части», я предлагаю это изображение как (не совсем серьезный) аргумент против использования DDD для реализации микросервисов;)
Дэвид Арно
3

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

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

DDD - превосходная парадигма для микро-услуг из-за концепции ограниченного контекста .

Остерегайтесь соблазна увидеть инфраструктурный код как часть вашего домена. Инфраструктурный код - это все, что вы не написали сами, или что-либо, связанное с платформой или библиотекой, которая взаимодействует со сторонней системой. Соединения с базой данных, почтовые программы SMTP, библиотеки ORM, время выполнения сервера приложений, все это - инфраструктура, и вы не должны включать или зависеть от этого в своем домене, если можете избежать этого.

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

RibaldEddie
источник
По поводу отделения кода инфраструктуры от домена. До сих пор я считал JPA Entities своим доменом, имеющим следующие прикладные уровни: controller -> service -> repository -> domain (JPA Entities). Каковы были бы правильные (или один из правильных) способов его моделирования в соответствии с вашей точкой зрения? Что-то вроде: контроллер -> богатая модель -> х? Как и где я буду иметь дело с транзакционностью? А как насчет JPA Mapping? Разве нам не пришлось бы дублировать нашу богатую модель с разделенными сущностями JPA?
созависимый
Сущность JPA - это простой старый объект Java. Отображение является частью инфраструктуры, но сам класс не должен быть. Если вы решите рассматривать его как часть инфраструктуры, вам следует рассматривать его как объект передачи данных, который используется на фабрике или в репозитории для создания сущности домена.
Рибальд Эдди
1

Богатый домен хорош, когда все сделано хорошо. Кошмар, когда нет. Анемичный домен - это всегда плохо. Но это знакомый удобный вид плохо.

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

Многие фреймворки пробираются в языковое пространство, пока вы не можете больше рекламировать работу как работу Java. Это работа на Java / Spring. Помимо того, что они заставляют вас зависеть от них, они превращают язык общего назначения в ублюдочную форму языка 4-го поколения.

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

Если ты в порядке с этим, тогда хорошо. Вы, конечно, не единственный.

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

У меня нет места в моей базе кода для вещей, которые ему не нужны.

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

candied_orange
источник
Я ценю ваш ответ и абсолютно согласен с тем, что некоторые фреймворки, такие как Spring или JPA-Hibernate, завоевали ландшафт Java. Однако также нельзя отрицать, что они предоставили множество хороших практик и упрощений, которые Java (JEE) вообще не рассмотрела или сделала неправильно. Я действительно с энтузиазмом отношусь к DDD и хотел бы понять все принципы, которые они рассказывают. опыт, какие платформы / языки / фреймворки лучше всего подходят для работы с чисто DDD-приложениями (с богатыми моделями доменов)? Какой-нибудь хороший пример Github вы знаете? Как вы говорите, я хочу делать вещи хорошо, а не соответствовать плохим практикам.
созависимый
Мы не делаем рекомендации по ресурсам здесь. Но я считаю, что правильный уровень инфраструктуры, который имеет дело с фреймворками, означает, что вы можете использовать любой вид, который вам нравится. Просто относись к ним как к библиотеке. Храните знания о них вне домена. Кроме того, не полагайтесь на магию. Не поддавайтесь желанию использовать вещи, которые вы не могли сделать сами. Потому что однажды вам может понадобиться.
candied_orange
Возвращаясь к исходной точке. А как насчет принципов SOLID? Богатые доменные модели предполагают много обязанностей, постоянство (JPA), бизнес-логику (необходимость иметь дело с транзакционностью) и т. Д. Анемичные модели, с другой стороны, заботятся только о постоянстве, имея отдельные службы, работающие с бизнес-логикой. Звучит также проще для тестирования. Что тут такого плохого?
созависимый
Главное, вы начинаете делать выбор дизайна на основе потребностей системы, а не семантических потребностей. Его тонкий, легко игнорируемый, стоимость не очевидна и трудно оправдать исправление. Короче говоря, это все равно что утверждать, что линии электропередач должны быть похоронены, а не на избирательных участках. Как только люди привыкнут к дешевой альтернативе, она вряд ли изменится. Даже когда ураганы выбивают власть.
candied_orange
1
Я собирался дать вам преимущество сомнения по поводу вашего заявления о том, что «богатая область хороша, когда все сделано хорошо. Кошмар, когда нет». Возможно, я просто никогда не видел, чтобы это было хорошо, но тогда вы делаете бессмысленное утверждение, что «анемичная область всегда плоха». Мнение ерунды делает твой ответ бесполезным. -1
Дэвид Арно