Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Подсказка
Это фрагмент из электронной книги «Архитектура микрослужб .NET для контейнеризованных приложений .NET», доступной в документации .NET или в виде бесплатного скачиваемого PDF-файла, который можно прочитать в автономном режиме.
Определите одну многофункциональную модель домена для каждой бизнес-микрослужбы или ограниченного контекста.
Ваша цель — создать единую единую модель домена для каждой бизнес-микрослужбы или ограниченного контекста (BC). Имейте в виду, однако, что бизнес-микросервис иногда может состоять из нескольких физических служб, которые используют одну общую модель домена. Модель домена должна отражать правила, поведение, бизнес-язык и ограничения единого Ограниченного контекста (Bounded Context) или бизнес-микрослужбы, которые она представляет.
Шаблон сущности домена
Сущности представляют объекты предметной области и в основном определяются их идентичностью, преемственностью и сохранением с течением времени, а не только атрибутами, составляющими их. Как говорит Эрик Эванс, "объект, в первую очередь определенный его удостоверением, называется сущностью". Сущности очень важны в модели домена, так как они являются основой для модели. Поэтому необходимо тщательно определить и разработать их.
Идентичность сущности может пересекать несколько микрослужб или Ограниченных Контекстов.
Та же идентичность (то есть то же самое значение Id
, хотя, возможно, не та же сущность домена) может быть смоделирована в нескольких ограниченных контекстах или микросервисах. Однако это не означает, что одна и та же сущность с одинаковыми атрибутами и логикой будет реализована в нескольких ограниченных контекстах. Вместо этого сущности в каждом ограниченном контексте ограничивают атрибуты и поведение, необходимые в домене ограниченного контекста.
Например, сущность покупателя может иметь большинство атрибутов человека, определенных в сущности профиля пользователя или микросервисе идентичности, включая идентичность. Но сущность покупателя в микрослужбе заказа может иметь меньше атрибутов, так как только определенные данные покупателя связаны с процессом заказа. Контекст каждой микрослужбы или ограниченного контекста влияет на модель домена.
Сущности домена должны реализовывать поведение в дополнение к реализации атрибутов данных.
Сущность домена в DDD должна реализовать логику домена или поведение, связанное с данными сущности (объект, к которому обращаются в памяти). Например, в рамках класса сущности заказа необходимо иметь бизнес-логику и операции, реализованные в качестве методов для задач, таких как добавление элемента заказа, проверка данных и общее вычисление. Методы сущности заботятся о инвариантных и правилах сущности вместо того, чтобы эти правила распространялись по уровню приложения.
На рисунке 7-8 показана сущность домена, которая реализует не только атрибуты данных, но и операции или методы с связанной логикой домена.
Рис. 7-8. Пример структуры сущности домена, реализующего данные и поведение
Сущность модели предметной области реализует поведение с помощью методов, то есть это не "анимическая" модель. Конечно, иногда можно иметь сущности, которые не реализуют логику в рамках класса сущностей. Это может произойти в дочерних сущностях в агрегате, если у дочерней сущности нет специальной логики, так как большая часть логики определена в корневом элементе агрегата. Если у вас есть сложная микрослужба с логикой, реализованной в классах служб, а не в сущностях домена, вы можете попасть в модель домена anemic, описанную в следующем разделе.
Богатая модель домена и анемичная модель домена
В своем посте AnemicDomainModel Мартин Фаулер описывает модель анимического домена следующим образом:
Основным симптомом анемической предметной модели является то, что сначала она кажется вполне реальной. Существуют объекты, многие именованные после существительных в пространстве домена, и эти объекты связаны с богатыми связями и структурой, которые имеют истинные модели предметных областей. Загвоздка в том, что когда вы изучаете поведение, вы осознаете, что у этих объектов практически нет поведения, что они представляют собой скорее мешки геттеров и сеттеров.
Конечно, при использовании анемичной доменной модели эти модели данных будут использоваться из набора сервисных объектов (традиционно называемых бизнес-уровнем), которые содержат всю доменную или бизнес-логику. Бизнес-уровень находится на вершине модели данных и использует модель данных так же, как данные.
Модель анемичного домена — это просто дизайн в процедурном стиле. Анемичные объекты сущностей не являются истинными объектами, так как они не имеют поведения (методов). Они хранят только свойства данных, поэтому не объектно-ориентированное проектирование. Поместив все поведение в служебные объекты (бизнес-слой), по сути, вы получаете spaghetti-код или транзакционные скрипты, и теряете преимущества, которые предоставляет доменная модель.
Независимо от того, является ли ваша микрослужба или ограниченный контекст очень простым (служба CRUD), анемичная модель домена в виде объектов сущностей, содержащих только свойства данных, может быть достаточно хорошей и может не оправдывать внедрение более сложных шаблонов DDD. В этом случае это будет просто модель сохранения данных, поскольку вы намеренно создали сущность исключительно для выполнения операций CRUD.
Именно поэтому архитектуры микрослужб идеально подходят для многоуровневого подхода в зависимости от каждого ограниченного контекста. Например, в eShopOnContainers микрослужба заказа реализует шаблоны DDD, но микрослужба каталога — простая служба CRUD — этого не делает.
Некоторые люди говорят, что модель анемического домена является антипаттерном. Это действительно зависит от того, что вы реализуете. Если создаваемая микрослужба достаточно проста (например, служба CRUD), следование анемичной доменной модели не является анти-паттерном. Тем не менее, если вам нужно решить сложность домена микрослужбы, в которой много постоянно изменяющихся бизнес-правил, анемическая модель домена может быть антипаттерном для этой микрослужбы или Ограниченного Контекста. В этом случае проектирование в виде богатой модели с сущностями, содержащими данные и поведение, а также реализация дополнительных шаблонов DDD (агрегатов, объектов значений и т. д.) может иметь огромные преимущества для долгосрочного успеха такой микрослужбы.
Дополнительные ресурсы
DevIQ. Сущность домена
https://deviq.com/entity/Мартин Фаулер. Модель домена
https://martinfowler.com/eaaCatalog/domainModel.htmlМартин Фаулер. Модель анемичного домена
https://martinfowler.com/bliki/AnemicDomainModel.html
Шаблон объекта Value
Как отметил Эрик Эванс, "Многие объекты не имеют концептуальной идентичности. Эти объекты описывают определенные характеристики вещи».
Для сущности требуется удостоверение, но в системе есть много объектов, которые не соответствуют шаблону объекта value. Объект значения — это объект без концептуальной идентичности, описывающий аспект домена. Это объекты, которые вы создаете, чтобы представить элементы дизайна, которые вас временно затрагивают. Вы заботитесь о том, что они есть, а не кто они. Примеры включают числа и строки, но также могут быть понятиями более высокого уровня, такими как группы атрибутов.
То, что является сущностью в микрослужбе, может не быть сущностью в другой микрослужбе, так как во втором случае ограниченный контекст может иметь другое значение. Например, адрес в приложении электронной коммерции может вообще не иметь идентичности, поскольку он может представлять только набор атрибутов профиля клиента, связанного с физическим лицом или компанией. В этом случае адрес должен классифицироваться как объект значения. Однако в приложении для энергетической компании, адрес клиента может быть важным для бизнес-домена. Поэтому адрес должен иметь удостоверение, чтобы система выставления счетов была напрямую связана с адресом. В этом случае адрес должен классифицироваться как сущность домена.
Человек с именем и фамилией обычно является сущностью, так как у человека есть удостоверение, даже если имя и фамилия совпадают с другим набором значений, например, если эти имена также ссылаются на другого человека.
Объекты значений трудно управлять реляционными базами данных и ORMs, такими как Entity Framework (EF), в то время как в базах данных, ориентированных на документ, проще реализовать и использовать их.
EF Core 2.0 и более поздних версий включают функцию "Принадлежащие сущности ", которая упрощает обработку объектов значений, как мы подробно рассмотрим далее.
Дополнительные ресурсы
Мартин Фаулер. Шаблон объекта value
https://martinfowler.com/bliki/ValueObject.htmlОбъект-значение
https://deviq.com/value-object/Объекты значений в разработке Test-Driven
https://leanpub.com/tdd-ebook/read#leanpub-auto-value-objectsЭрик Эванс. Domain-Driven дизайн: решение сложности в сердце программного обеспечения. (Книга; включает обсуждение объектов значений)
https://www.amazon.com/Domain-Driven-Design-Tackling-Complexity-Software/dp/0321125215/
Шаблон агрегирования
Модель домена содержит кластеры различных сущностей данных и процессов, которые могут управлять значительной областью функциональных возможностей, таких как выполнение заказа или инвентаризация. Более точное подразделение DDD — это агрегат, описывающий кластер или группу сущностей и поведения, которые можно рассматривать как единую единицу.
Обычно вы определяете агрегат на основе необходимых транзакций. Классический пример — это заказ, который также содержит список товаров. Элемент заказа обычно будет сущностью. Но это будет дочерняя сущность в агрегате заказа, которая также будет содержать сущность заказа в качестве корневой сущности, что обычно называется агрегатным корнем.
Идентификация агрегатов может быть сложной. Агрегат — это группа объектов, которые должны быть согласованы вместе, но вы не можете просто выбрать группу объектов и пометить их агрегатом. Необходимо начать с концепции домена и подумать о сущностях, которые используются в наиболее распространенных транзакциях, связанных с этой концепцией. Те сущности, которые должны быть транзакционно согласованными, образуют агрегат. Мышление об операциях транзакций, вероятно, является лучшим способом идентификации агрегатов.
Шаблон агрегатного корня или шаблон корневой сущности
Агрегат состоит по крайней мере из одной сущности: корня агрегата, также называемого корневой сущностью или первичной сущностью. Кроме того, он может иметь несколько дочерних сущностей и объектов значений, с всеми сущностями и объектами, работающими вместе для реализации требуемого поведения и транзакций.
Цель корня агрегата — обеспечить согласованность агрегата; он должен быть единственной точкой входа для внесения изменений через методы или операции в классе корня агрегата. Следует вносить изменения в сущности агрегата только через корень агрегата. Это хранитель согласованности агрегата, обеспечивающий выполнение всех инвариантов и правил согласованности, которые необходимо соблюдать в вашем агрегате. При независимом изменении дочерней сущности или объекта значения корень агрегата не может убедиться, что агрегат находится в допустимом состоянии. Это было бы как стол с свободной ногой. Поддержание согласованности является основной целью агрегатного корня.
На рис. 7-9 можно увидеть примеры агрегатов, таких как агрегат покупателя, который содержит единственную сущность (корневую сущность агрегата Покупатель). Агрегат порядка содержит несколько сущностей и объект значения.
Рис. 7-9. Пример агрегатов с несколькими или отдельными сущностями
Модель домена DDD состоит из агрегатов, агрегат может содержать только одну сущность или несколько, а также может включать объекты значений. Обратите внимание, что агрегат "Покупатель" может иметь дополнительные дочерние сущности в зависимости от вашего домена, как это реализовано в модуле оформления заказа в справочном приложении eShopOnContainers. Рис. 7-9 просто иллюстрирует случай, в котором покупатель имеет одну сущность, в качестве примера агрегата, содержащего только корень агрегата.
Чтобы обеспечить разделение агрегатов и обеспечить четкие границы между ними, рекомендуется использовать модель домена DDD, чтобы запретить прямую навигацию между агрегатами и иметь только поле внешнего ключа (FK), как реализовано в модели домена микрослужб заказа в eShopOnContainers. Сущность Order имеет только поле внешнего ключа для покупателя, но не свойство навигации EF Core, как показано в следующем коде:
public class Order : Entity, IAggregateRoot
{
private DateTime _orderDate;
public Address Address { get; private set; }
private int? _buyerId; // FK pointing to a different aggregate root
public OrderStatus OrderStatus { get; private set; }
private readonly List<OrderItem> _orderItems;
public IReadOnlyCollection<OrderItem> OrderItems => _orderItems;
// ... Additional code
}
Для идентификации и работы с агрегатами требуются исследования и опыт. Дополнительные сведения см. в следующем списке дополнительных ресурсов.
Дополнительные ресурсы
Вон Вернон (Vaughn Vernon). Эффективное проектирование агрегатов — часть 1: Моделирование одного агрегата (из https://dddcommunity.org/)
https://dddcommunity.org/wp-content/uploads/files/pdf_articles/Vernon_2011_1.pdfВон Вернон (Vaughn Vernon). Эффективное проектирование агрегатов - часть II: Обеспечение совместной работы агрегатов (из https://dddcommunity.org/)
https://dddcommunity.org/wp-content/uploads/files/pdf_articles/Vernon_2011_2.pdfВон Вернон (Vaughn Vernon). Эффективная агрегатная конструкция — часть III. Получение аналитических сведений с помощью обнаружения (из https://dddcommunity.org/)
https://dddcommunity.org/wp-content/uploads/files/pdf_articles/Vernon_2011_3.pdfСергей Grybniak. Шаблоны тактического проектирования DDDD
https://www.codeproject.com/Articles/1164363/Domain-Driven-Design-Tactical-Design-Patterns-PartКрис Ричардсон. Разработка микрослужб транзакций с помощью агрегатов
https://www.infoq.com/articles/microservices-aggregates-events-cqrs-part-1-richardsonDevIQ. Шаблон агрегирования
https://deviq.com/aggregate-pattern/