Москва: проверенные б/у ноутбуки с гарантией и проверкой перед оплатой
+7 906 722-94-45

Главная → Статьи → Context mapping: связи между ограниченными контекстами

Context mapping: девять способов связать контексты

Context mapping: партнёрство, общий ядро, клиент-поставщик, конформист и антикоррупционный слой — как выбрать способ интеграции.

Прямой ответ

Context mapping описывает способы связи между ограниченными контекстами. Связь бывает не только технической — она отражает отношения команд: кто от кого зависит, кто согласовывает изменения, кто подстраивается под чужую модель.

Основные типы связей:

Тип Суть Когда применять
Партнёрство Два контекста меняются согласованно Тесно связанные команды, общий результат
Общее ядро Часть модели разделяется явно Небольшая общая область при высокой цене дублирования
Клиент–поставщик Поставщик учитывает требования клиента Внутренняя интеграция с диалогом команд
Конформист Клиент принимает модель поставщика без перевода Поставщик не готов меняться, модель приемлема
Антикоррупционный слой Клиент транслирует чужую модель в свою Внешняя или нестабильная модель
Открытый хост Поставщик публикует протокол для многих клиентов Интеграция с несколькими потребителями
Публикуемый язык Общий формат обмена Нужен нейтральный формат, понятный всем
Раздельные пути Контексты не интегрируются Связь не нужна или слишком дорога
Большой ком грязи Границ нет, модель перетекает Антипаттерн, требующий изоляции

Практический смысл карты — она делает выбор явным. Без карты связь по умолчанию становится конформизмом: команда копирует чужую модель внутрь, потому что так быстрее, и через год изменение во внешней системе ломает внутреннюю логику.

Наиболее полезный на практике паттерн — антикоррупционный слой. Он изолирует внутреннюю модель от чужой:

class DeliveryAdapter:
    """Переводит модель внешней службы доставки в термины домена."""

    def to_shipment(self, external: dict) -> Shipment:
        return Shipment(
            shipment_id=external["trackingCode"],          # их имя -> наше
            state=ShipmentState(external["st"]),           # их код -> наш enum
            promised_at=parse_iso(external["eta_iso"]),
        )

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

Практика: как применять карту контекстов

1. Рисуйте карту до интеграции. Схема из прямоугольников и подписанных связей занимает час и предотвращает месяцы неявных решений.

2. Подписывайте тип каждой связи. Стрелка без подписи ничего не говорит. «Заказы → Доставка: клиент–поставщик» и «Заказы → Доставка: конформист» — разные обязательства.

3. Не используйте общее ядро без необходимости. Разделённая модель требует согласования каждого изменения. Общее ядро оправдано, когда дублирование дороже согласования.

4. Конформизм — осознанный выбор, а не отсутствие выбора. Принять чужую модель допустимо, если она стабильна и близка к вашей. Ошибкой является конформизм по умолчанию.

5. Антикоррупционный слой обязателен для внешних систем. Внешний поставщик не согласует изменения с вами, поэтому перевод нужен всегда.

6. Открытый хост требует публикуемого языка. Протокол для многих потребителей должен быть документирован и версионирован — см. статью про OpenAPI.

7. Раздельные пути — нормальное решение. Не всякую интеграцию нужно строить. Иногда дублирование небольшой части данных дешевле связи.

Рекомендации:

  1. Фиксируйте карту в репозитории. Диаграмма, которую никто не обновляет, вводит в заблуждение сильнее, чем её отсутствие.
  2. Связывайте карту с командами. Тип связи отражает отношения команд: партнёрство невозможно между командами, которые не общаются.
  3. Пересматривайте при изменении структуры. Смена команды-владельца меняет допустимый тип связи.
  4. Изолируйте большой ком грязи. При интеграции с legacy-системой её модель не должна проникать внутрь — о постепенной замене в статье про Strangler Fig.
  5. Согласуйте способ обмена. Синхронный запрос и событие задают разные обязательства по доступности; о событийном обмене — в статье про событийную интеграцию.

Практический сценарий: внешняя CRM продиктовала модель внутри системы

Контекст: интеграция с внешней CRM была выполнена напрямую: объекты CRM сохранялись во внутреннюю базу без перевода. Через полгода CRM изменила схему, и внутренняя логика сломалась в двадцати трёх местах.

  1. Диагностика. Поиск по коду показал, что имена полей внешней системы использовались в расчётах, валидации и отчётах. Внутренней модели сущности не существовало.
  2. Причина. Связь была реализована как конформизм по умолчанию: команда приняла чужую модель, чтобы ускорить запуск.
  3. Оценка. Прямой перенос на новую схему CRM требовал правок во всех найденных местах и не защищал от следующего изменения.
  4. Действия. (а) Описали внутреннюю модель клиента в терминах предметной области; (б) ввели адаптер, переводящий объекты CRM во внутреннюю модель, и обратный адаптер для выгрузки; (в) заменили прямые обращения к полям CRM на обращения к внутренней модели; (г) добавили контрактные тесты на формат CRM, чтобы изменение схемы обнаруживалось на тесте адаптера; (д) отметили связь на карте как антикоррупционный слой и зафиксировали причину.
  5. Результат. Последующее изменение схемы CRM потребовало правки одного адаптера и одного теста; внутренняя логика не затрагивалась.

Вывод: тип связи определяет стоимость изменений. Конформизм дешевле в начале и дороже в долгосрочной перспективе; антикоррупционный слой требует дополнительных усилий на старте и окупается при первом изменении внешней системы.

FAQ

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

Чем карта контекстов отличается от диаграммы сервисов? Диаграмма сервисов показывает развёртывание и сетевые связи. Карта контекстов показывает границы моделей и отношения команд, которые не видны на схеме развёртывания.

Можно ли изменить тип связи позже? Да. Переход от конформизма к антикоррупционному слою — обычная практика после накопления опыта работы с чужой моделью.

Что делать, если поставщик не хочет учитывать требования? Выбирать между конформизмом и антикоррупционным слоем. Если модель поставщика нестабильна, перевод обязателен независимо от его готовности к диалогу.

Источники: domainlanguage.com (DDD), Martin Fowler (BoundedContext), InfoQ — ссылки в шапке.