Меня зовут Игорь Савинов, я работаю системным аналитиком в Альфа-Банке более 5 лет. Последние несколько лет занимаюсь новым интернет-банком для юридических лиц в части внешнеэкономической деятельности, а до этого развивал внутренние сервисы. Сначала немного упомяну о Docs as Code и миддловой документации, чтобы при сравнении были хорошо видны проблемы фронтовой документации (и про решение тоже расскажу).

Кратко о документации и Docs as Code

Docs as Code — это подход к разработке документации с использованием тех же инструментов и процессов, что и для написания кода. Например, мы используем одни и те же инструменты с разработчиками: Git, IDE, CI/CD и другие различные аббревиатуры. С Docs as Code мы можем автоматизировать сборку документации в различных форматах и её публикацию, автоматизировать как часть документации, так и всю, а ещё снижается процент расхождения документации и кода.

Но с другой стороны:

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

  • Там, где у нас есть автоматизация, необходим процесс настройки и поддержки всего процесса.

Документация в Альфа-Банке делится по слоям: фронт, миддл и бэкенд.

Фронт — слой микросервисов UI-приложения. Здесь мы ведём документацию в Confluence. Также можем использовать различные плагины, например, PlantUML.

Бэкенд — это у нас ABS банка. По ней долгое время документация велась в Word и Excel, но, к счастью, мигрировала в Confluence. 

Миддл — это слой микросервисов. Здесь мы применяем Docs as Code, в качестве языка разметки используем AsciiDoc, для генерации диаграмм PlantUML, а для отслеживания изменений и ревью — Bitbucket.

Документация на миддл-слой ведётся так:

  • На каждый сервис есть свой git-репозиторий.

  • В каждом репозитории есть отдельная папка для ведения документации и любой из членов команды разработки может внести свои изменения.

  • После того, как изменения успешно попадают в ветку master, запускается пайплайн. В качестве системы CI/CD у нас собственная платформа на базе Jenkins.

  • Далее собирается билд, а итоговый артефакт в формате HTML публикуем в своем хранилище JFrog Artifactory. 

Немного о формате и структуре.

index.adoc. В корне папки docs/asciidoc есть файл index.adoc, в котором перечисляются все методы API с кратким пояснением, и ссылкой на более подробное описание.

Пример index.html
Пример index.html

db.adoc. Отдельный файл для описания структур БД, где также могут описываться, например, kafka топики.

config.adoc. Файл для описания конфигов: ссылка на сервис конфигов, или текстовое описание, которое в дальнейшем может использоваться для описания метода сервиса.

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

currencyPayments — каталог, который есть у каждого метода сервиса. В таком каталоге у нас есть 4 файла.

  • №1. Одноименный файл с каталогом с расширением .adoc. В нем описана вся логика, бизнес-описание, схема, пошаговый алгоритм, маппинги обработки кодов ошибок.

  • №2. Файл diagram.puml. В нём может быть диаграмма активностей или последовательности.

  • №3. request.adoc — пример запроса метода сервиса.

  • №4. response.adoc – примеры ответа метода сервиса.

Последние два файла включаются внутрь основного файла с использованием специальной команды include.

Итоговый билд в формате .html.

currencyPayments.html
currencyPayments.html

Проблемы и решения фронтовой документации

Единственным отличием и проблемой документации фронт слоя от миддл стало наличие изображений экранных форм.

При сохранении изображений и их изменений в Git они сохраняются в истории коммитов, увеличивая размер нашего репозитория. 

Например, пусть одно изображение весит 300 КБ, а в проекте их может быть также 300, то это уже будет 90 МБ репозитория. Предположим, что мы будем апдейтить 30% документации один раз в месяц — через месяц репозиторий будет весить 117 МБ, а через год практически 1,5 ГБ. При этом стандартный фронтовый репозиторий весит 6 МБ (не учитывая всякие зависимости).

Чтобы избежать данной проблемы, решили использовать Git LFS. Это расширение для Git, которое заменяет большие файлы на текстовые указатели, а само содержимое файлов сохраняет в удалённом хранилище. 

Например, при добавлении файла в репозитории, Git LFS заменит его на текстовый указатель, а сам файл сохранит в локальном хранилище Git LFS.

Источник: https://www.atlassian.com/git/tutorials/git-lfs 

Когда мы захотим отправить новый коммит, где есть указатели Git LFS, которые ссылаются на эти коммиты, мы перенесем их файлы из локального хранилища в удалённое, которое будет привязано и настроено к нашему репозиторию.

Источник: https://www.atlassian.com/git/tutorials/git-lfs 

При переключении на какие-то коммиты, которые содержат указатели Git LFS, мы уже заменим наши текстовые указатели из локального хранилища или из удаленного.

Источник: https://www.atlassian.com/git/tutorials/git-lfs 

Стоит отметить, что Git LFS работает незаметно для пользователя — не надо специально выполнять эти самые команды, всё происходит фоном при выполнении стандартных команд. Например, при команде git pull, когда мы хотим получить изменения к себе в рабочую копию, Git LFS автоматически подтянет только те файлы, на которые он ссылается, а не все существующие версии.

Первоначально мы хотели хранить сами файлы также в JFrog Artifactory, но от этого варианта отказались, потому что Bitbucket ничего не знает про Artifactory. Когда мы просматривали файлы с изображениями в Bitbucket, файл не отображался — была ошибка с указанием на то, что файл хранится в каком-то удалённом хранилище LFS.


