Почему я использую doc-as-a-code
В этой статье я постараюсь рассказать и показать, почему я использую подход doc-as-a-code, как помогает git системному аналитику и зачем это всё. И «почему не confluence?»
Процесс разработки
Начнём с простого. Процесс разработки.
Процесс разработки цикличен и более-менее стандартизирован от компании к компании. При этом мы применяем принцип «documentation-first».

Давайте проговорим его:
Приходит заказчик, садится с бизнес аналитиком (БА) и рассказывает, что же они хотят от системы. Или с продактом. Или с продуктовым аналитиком. По разному называют эту роль в разных компаниях. Результат примерно одинаковый. На выходе у БА должны быть бизнес требования, в виде текстового описания «что система делает», BPMN схем бизнес процесса, описания пользовательского пути, прорисованные макеты, постановки в виде user-story. В зависисимости от опыта БА и требуемого качества это может быть целевой документ, а могут быть разрозненные кусочки в виде задач.
С этими артефактами проводится грумминг. Если разработка большая, то с архитектором решается на какие этапы разделить реализацию, и в какой последовательности доставлять бизнес ценности заказчику. По результатам грумминга эпик делится на отдельные стори, которые в свою очередь передаются Архитектору на проработку.
Архитектор переносит бизнес процессы и накладывает их на архитектуру. Используя к примеру Archimate, он отрисовывает бизнес слой и проектирует, как он будет реализовываться на уровне приложений. Опять-таки, в разных компаниях — по-разному. Иногда роль архитектора передают в команду разработки и этим занимается ведущий аналитик или тех лид. Сути это не меняет: перед детальной проработкой необходимо выбрать архитектурное решение и задокументировать его не только в виде ADR, но и в целевой архитектуре, в чем бы она не велась.
Проработав архитектурное решение архитектор презентует его команде, которой предстоит его разрабатывать. На этом этапе определяется, какие работы должны быть выполнены в том или ином сервисе. Детализация работ будет выполнена на следующем этапе.
Когда готовы бизнес требования и архитектура, команда приступает к работе. Если Архитектор и БА работали над эпиком и декомпозировали его на стори, то команда разработки берет стори и реализует её. Стори — это какая-то минимальная бизнес ценность, которая может быть доставлена.
Первым из команды заходит системный аналитик и описывает спецификацию. Он детально прорабатывает техническое решение. Его спецификация будет отвечать на вопрос «Как это работает». Об это позже и подробнее.
После того как спецификация готова (или изменена) проводится ревью. На ревью обсуждается, какие именно изменения в какие части кода и системы должны быть внесены. Про ревью спеки тоже поговорим подробнее чуть позже. Если необходимо, в спецификацию вносятся изменения. Главное: Если вы исповедуете «documentation first», то следите за этим строго! Сначала правка в спеку, потом правка в код. И никак иначе.
Когда спека готова и финализирована, все изменения согласованы и каждому члену команды понятно, что именно мы будем делать, заводятся задачи и передаются в разработку. Т.е. в рамках одной стори нарезается множество тасок, с которыми и работают разработчики.
Каждый разработчик выполняет свою задачу (task, subtask и т.п. в зависимости от того, как вы работаете с доской). В задаче описаны детали, касаемые функционала системы, который необходимо разработать. Например «Добавить поле в эндпоинт и сохранить его». Только выполнив все задачи в этой стори бизнес ценность будет доставлена.
Тестирование может быть организовано как по отдельным задачам, так и всей стори целиком. Детали организации тестирования я опущу.
Когда все работы по сторе завершены, проводится демонстрация заказчику. В случае успеха — ценность доставляется на прод. В случае неудачи — цикл повторяется сначала.
Ничего нового, в большинстве своем компании говорят «у нас так же». Но, как обычно, дьявол в деталях.
Что важно в этом процессе:
Соседние роли совмещать нельзя. Многие считают, что «ничего страшного», но я ни разу не видел хорошо работающего процесса, в котором соседние роли совмещены и соответствующие артефакты появляются в должном качестве. Пример я решил вырезать, потому что вопрос «как пишут доку разработчики» может оказаться холиварным.
Строго соблюдать принцип documentation first. Если он не соблюдается, то очень часто из-за спешки, документирования откладывается в тех долг. В результате у вас есть работающий код, но нет документации на него. В большинстве компаний, где роли системного аналитика нет, или под SA понимают бизнес аналитика, разработка идет без документации. В результате, когда команда меняется и вся экспертиза остается в головах ушедших сотрудников, компании надо в два раза больше ресурсов, чтобы доработать такой код.
Все артефакты документирования — обязательны.
Без бизнес-постановки не понятно, какой результат ожидает заказчик. И как заказчик будет принимать работу.
Архитектура связывает воедино бизнес требования и системную спецификацию и прорабатывает взаимодействие на более высоком уровне.
Системная аналитика (спецификация) подробно рассказывает, что происходит под капотом системы. Как работает и как будет работать система и её отдельные части.
Тесткейсы позволяют стабильно проверять работоспособность кода после любых изменений и не допускать баги на прод. Если вы опускаете какой-то из артефактов — у вас разрыв в требованиях. Например, без документированной архитектуры сложно понять, как и в каких системах реализованы определённые бизнес требования.
Артефакты документации нельзя смешивать. Один из частых примеров это работа фулстек аналитиков. Бизнес-системных-аналитиков. В производимых ими документах часто нет границы между бизнес сущностями и системными сущностями. В них можно увидеть рассуждения, что сущность «Заказ» хранится в БД. Хотя «Заказ» это бизнес сущность, у которой есть бизнес атрибуты. А в БД хранятся записи в таблицах, которые соответствую этой бизнес-сущности. Это два разных уровня абстракции, которые нельзя смешивать. В системе работа происходит с системными объектами. Записи в БД, объекты запросов, сообщения и т.п. Бизнес оперирует своими понятиями и «Заказ» это не обязательно одна запись в БД. Это может быть множество связанных записей и объектов, передаваемых и хранящихся внутри системы. Обратная сторона — это системы без продуктовой аналитики. Знаете, когда все постановки спрятаны где-то в задачах и конечной документации вообще нет. При восстановлении бизнес процессов вместо использования бизнес понятий начинают использовать системные. Вместо «Платеж передается в систему расчёта начислений» в бизнес постановке написано «Платеж отправляется в очередь kafka» У этого правила есть особенность: Да, смешивать документы нельзя. В бизнес требованиях не должно быть системных атрибутов. Но есть особенность описания системных требований. В системных требованиях хорошим тоном считается не только описания системного действия (отправьте сообщение в такой-то журнал), но и какому бизнес действию оно соответствует. Например «Получите список заказов клиента. Для этого выполните запрос …» Это облегчает понимания документации и её сверки с бизнес постановкой.
Системная документация
Основные принципы мы проговорили. Понимаем, что речь дальше пойдёт о системной документации, спецификациях на сервисы, описании эндпоинтов, страниц фронта, сообщениях в очередях и структуре БД.
Бизнес документацию не трогаем. Ни какие бизнес-процессы и их описание в системную документацию не дублируются.
Даже если у вас крутится Camunda, которая реализует какой-то бизнес процесс, помните: Есть схема бизнес процесса в бизнес требованиях. И есть BPMN схема с обработчиками в коде.
Это две разные схемы, хоть одна и реализует другую.
Как структурирована идеальная документация в моем мире и при чем здесь doc-as-a-code
Вообще, со мной произошёл странный казус, который в корне поменял мое представление о системной документации. Когда я первый раз услышал термин doc‑as‑a-code я понял это так:
«Структура документации соответствует структуре кода». Ну как понял, так и пошел писать, дабы учителя понимали так же.
В результате структура документации на обычный backend REST сервис состоит из следующих артефактов:
Swagger для описания контрактов взаимодействия. Или proto-схема, если у вас grpc.
Спецификация каждого эндпоинта, состоящая из:
Пути запроса и его параметров
Примеров тела запроса и ответа
Sequence-диаграммы со всеми интеграциями
Логика исполнения эндпоинта, в которой указывается
какие запросы выполняются в какой последовательности
какие данные и как сохраняются
какие сообщения в какие журналы передаются
какие компоненты сервиса вызываются
Если логика сложная — activity диаграмма
Маппинга полей для сохраняемых и передаваемых данных
Описание всех таблиц в виде DDL файлов или DBML (если реляционная БД) или коллекций в виде yaml-файлов (для нереляционок)
Если сервис читает сообщения в журналах, то описывается логика каждого консьюмера.
и readme файл, содержащий общую информацию о сервисе со ссылками на все его компоненты
Если есть frontend, то спецификация аналогичная:
на каждую страницу — артефакт документации, включающий:
макеты экранных форм
мапинг предзаполнения полей
мапинг отправляемых данных
логика обработки получаемых данных
логика работы элементов формы
Если у вас сервис, на котором крутится camunda, то документация будет содержать:
bpmn схему
описание логики получения событий
описание логики задач
описание шлюзов
Таким образом, артефакты документации соответствуют тем или иным артефактам кода. Необходимо понимать, что код устроен по другому. И это не попытка спроектировать структуру кода.
Это документация на функционал. Это описание того, как должна работать система.
При этом есть один важный момент: такие артефакты как swagger, описание сообщений в asyncApi и таблицы, описанные на DDL — это часть работы разработчика, которая передаётся аналитику.
У этой парадигмы есть плюсы и минусы.
С одной стороны не надо делать одну и туже работу дважды. Ведь если аналитик описывает БД в виде таблицы, содержащей название полей, тип данных, описание этого поля, то разработчик это всё должен перенести в код. Руками. И могут быть ошибки.
С другой стороны, не все готовы работать в такой парадигме. Разработчику остаётся только писать код. У него забирается функция проектирования решения. Многие разработчики против такого подхода.
Теперь по настоящему doc as code
«Ну хорошо» — скажете вы — «всё то же самое делается в конфе. При чём здесь Git?»
Про сам подход уже много чего написано. Наверное, я не буду здесь пионером и во многом повторюсь.
Суть:
Документация ведется в репозитории Git.
может лежать в репозитории сервиса и быть его частью
может лежать в отдельном репозитории документации, где лежат спецификации всех сервисов системы
для спецификаций используются:
swagger / openApi — контракты REST сервисов
protobuf схемы — контракты сервисов grpc
asyncApi — требования к журналам сообщений
markdown, asciidoc — спецификация артефактов
plantUML, mermaid — диаграммы
ddl sql, dbml, yaml — требования к БД
Правки в документацию вносятся через merge/pull request
Возможность распределённой работы с документацией
Версионирование средствами Git
Согласен, в той же конфе гораздо больше «бантиков». И таблицы разнообразнее, и всякие красивые вставочки, и форматирование, и плагины.
С моей точки зрения, главное в конечной документации, это понятно изложенная информация и удобный процесс поддержания актуальности. А для этого текста и простых диаграмм достаточно.
Просто надо для себя решить: «вам шашечки или ехать?»
На живом примере
Теперь самое интересное.
Давайте соберем это всё в кучу, и посмотрим, как это ложится на процесс разработки и как будет работать. Заодно поймем, почему в конфе такого сделать не получится.
За спецификацию у нас отвечает системный аналитик, про его работу и поговорим.
Представьте:
У нас есть некая система, состоящая из Фронта, промежуточного слоя BFF (back for front) и глубокого бэкэнда.
И есть функционал «Создание заказа».
На фронте пользователь нажимает кнопку «сохранить», отправляется POST запрос в BFF который проверяет данные и передает их в бэк. Бэк сохраняет их в БД и отправляет сообщение в какой‑нибудь журнал.
Такая вот нехитрая архитектура.
Это всё у нас уже разработано и работает. И задокументировано!
И вот к нам приходит продакт с постановкой: добавьте на форме чекбокс «срочный заказ». Если пользователь его устанавливает, то меняется стоимость заказа, и менеджер должен получить особое уведомление.
Архитектор проработал эту сторю и спроектировал дополнительный журнал, в который мы должны отправлять сообщение, если этот чекбокс стоит.
Наша команда отвечает только за первую часть бизнес процесса — «Создание заказа». Уведомление менеджеров и взаиморасчёты — это другие команды.
Обсудили решение, и системный аналитик взял сторю в работу.
Напоминаю, что мы строго придерживаемся принципа «documentation first» (включая api).
По результатам работы он внесёт изменения в следующие артефакты:
Спецификация формы «Создание заказа» на фронте
Спецификация эндпоинта createOrderBFF в BFF
Swagger BFF
Спецификация эндпоинта createOrderBE на бэке
Swagger BE
DDL-скрипт таблицы orders (или описание таблицы, если постановка на БД ведётся по старинке)
Спецификация журнала OrderCreated
asyncApi журнала OrderCreated
и добавить ещё два артефакта:
Спецификация журнала UrgentOrderAppointment
asyncApi журнала UrgentOrderAppointment
Итого у нас затронуто 10 артефактов.
В Git это будет 10 разных файлов.
В конфе это будет 5 статей и 5 приложенных к ним файлов.
Эти изменения необходимо согласовать с разработчиками, а потом нарезать на задачи.
Используем классический подход
Как будет выглядеть процесс, если у нас документация ведется в системах а-ля wiki, или даже word:

