Проектирование на основе домена (DDD) выступает против идеи создания единой единой модели для всей системы; Вместо этого она поощряет разделение системы на ограниченные контексты, каждая из которых имеет собственную модель. На стратегическом этапе предметно-ориентированного проектирования составляется схема предметной области бизнеса и определяются ограниченные контексты для модели предметной области.
На тактическом этапе модели предметной области определяются с более высокой точностью. Тактические шаблоны применяются в рамках одного ограниченного контекста. В архитектуре микрослужб, где каждый ограниченный контекст является кандидатом микрослужб, мы особенно заинтересованы в сущности и агрегатных шаблонах. Применение этих шаблонов поможет нам определить естественные границы для служб в нашем приложении (см. следующую статью в этой серии). Как правило, микрослужба должна быть не меньше статистического выражения и не больше ограниченного контекста. Сначала рассмотрим тактические шаблоны. Затем мы применим их к ограниченному контексту доставки в приложении доставки с помощью дронов.
Общие сведения о тактических шаблонах
Этот раздел содержит краткую сводку тактических шаблонов DDD. Так что, если вы уже знакомы с ними, можете переходить к следующему разделу. Шаблоны подробно описаны в разделах 5 – 6 книги Эрика Эванса, а также в реализации дизайна на основе домена в Vaughn Vernon.
Сущности. Сущность представляет собой объект с уникальным идентификатором, который сохраняется с течением времени. Например, в банковском приложении клиенты и учетные записи выступают сущностями.
- У сущности в системе есть уникальный идентификатор, который может использоваться для поиска или извлечения объекта. Это не означает, что идентификатор всегда предоставляется пользователям напрямую. Это может быть GUID или первичный ключ в базе данных.
- Идентификатор может охватывать несколько ограниченных контекстов. Срок его действия может превышать время существования приложения. Например, номера банковских счетов или идентификаторы, выданные правительством, не привязаны к времени существования конкретного приложения.
- Атрибуты сущности могут изменяться со временем. Например, имя или адрес пользователя могут измениться, но сущность останется одной и той же.
- Сущность может содержать ссылки на другие сущности.
Объекты-значения. Объект-значение не имеет идентификатора. Он определяется только значениями его атрибутов. Объекты-значения также являются неизменяемыми. Чтобы обновить объект-значение, всегда создавайте новый экземпляр для замены старого. Объекты-значения могут иметь методы, которые внедряют логику предметной области, но эти методы не должны иметь побочных эффектов для состояния объекта. К самым распространенным примерам объектов-значений относятся цвета, даты и время, а также значения валюты.
Статистические выражения. Статистическое выражение определяет границу согласованности одной или нескольких сущностей. Одна сущность в статистическом выражении является корневой. Поиск выполняется по идентификатору корневой сущности. Любые другие сущности в статистическом выражении являются дочерними элементами корневой сущности, на которые ссылаются следующие указатели корневой сущности.
Статистические выражения предназначены для моделирования транзакционных инвариантов. Взаимосвязь объектов в реальном мире очень сложна. Клиенты создают заказы, заказы содержат продукты, у продуктов есть поставщики и т.д. Если приложение изменяет несколько связанных объектов, как оно гарантирует их согласованность? Как отслеживать инварианты и применять их?
Традиционные приложения часто используют транзакции базы данных для обеспечения согласованности. Однако в распределенном приложении это, как правило, нецелесообразно. Одна бизнес-транзакция может охватывать несколько хранилищ данных, долго выполняться или включать сторонние службы. В конечном итоге обеспечение требуемых для предметной области инвариантов зависит от приложения, а не от уровня данных. Вот что должны моделировать статистические выражения.
Примечание.
Статистическое выражение может состоять из одной сущности без каких-либо дочерних сущностей. Этот объект является статистическим выражением благодаря транзакционной границе.
Службы предметных областей и службы приложений. В терминологии DDD служба является объектом, который реализует логику без удержания какого-либо состояния. Эванс различает службы предметных областей, которые содержат логику предметной области, и службы приложений, которые предоставляют технические функциональные возможности, такие как проверка подлинности пользователя или отправка текстового сообщения. Службы предметных областей часто используются для моделирования реакции на событие, охватывающей несколько сущностей.
Примечание.
Термин служба перегружен в разработке программного обеспечения. Приведенное здесь определение не связано непосредственно с микрослужбами.
События предметной области. События предметной области могут использоваться для уведомления других частей системы, когда происходит событие. Как следует из названия, события предметной области должны означать что-то внутри предметной области. Например, "в таблицу вставлена запись" не является событием предметной области. "Доставка отменена" — пример события предметной области. События предметной области особенно важны в архитектуре микрослужб. Так как микрослужбы распределены и не имеют общих хранилищ данных, события предметной области предоставляют микрослужбам способ координации друг с другом. В статье Интерслужба коммуникации подробно описывается асинхронное обмен сообщениями.
Есть также несколько других шаблонов DDD, которые не перечислены здесь, включая фабрики, репозитории и модули. Эти шаблоны могут быть полезны при реализации микрослужбы, однако они менее актуальны при разработке границ между микрослужбами.
Доставка с помощью дронов: применение шаблонов
Мы начнем со сценариев, которые должен обрабатывать ограниченный контекст доставки.
- Клиент может запросить дрон, чтобы быстро принять товар у компании, зарегистрированной в службе доставки с помощью дронов.
- Отправитель создает тег (штрихкод или RFID) для размещения на грузе.
- Дрон примет и доставит груз из исходного расположения в целевое.
- Когда клиент планирует доставку, система выдает предполагаемое время приема и доставки на основе информации о маршруте, погодных условиях и исторических данных.
- Когда дрон в пути, пользователь может отслеживать его расположение и последнее ETA.
- Пока дрон не получил груз, клиент может отменить доставку.
- Клиент уведомляется о завершении доставки.
- Отправитель может запросить подтверждение от клиента в форме подписи или отпечатка пальца.
- Пользователи могут просмотреть историю завершенной доставки.
В этих сценариях команды разработки определили следующие сущности:
- Доставка
- Пакет
- Дрон
- Учетная запись
- Подтверждение
- Notification
- Тег
Первые четыре сущности (доставка, груз, дрон и учетная запись) являются статистическими выражениями, которые представляют границы согласованности транзакций. Подтверждения и уведомления являются дочерними сущностями доставки, а теги — дочерними сущностями грузов.
Объекты-значения в этом проекте включают расположение, ETA, вес и размер груза.
Для демонстрации ниже приведена схема UML статистического выражения доставки. Обратите внимание, что оно содержит ссылки на другие статистические выражения, включая учетную запись, груз и дрон.
Есть два события предметной области:
когда дрон выполняет доставку, одноименная сущность отправляет события DroneStatus (состояние дрона), которые описывают его расположение и состояние (в пути, приземлился);
сущность доставки отправляет события DeliveryTracking при каждом изменении этапа доставки. К ним относятся DeliveryCreated (доставка создана), DeliveryRescheduled (доставка перепланирована), DeliveryHeadedToDropoff (груз направляется в конечный пункт) и DeliveryCompleted (доставка завершена).
Обратите внимание, что эти события описывают элементы, которые важны в модели предметной области. Они описывают что-то о предметной области и не привязаны к конкретной конструкции языка программирования.
Команда разработчиков определила еще одну область функций, которая не соответствует полностью ни одной из уже описанных сущностей. Некоторая часть системы должна координировать все шаги, связанные с планированием или обновлением доставки. Поэтому команда разработчиков добавила в проект две доменные службы : планировщик , который координирует шаги, и руководитель , отслеживающий состояние каждого шага, чтобы определить, завершились ли какие-либо шаги сбоем или истекло время ожидания. Это вариант шаблона диспетчера агентов планировщика.
Следующие шаги
Следующий шаг — определить границы для каждой микрослужбы.