Ну раз Bitbucket ничего не знает про Artifactory, то сам про себя-то он что-то знает? И решили использовать стандартное хранилище на Bitbucket сервере для хранения файлов в Git LFS. Поэтому к уже знакомой схеме по миддл-документации добавляется Git LFS.

Структура документации на фронт практически такая же, как и на миддл.

  • Также есть файл index.adoc, где есть краткое описание спецификации.

  • Есть папка _еxternal, где у нас находятся запросы внешних сервисов.

  • Каждая спецификация также располагается в отдельном каталоге.

  • В каждом таком каталоге появляется папка images, в которой мы сохраняем непосредственно наши изображения.

  • Есть небольшие отличия в том, что у нас в каждом каталоге нет примеров запросов и ответов, потому что для фронтового вызова это будет какой-то внешний сервис и он будет описан в папке _еxternal.

  • Также нет каких-то файлов типа db.adoc, потому что мы взаимодействуем с ними через миддл-слой.

Вот как это выглядит в коде:

  • Есть описание сценария.

  • Внутри сценария указываем якорь ссылки на макеты.

  • Под каждым пунктом есть макеты, их скрываем в html элемент <details> с помощью команды [%collapsible], в этом блоке описываем уже непосредственно ссылку на изображение. 

  • Дополнительно для каждого изображения можно указать атрибуты, например, ширина и признак открытия изображения в новом окне.

Как выглядит результат

Итак:

  • В начале блок с общей информацией, в котором располагаются ссылки на архитектурную документацию, макеты, задачи, другие связанные документы.

  • Далее блок с описанием бизнес-процесса.

  • Описание самой фичи, где по действиям расписаны шаги пользователя с примерами запросов и ответов сервисов.

  • Также под каждым действием есть макеты.

  • В конце идет описание экранных форм. Здесь описываются общие элементы со страницы, например, фильтры или календарь.

В итоге получается, что документацию по миддл слою мы ведём где-то с 2017 года. По фронтовой документации прошли пилот, теперь можем успешно её автоматически собирать, тестировать и измерять метрики работы аналитика.

Примечание про пилот.

Вообще, на первом этапе мы решили вести документацию для фронта в отдельном репозитории — почти рядом с кодом.

В Альфа-Банке уже имелся настроенный asciidoctor gradle plugin, который мы использовали для сборки документации на Java-сервисах. Чтобы не тащить gradle в проекты с фронтом, мы решили доработать фронтовый пайплайн и использовать специальный плагин asciidoctor.js. И пока у нас дорабатывался пайплайн, решили не терять время и переносить документацию с Confluence в Git с использованием разметки asciidoc. 

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

Сейчас мы в активной части пилота, где документация располагается рядом с кодом.

  • Для сборщика у нас используется asciidoctor.js.

  • Изображение мы храним в Git LFS. 

  • Язык разметки также asciidoc, как и для миддл слоя.

  • Система контроля версий Bitbucket.

  • Для написания документации в качестве IDE преимущественно используем IDEA, но ограничений нет.

Проблема с фронтом также касалась и бэкенд слоя — здесь тоже есть изображения, которые необходимо описывать в документации. Нам остается только адаптировать форматы и можно будет приступать к пилоту по бэкенд слою.

Используете ли вы подход Docs as Code? Как ведет в этом случае документацию? Ведет ли документацию рядом с кодом? Как решаете проблему с изображениями?


Полезные ссылки:

Также подписывайтесь на Телеграм-канал Alfa Digital — там мы постим новости, опросы, видео с митапов, краткие выжимки из статей, иногда шутим.

Комментарии (4)


  1. yaguarundi
    01.09.2023 08:18
    +1

    Мы используем Docs-as-Code. Точнее переходим на него сейчас. LFS тоже подключили.

    Но я не понял, что за команда git lfs add на картинке. Там же надо сделать git lfs track... и всё. Никаких lfs add мы не делаем.

    Ещё такой эффект заметил. Если проект был без LFS, а потом вы его подключили, то те файлы, которые начинают отслеживаться LFS, из основного хранилища в LFS не переносятся. Их старая копия остаётся в Git навсегда.


    1. savinov_garik Автор
      01.09.2023 08:18
      +3

      Привет. Команда git lfs add выполняется в фоне, когда ты добавляешь файл в репозиторий. Ты можешь просто перетащить файл в определенную директорию в IDE или добавить файл с помощью команды git add и если у тебя настроен track файлов на данный тип, то выполниться еще и команда git lfs add. Данную команду не надо выполнять отдельно. 

      Если необходимо подключить LFS в текущий репозиторий и перенести уже существующие файлы и очистить историю, то можно почитать про команду git lfs migrate. Есть еще есть BFG Repo-Cleaner, но это вроде устаревшее решение.


  1. savinov_garik Автор
    01.09.2023 08:18

    -


  1. andyblaster
    01.09.2023 08:18

    У нас попроще, документация на уровне команды, пока хватает material for mkdocs, это генератор статических сайтов на питоне в markdown-разметке. Ну и рядом, в том же репозитории, схемки API под классический Swagger/reDoc. Публикация через GitLab CI тупо копией собранной странички/сайта на веб-сервер. До картинок еще не дошли. В общем, без особых откровений.