Т.е. аналитик должен:
Внести изменения в 10 артефактов. (Я встречал подход, в котором изменения маркируются в тексте спецификации разными цветовыми маркерами. После разработки маркеры надо удалять.)
Выписать все внесённые изменения в задачу, с которой он работает.
Согласовать эти изменения. Если будут замечания (разработчики решили, что нэйминг поля не соответствует регламенту) — повторить всё ещё раз.
Выписанные изменения перенести в задачи.
т. е. аналитик пишет одно и тоже как минимум 3 раза. 3 раза он делает одну и туже работу.
Я привел в пример простую задачу. В реальности, задачи могут охватывать большее количество артефактов и гораздо более сложную логику, которая должна быть реализована.
Также часто бывают случаи, когда два аналитика берут разные стори, в рамках которых правятся одни и те же артефакты.
Как, в таком случае, отличить правки одного аналитика от другого? Помечать разными цветами? А как потом эти цветовые маркеры удалять? И в какой момент?
А теперь представьте, что в момент согласования задачи с разработчиками пришел продакт и сказал: стоп ребятки! У нас есть более важная задача: добавить в заказ поле «Комментарий сборщику».
Или быть может эту сторю уже делает второй аналитик, и работает параллельно.
Что делать? Откатывать документацию? Оставлять как есть с надеждой, что сделаем в следующем спринте? А какая версия свагера поедет в релиз? С обоими полями?
Используем doc-as-a-code
А теперь представим, что у вас doc-as-a-code. В этом случае процесс работы аналитика заметно упрощается. Пункты практически те же, но их качество кардинально другое.

