Что приписывает DDD - использование монолитов или микросервисов?

Это мои мысли, если с чем-то не согласны – пишите, обсудим.
Возможно подготовлю материал еще по тому как поделить один контекст на несколько и то какие вопросы задать себе, чтобы проверить наличие разных моделей в рамках одного контекста, может они были ошибочно объединены в одном контексте.

Немного про DDD.

DDD - это решение сложности в самом сердце - предметной области, бизнес-задаче (domain).

DDD это про моделирование сложной бизнес-логики (стратегическое проектирование) и организацию кода (тактические паттерны), а не про использование микросервисов или монолитов.
Фокус идет только на домене (бизнес-логике).

Стратегическое проектирование – это то как делить систему на контексты и взаимодействия между ними. (Domain, Subdomain, Bounded Context, Ubiquitous Language)

Тактические паттерны – это то как писать код внутри одного контекста (Entities, VO, Domain Services, Aggregate, Repositories и тд).

Монолит и Микросервисы

Большой и маленький монолит, с точки зрения DDD, являются вполне допустимыми, если они содержат несколько "Ограниченных контекстов" и в них нет конфликтующих моделей, то есть когда контексты не противоречат друг другу, то все ок.

Идеальный сервис соответствует одному "Ограниченному контексту", но не наоборот, когда КАЖДЫЙ "Ограниченный контекст" требует выделения своего сервиса.

Микросервис может включать несколько маленьких контекстов, если они тесно связаны (Управление пользователями + Аутентификация).

Соответственно НЕ КАЖДЫЙ "Ограниченный контекст" ДОЛЖЕН являться микросервисом, но в одном микросервисе МОЖЕТ БЫТЬ несколько “Ограниченных контекстов”.

Примеры сервисов и контекстов:

- Если НЕСВЯЗАННЫЕ контексты со СМЕЖНЫМИ МОДЕЛЯМИ смешиваются в одном сервисе, то это антипаттерн для DDD.
Например, "Аутентификация" (id, email, хеш пароля) и "Кредитование" (ФИО, кредитная история, доход) с разным пониманием модели "пользователь".

- Если выделенный вами контекст оказался слишком сложным и большим, то скорее всего вы плохо рассмотрели границы контекста и поддомена, и данный сервис решает несколько бизнес-задач.
Такой контекст лучше делить на несколько, которые будут решать мелкие задачи. Но если данный сервис редко обновляется или добавление нового функционала не ломает другой функционал (по сути нет конфликтующихся моделей или "пересекающихся" контекстов), то можно и оставить в таком состоянии все.
По идее эти контексты могут храниться в рамках одного сервиса (монолита), так и быть разделены.
Но если данные контексты просто ТЕСНО связаны (решают связанные бизнес-задачи, например, обработка заказа и его валидация), то вы рискуете получить распределенный монолит, когда сервисы ЖЕСТКО связаны.

- С помощью DDD можно будет выделить "горячие" сущности, которые часто запрашиваются, и за счет этого отдельно масштабировать каждый контекст не зависимо.
Например: поиск товаров, рекомендации и управление товарами (все работают с сущностью "товар", но имеют разные модели и бизнес-правила, что позволяет разнести их в отдельные сервисы и масштабироваться).

Есть еще "пересекающиеся" (смежные) контексты, где один контекст ИСПОЛЬЗУЕТ часть данных из моделей (сущностей) другого контекста.Что с такими контекстами делать?

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

Если нужно, чтобы какие-то критичные повторяющиеся данные не изменялись сразу в двух контекстах/таблицах, можно выделить так называемый "мастер" контекст – это контекст, который решает определенную задачу и может менять у сущности БАЗОВЫЕ атрибуты (критичные), не трогая при этом атрибуты, которые ему не принадлежат.

Пример использования "мастер" контекста:
SaleContext отвечает за создание покупателей (id, ФИО).
В SupportContext также необходимо иметь эти поля, при этом у покупателя в рамках SupportContext будут дополнительные поля, допустим, уровень поддержки.
Так SaleContext является "мастер" контекстом в рамках id и ФИО, SupportContext может читать эти записи, но не может изменить их.

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

Итог:

DDD может соблюдаться как в микросервисах, так и в монолите. Главное, чтобы не было смешения и конфликтов контекстов. Например, один микросервис для заказов и доставки, но с разными или, наоборот, объединенными моделями данных "клиента".

1
2 комментария