Прежде чем писать код, спеку или задачу агенту, стоит ответить на вопрос, который почти никогда не задают вслух: из каких понятий состоит наша задача и как они связаны?
Раньше нестыковку понятий сглаживали люди: аналитик переспросит, разработчик догадается, тестировщик заметит. Агент не переспрашивает — он молча достраивает пробелы правдоподобными догадками. Если в вашей голове «заказ» один, в задаче описан другой, а в базе лежит третий, агент реализует четвёртый.
Эта статья — про весь путь: от «из чего состоит задача» до словаря, которым одинаково пользуются бизнес, команда и агент, и до графа, у которого можно спрашивать.
Система понятий есть у любого проекта
«Заказ состоит из позиций. У заказа есть владелец-клиент. Заказ оплачивается платежом. Отменённый заказ оплатить нельзя» — вот кусочек описания предметной области: четыре понятия, связи между ними и одно правило. Строгое имя этому — онтология, но за страшным словом стоит простая вещь: перечень понятий, их свойств, связей и правил.
Важно понять: такая система понятий есть у любого проекта — вопрос лишь, записана ли она. Команда в любом случае оперирует какими-то понятиями. Если они нигде не зафиксированы, они живут в головах, у каждого своей версией. Продакт под «заказом» понимает одно, разработчик — другое, поддержка — третье. Все три версии работают, пока не встретятся в одном спринте.
Первая ловушка — искать «истинную» модель домена. Её не существует. Что такое «клиент» для магазина? Для маркетинга — профиль с историей интересов. Для платежей — плательщик с реквизитами. Для доставки — получатель с адресом. Это три разные модели одного человека, и попытка сделать одну «универсальную» даст худшую из всех: раздутое понятие, неудобное каждому. Критерий качества модели — не истинность, а пригодность: помогает ли она решать задачи, ради которых построена, и одинаково ли её понимают все участники.
Второй практичный инструмент — замечать, на каком уровне вы сейчас говорите. Понятия выстраиваются в этажи: конкретный заказ №4211 от Иванова на 3 400 ₽ → тип «заказ» (у любого есть номер, клиент, позиции, статус) → «бизнес-сущность» (заказы, клиенты, платежи — всё это сущности с жизненным циклом) → соглашения о том, как мы вообще описываем сущности. Половина запутанных споров в командах — это спор людей с разных этажей: один говорит про конкретный заказ («а вот тут заказ без клиента!»), второй — про тип («заказа без клиента не бывает по определению»). Умение сказать «мы на разных уровнях» экономит часы.
Модель понятий — не схема базы данных
Самая частая ошибка на старте: услышав задачу, инженер открывает редактор и рисует таблицы. Кажется, что это и есть моделирование. На деле пропущен целый этап, и его пропуск оплачивается позже переделками схемы и спорами «а что мы вообще имели в виду».
Это два разных вопроса. Модель понятий отвечает: какие понятия есть и как они связаны — заказ состоит из позиций, платёж относится ровно к одному заказу, отменённый заказ оплатить нельзя. Здесь нет ни слова про таблицы и индексы. Схема базы отвечает на другой вопрос: как это хранить — в каких таблицах, с какими ключами, что денормализовать ради скорости.
Одна и та же модель понятий ложится на десятки схем: нормализованную, денормализованную под чтение, документную, событийную. Выбор схемы — инженерный компромисс под нагрузку и запросы; выбор понятий — договорённость о смысле. Когда прыгаешь сразу в таблицы, договорённость о смысле принимается молча, как побочный эффект структуры хранения.
Отучающее упражнение: перестаньте считать, что понятию соответствует таблица.
- Одно понятие — несколько таблиц. «Заказ» живёт в
orders,order_lines,order_status_history— три таблицы, одно понятие. - Одна таблица — несколько понятий. В
usersчасто смешаны «учётная запись» (логин, пароль, роли) и «человек» (имя, контакты) — два понятия с разным жизненным циклом, склеенные структурой хранения. Отсюда растут боли вида «удалили пользователя — потеряли автора заказов». - Понятие без таблицы. «Просроченный платёж» — полноценное понятие с правилами, но в базе это условие
WHERE, а не таблица.
Если модель понятий не записана отдельно, схема базы становится моделью понятий — со всеми её компромиссами. Через год уже никто не помнит, что склейка «учётки» и «человека» была случайностью, и новые возможности строятся поверх неё как поверх осмысленного решения. У этого есть и наружные следствия: API начинает повторять таблицы (наружу торчат user_id и джойны вместо понятий домена), каждая миграция под нагрузку превращается в пересмотр смысла, а спор «нужна ли отдельная таблица для X» маскирует нерешённый вопрос «а X — это вообще отдельное понятие или атрибут Y?».
С агентом это критично вдвойне: дайте ему только DDL — и он честно примет структуру хранения за модель домена, со всеми склейками и случайностями.
Как моделировать до таблиц — час честной работы, без тяжёлых инструментов:
- Выпишите понятия существительными из языка бизнеса: заказ, позиция, клиент, платёж, возврат.
- Свяжите их: «состоит из», «принадлежит», «относится к» — с кратностями (у заказа один клиент; у клиента много заказов).
- Запишите состояния и правила: какие статусы бывают, какие переходы разрешены, что запрещено («оплатить отменённый нельзя»).
- Проверьте на бизнесе: покажите модель тому, кто владеет задачей, — на этом уровне (в отличие от DDL) он способен найти ошибку.
Результат — страница текста или простая схема. Уже из неё проектируется структура хранения — осознанно, под запросы и нагрузку.
Единый язык: словарь как контракт
Модель понятий бесполезна, если ею пользуетесь только вы. Её сила — когда одними и теми же словами говорят бизнес, код и агент. Эта практика называется ubiquitous language, «единый язык», и это самая недооценённая идея DDD: она не про архитектуру, а про то, как перестать терять смысл при переводах.
Посмотрите, сколько переводов проходит обычное требование. Бизнес говорит «клиент бросил корзину». Аналитик записывает «сессия с неоформленным заказом». Разработчик называет это abandoned_cart, а рядом в коде живёт pending_order — «это же почти то же самое». Тестировщик проверяет «незавершённую покупку». Четыре формулировки, и у каждой чуть-чуть свой смысл: почти то же самое, но «почти» здесь — источник дефектов.
Каждый перевод — точка потери смысла. Единый язык убирает переводы: слово из разговора с бизнесом попадает в модель, из модели — в код, из кода — в тесты и в задачу агенту, не меняясь по дороге. Отсюда практическое следствие: если для понятия в коде нет слова из языка бизнеса — это сигнал. Либо вы изобрели сущность, которой нет в домене, либо бизнес пользуется понятием, которого нет в вашей модели.
Вторая половина идеи, без которой первая не работает: не пытайтесь сделать один словарь на всю компанию. Мы уже видели на примере «клиента»: для маркетинга, платежей и доставки это три разных понятия. Это не беспорядок, который надо победить, а природа предметных областей. Решение — границы контекстов: единый язык действует внутри границы. Внутри контекста платежей «клиент» — всегда плательщик с реквизитами, и никаких других значений. На границе между контекстами происходит явный перевод: событие «заказ оформлен» превращается в «появился плательщик» — и этот перевод записан, а не происходит в чьей-то голове.
Работает всё это, только если словарь записан. Формат минимальный — глоссарий на страницу: термин (и имя в коде, если отличается, — но лучше, чтобы не отличалось), определение одним-двумя предложениями без «ну все же понимают», границы (в каком контексте действует, чем отличается от похожего термина соседнего контекста), состояния и правила, если у понятия есть жизненный цикл. Признак живого словаря: на ревью можно сказать «у нас нет понятия „подписка", есть „регулярный платёж"» — и это аргумент, а не вкусовщина.
Для агента словарь — не справка, а контракт. Он называет сущности так же, как бизнес; не изобретает синонимов (Order, а не Purchase во второй сессии); соблюдает записанные правила состояний. Три сессии без словаря дают три несовместимых решения — не потому что модель плохая, а потому что каждый раз она заново угадывает вашу систему понятий. Словарь делает угадывание ненужным.
Когда понятий много: граф знаний
Пока речь шла об одной задаче или одном сервисе, хватает страницы текста. На масштабе продукта или платформы появляется другая потребность: у записанных понятий хочется спрашивать.
Обычный поиск по документам находит фрагменты, похожие на вопрос по смыслу. Это отлично работает для «что такое X» и плохо — для трёх видов вопросов. Многошаговых: «какие сервисы затронет изменение контракта платёжного API?» — ответ нигде не написан одним куском, он выводится по цепочке связей. Агрегирующих: «сколько у нас интеграций с внешними провайдерами?» — это подсчёт по всей базе знаний. Точечных: «кто владелец сервиса X?» — похожих кусков много, а нужен один достоверный факт, а не наиболее похожий абзац. Причина общая: текст хранит связи неявно, размазанными по формулировкам.
Граф знаний хранит их явно — фактами вида «субъект → отношение → объект»: «payment-service — потребляет — orders-api», «orders-api — принадлежит — команде checkout». Узлы — понятия, рёбра — связи. А чтобы граф не превратился в свалку произвольных стрелок, ему нужна схема: какие бывают типы узлов (сервис, команда, контракт) и какие отношения допустимы. Это ровно та же система понятий, с которой начиналась статья, только записанная строго. По графу можно ходить: от контракта к потребителям, от них — к зависимым, сколько угодно шагов, с проверяемым результатом на каждом.
Связка графа с моделью работает так: из вопроса выделяются сущности, вокруг них обходятся связи, собранный подграф подмешивается в контекст, и модель формулирует ответ по фактам, а не по похожим абзацам. Слабости закрываются взаимно: граф не понимает вопросов на естественном языке — модель понимает; модель выдумывает и не выводит цепочки надёжно — граф хранит проверяемые факты.
Цена у графа есть: его надо спроектировать, наполнить и поддерживать актуальным — протухший граф хуже отсутствующего, он уверенно врёт. Поэтому для вопросов «найди и перескажи» достаточно обычного поиска по документам, а граф оправдан там, где вопросы про связи и следствия: анализ влияния изменений, зависимости сервисов и команд, «какие системы трогают персональные данные».
И заметьте знакомый узор: реестр сервисов с владельцами, контрактами и связями — это и есть граф знаний вашего продукта, просто записанный в файлах. Модель понятий, словарь и граф — одна дисциплина на разных масштабах: записывайте понятия и связи явно, и по ним смогут работать и люди, и агенты.
Коротко
- Система понятий есть у любого проекта; вопрос — записана она или живёт в головах разными версиями.
- Модель не бывает истинной, только подходящей под задачу; универсальное понятие «для всех» обычно худшее для каждого.
- Споры «на разных этажах» (конкретный заказ против типа «заказ») — источник половины недопониманий.
- Модель понятий ≠ схема базы. Объект не равен таблице: понятие может жить в трёх таблицах, а таблица — склеивать два понятия. Не записали модель — ею станет схема хранения, со всеми её случайностями.
- Порядок: понятия → связи с кратностями → состояния и правила → проверка на бизнесе. Потом таблицы.
- Единый язык — одно слово на всём пути от бизнеса до кода и тестов; каждый перевод между жаргонами теряет смысл.
- Один словарь на всю компанию невозможен: слова меняют смысл на границах контекстов; внутри границы значение строгое, на границе — явный записанный перевод.
- Для агента словарь — контракт, убирающий угадывание: без него каждая сессия заново изобретает вашу модель понятий.
- Когда вопросы становятся про связи и следствия, записанные понятия превращаются в граф знаний, у которого можно спрашивать; цена — поддержание актуальности.
Что почитать дальше
- От модели к контракту — как превратить понятия в документ, по которому агент строит, а вы принимаете.
- Галлюцинации — почему пробелы в понятиях агент заполняет молча.
- Поиск по своим данным — как подмешивать знания в контекст модели.
- Use Case Pattern — методология, где спецификация домена живёт рядом с кодом.