В начале работы с задачей SA создает новую ветку в репозитории спецификации.
Все правки в документацию вносятся в эту ветку и по завершению работы создаётся один Merge/Pull Request (MR). Если у вас документация на все сервисы лежит в одной репе, а не в репозитории кода — то это один MR.
Созданная ветка живёт своей жизнью. Пока MR не слит — она не затрагивает текущую версию вашей документации. Даже если вы решите не делать эту сторю, наработанные изменения не попадут в основную ветку, но их можно будет «прикопать» на будущее.
Если несколько аналитиков параллельно работают над разными задачами, то каждый вносит правки в свою ветку. И пока MR не слит, эти правки не влияют друг на друга.
При согласовании с разработчиками обсуждается DIFF в этом MR, который генерируется автоматически. А в нём видны все внесенные изменения. Если надо что-то поменять — правки идут отдельными комитами в ту же ветку и DIFF автоматически обновляется.
После согласования MR сливается. Документация в целевой ветке обновляется. При этом вам по прежнему доступен DIFF. А также вы можете легко откатить всё внесенные изменения, если работу пришлось отменить.
В созданных задачах указывается ссылка на конкретный файл в DIFF, относящейся к конкретной задаче на разработку.
Таким образом, системный аналитик делает свою работу один раз и получает всё необходимое:
обновленную целевую документацию
перечень, что надо изменить со ссылками на изменяемые артефакты
Даже если после согласования с командой есть необходимость в правках, то исправляется всё в одном месте.
С моей точки зрения, это в 3 раза быстрее и в 3 раза меньше шанс что-то где-то забыть исправить и получить неконсистентные данные в постановке между задачей и конечной спецификацией.
Ах да, у нас же пришел продакт и попросил «сделать другое»…
Что ж… это тоже достаточно просто:
Откатываем MR. Это одно простое действие. Вам не надо бегать по всем артефактам и вспоминать, «а как было до этого».
Делаем новый MR для новой задачи.
А когда продакт решит, что первую задачу всё-таки делаем, то все изменения, которые были отменены, можно восстановить и сделать новый MR. Тоже для всех артефактов разом, а не по отдельности.
Парам-пам-парам-пам! Всё!
Ещё пара слов
Doc as a code это не только упрощение процесса ведения вашей документации.
Хочу отметить ещё несколько моментов:
Артефакты документации могут быть преобразованы в артефакты кода. Что это значит:
используя swagger и asyncApi можно автоматически генерировать DTO в коде
используя DDL SQL можно генерировать миграции
Для написания кода используется IDE. Это позволяет:
работать в offline
использовать специализированные плагины, вместо онлайн ресурсов (тот же swagger, plantuml)
использовать ИИ-ассистенты. Это реально ускоряет написание спецификации процентов на 20…
использовать ту IDE, которая удобна вам, а не ограничиваться возможностями вашей wiki системы
Более продвинутое версионирование, чем в confluence.
если вы используете правильный процесс изменения спецификации через MR, то для каждой измененной строки можно найти MR, в котором она была изменена. А MR привязан к задаче.
используя специальные инструменты IDE вы можете видеть, что этот же артефакт сейчас исправляет другой аналитик.
Продвинутое использование артефактов документации.
PlantUml с операцией include позволяет вести разные представления диаграмм из одного источника в нескольких публикациях. Вам не придётся поддерживать одинаковые диаграммы в нескольких местах.
asciidoc позволяет собирать из нескольких документов один с необходимым набором внутренних артифактов. Вы можете собирать документы для разных целевых потребителей из одного источника, что упрощает поддержку документации.
Резюме
Не могу сказать, что для меня ведение системной документации в Git стало чем‑то революционным. Я просто попробовал, и больше не смог вернуться на старые рельсы.
Да, был период косяков с MR‑ами, освоения markdown, plantUml, DDL SQL, работы с ветками и т. д.
Да, на освоение новых инструментов нужно время. По моим прикидкам, если у вас уже есть гуру doc‑as‑a-code, то за месяц аналитики перейдут на новый процесс.
Если нет — то за три. Да, будут набиваться шишки. Да, иногда будет не хватать красивого форматирования, и придётся оттачивать подход другими способами.
Но если у вас принято считать деньги, потраченные на каждую сторю, то я уверен, что через три месяца вы увидите колоссальную экономию ресурсов.
И перейдя на этот процесс, будете задаваться вопросом: «а как мы до этого всё это делали?»