Раздел 9 · Backend

Лестница моделирования: онтологии, C4, Event Storming, FSM

middle-senior~35 мин

без входаВойди, чтобы отмечать прогресс, вести заметки и решать задачи в редакторе. войти

Лестница моделирования: онтологии, C4, Event Storming, FSM

Весь раздел мы проектировали системы словами и кодом: границы, контракты, потоки событий. Пока команда умещается за одним столом, этого хватает. Потом появляется второй стол, новый разработчик, аудитор из прошлого урока, и оказывается, что устройство системы нужно показывать, а не пересказывать. Тут у моделирования всплывает дурная репутация: толстые UML-альбомы, устаревшие в день печати, и архитектор, рисующий квадратики вместо работы. Репутация заслуженная, но выводы из неё обычно делают неверные. Проблема не в моделях, а в неумении выбирать уровень формальности. Этот урок и есть лестница таких уровней: от глоссария до конечного автомата, с правилом, какую ступень брать под какой вопрос.

Лестница уровней

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

СтупеньОтвечает на вопросЦена
Глоссарийкак мы называем вещикопейки
ER, концептуальная моделькакие сущности и как связанынизкая
Event Stormingчто происходит в доменеодин воркшоп
C4из чего состоит системанизкая, если as code
State diagramв каких состояниях живёт сущностьсредняя
BPMN, DMNкак течёт процесс, как принимается решениевысокая
TLA+не нарушается ли инварианточень высокая

Выбирай самую дешёвую ступень, которая отвечает на твой вопрос. Вопрос «почему сотрудники площадки и кассиры называют одно и то же слово билет разными вещами» решается глоссарием, и рисовать для него C4 бессмысленно. Вопрос «может ли возврат и продажа одного места столкнуться» глоссарием не решается, тут нужна как минимум статусная модель.

Почему же «нарисовать всё в UML» не сработало? UML предлагал четырнадцать видов диаграмм и культуру вокруг них: CASE-инструменты, генерацию кода из моделей и обратно. Индустрия проверила и оставила от всего этого два жанра: диаграммы структуры (близкие к ER) и диаграммы последовательности. Остальное умерло от главной болезни моделей: модель, которую не обновляют, врёт, и врёт авторитетно, ведь она выглядит как документация. Отсюда второе правило урока: заводя модель, заводи и процесс её обновления. Лучший из известных процессов: хранить модель как текст рядом с кодом и ревьюить диффом, к этому вернёмся на ступени C4.

Онтологии: от реальности к схеме

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

Дальше понятия обрастают структурой, и тут индустрия данных давно разделила три уровня модели:

УровеньЯзыкПример для афиши
CDMсущности и связи словамибилет принадлежит заказу и даёт право на место
LDMатрибуты, ключи, кардинальностиу Ticket есть order_id, seat_id, уникальность места внутри события
PDMтаблицы и индексы СУБДtickets с bigint-ключами, уникальный индекс (event_id, seat_id), партиции по сезону

Ценность не в каждом уровне по отдельности, а в дисциплине перехода: спор о том, может ли заказ существовать без билетов, это спор уровня CDM, и решать его выбором между NULL и NOT NULL на уровне PDM, минуя обсуждение, означает зашить случайное бизнес-решение в схему. Классические нотации этих уровней: ER-диаграммы и IDEF1X; идея доводилась до предела в MDA, где из моделей собирались генерировать весь код. Генерация не взлетела, лестница осталась.

C4: четыре зума

Поднимаемся от данных к системе целиком. C4 победила UML на поле «показать устройство системы» одним приёмом: она узаконила зум. Вместо одной диаграммы обо всём четыре уровня, каждый для своей аудитории:

  • Context. Система как чёрный ящик: кто пользователи, какие внешние системы вокруг. Аудитория: все, включая бизнес.
  • Container. Из каких деплоймент-юнитов система состоит: приложения, базы, очереди, воркеры. Аудитория: инженеры, включая соседние команды.
  • Component. Что внутри одного контейнера: модули и их связи. Аудитория: команда этого контейнера.
  • Code. Классы и функции. Этот уровень почти никогда не рисуют руками: он устаревает быстрее всех, а при нужде генерируется из кода.
C4 · четыре зума на одной афише
ЗрительМенеджер площадки
Афишаsoftware system
Платёжный провайдерIdP клиента

Система как чёрный ящик: люди слева, внешние системы справа. Что внутри, уровень не говорит, и в этом его сила.

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

Пройди по табам слева направо и следи за строкой «аудитория»: каждый зум сужает её. Если на одной диаграмме встретились Зритель, Postgres и класс OrderService, уровни смешаны, и диаграмма отвечает на все вопросы сразу, то есть ни на один.

Главный анти-паттерн ровно один: смешать уровни на одной диаграмме, где рядом живут «Зритель», «Postgres» и «класс OrderService». Такая диаграмма не отвечает ни на один вопрос, потому что отвечает на все сразу.

Вторая причина победы C4: она дружит с diagrams as code. Диаграмма как текст в репозитории лечит болезнь устаревания наполовину: она хотя бы меняется тем же процессом, что и код, и ревьюер видит диф архитектуры. Context и Container афиши на Structurizr DSL умещаются в экран:

workspace {
  model {
    visitor = person "Зритель"
    manager = person "Менеджер площадки"

    afisha = softwareSystem "Афиша" {
      web    = container "Веб-приложение" "Astro SSR"
      api    = container "API" "Node.js"
      db     = container "База" "PostgreSQL"
      worker = container "Биллинг-воркер" "обработчик очереди"
    }

    payments = softwareSystem "Платёжный провайдер" "внешняя система"
    idp      = softwareSystem "IdP клиента" "Okta, Entra"

    visitor -> web "покупает билеты"
    manager -> web "управляет событиями"
    web -> api "HTTP"
    api -> db "SQL"
    worker -> payments "создаёт списания"
    payments -> api "webhooks"
    idp -> api "SAML, SCIM"
  }
}

Инструмент рендерит из этого и Context (системы и люди), и Container (содержимое afisha). Альтернативы по вкусу: Mermaid рисуется прямо в GitHub и в маркдауне, PlantUML ветеран с самым богатым синтаксисом, D2 самый приятный глазу. Где такие диаграммы живут и как соотносятся с остальной архитектурной документацией, разобрано в уроке про карту документов.

дальше после входа

Урок целиком открыт всем, кто вошёл. Войди по своему email, чтобы читать дальше.

Вход пока по приглашению. Если хочешь учиться, напиши Vassiliy.