В Альфа-Банке мы уже больше 5 лет ведём документацию рядом с кодом. Однако эта практика используется не везде. Дело в том, что документация у нас делится по слоям: фронт, миддл и бэк. Если с миддлом — слоем микросервисов — всё хорошо, то с фронт- и бэк-документацией возникает трудность, связанная с необходимостью хранения бинарных файлов, изображений с примерами пользовательского интерфейса.

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

Кратко о том, как ведём документацию

Документация — неотъемлемая составляющая программного продукта. Для обеспечения консистентности его частей хочется работать над ним, используя единые инструменты. В этом случае шанс того, что код разойдётся с документацией, ниже, чем в случае, когда код ведётся в одной системе, а документация в другой. Особенно если код и документацию пишут и ревьюят разные люди.

Проектная документация у нас делится по слоям: на фронт, миддл и бэк. И в зависимости от слоя мы ведём её в разных местах.

Миддл. Рядом с кодом лежит документация на миддл-слой или слой микросервисов. В качестве системы контроля версий используем Bitbucket. Для разработки документов используем язык текстовой разметки AsciiDoc в связке с PlantUML, который позволяет создавать диаграммы из текста.

Фронт. Документацию на фронт мы также могли бы вести рядом с кодом, но она требует изображений с примерами пользовательского интерфейса — бинарных файлов. А они достаточно тяжелые по сравнению с текстовыми файлами с исходным кодом. Если хранить их в Bitbucket, то репозиторий быстро раздувается, а при обмене данными между локальными машинами и сервером нагрузка на сеть сильно растёт. Поэтому документацию на фронт мы ведём в Confluence.

Бэкенд. Под бэкендом я, в первую очередь, понимаю нашу АБС Equation (примечание: Equation — комплексная, многовалютная и многоязычная система для банков). Исторически, документация на неё, — это спецификации в MS Word и MS Excel, размещаемые в базах Lotus Notes. Со временем их мигрировали в Confluence.

Документацию на бэк можно перенести в Bitbucket. Но у модулей АБС есть собственный пользовательский интерфейс, поэтому при миграции документации также возникает вопрос о хранении бинарников, который мы пока не решили.

Итого. Документацию на миддл ведём рядом с кодом, на фронт и бэк — в Confluence.

Основная проблема переноса фронт- и бэк-документации в Bitbucket — в необходимости хранения бинарных файлов с примерами пользовательского интерфейса. Проблема в том, что это всё много весит.

Ниже опишу, как мы работаем с миддл-документацией. А после рассмотрю вариант, что мы можем сделать с фронтом и бэком, как здесь решить проблему с бинарниками.

Подробнее о том, как ведём документацию на миддл-слое

Процесс ведения документации на миддл выглядит так:

  • Есть проект в Bitbucket. В проекте находятся репозитории с исходным кодом микросервисов.

  • Файлы с исходниками распределены по папкам. Одна из папок предназначена для файлов документации на микросервисы.

  • Члены команды разработки выгружают репозитории с исходным кодом и документацией себе на локальные машины при помощи git. 

  • Вносят изменения и отправляют их на сервер Bitbucket на ревью.

  • После успешного ревью изменения мержим в master-ветку.

  • Система CI/CD узнаёт об изменениях в master, выгружает исходники и прогоняет их по преднастроенному pipeline. Конкретную систему не указываю — на моей памяти их было несколько: сначала использовали Jenkins, затем пилотировали GoCD, потом переключились на Bamboo. Сейчас переходим на собственное решение, под капотом которого крутится тот же Jenkins.

  • Получившиеся сборки кода и документации размещаются в Artifactory. Документация представлена в виде HTML-файлов.

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

Для описания сервиса можно использовать следующую структуру файлов:

  • index.adoc — корневая спецификация: содержит общее описание сервиса и ссылки на его методы.

index.adoc
index.adoc
  • getReport — папка с файлами: описывает метод getReport.

  • getReport/getReport.adoc — спецификация метода getReport.

getReport/getReport.adoc
getReport/getReport.adoc
  • getReport/getReport.puml — файл с описанием диаграммы: отражает логику  работы метода getReport.

getReport/getReport.puml
getReport/getReport.puml

С данными файлами члены команды разработки работают локально. Очевидно, содержимое файлов не очень наглядно, потому что содержит текстовую разметку. Хочется видеть собранный документ.

Результат можно увидеть в интерфейсе IntelliJ IDEA с установленными плагинами AsciiDoc и PlantUML Integration. Также документацию можно собрать локально.

Примечание. Для сборки в учебных целях можно использовать движок Asciidoctor с расширением Asciidoctor PlantUml. В качестве PlantUML Server задействуем https://www.plantuml.com.

Пример команды сборки:

PLANTUML_URL="https://www.plantuml.com/plantuml"   \
PLANTUML_ENCODING="deflate"                        \
asciidoctor -r asciidoctor-plantuml index.adoc getReport/getReport.adoc

В результате её выполнения будут созданы два файла - index.html

index.html
index.html

и getReport/getReport.html.

getReport/getReport.html
getReport/getReport.html

В собранном виде документация наглядна. В ней есть ссылки, таблицы, схемы и пр. И, кажется, остальную документацию также следует вести рядом с кодом. Но что делать с бинарниками?

Основная проблема хранения бинарников рядом с кодом — их размер. 

Нужно найти альтернативный способ хранения данных файлов. Здесь может помочь Git LFS. В качестве хранилища для исходников документации оставляем Bitbucket, а изображения с примерами пользовательского интерфейса будем складывать в Artifactory в репозиторий GitLfs.

На примере документации для фронта покажу, как помогает Git LFS.

Как ведём документацию на фронт?

Процесс ведения документации на фронт будет выглядеть следующим образом:

  • По аналогии с репозиториями микросервисов в репозиториях с исходным кодом фронтовых приложений появится папка для ведения файлов документации.

  • Для бинарных файлов с примерами пользовательского интерфейса в ней можно создать отдельную подпапку, документы из которой будет отслеживать Git LFS.

  • Члены команды разработки выгружают репозитории с исходным кодом и ссылками на файлы документации себе на локальные машины при помощи git. Если нужны сами файлы документации по ссылкам — с помощью Git LFS. 

  • После внесения изменений бинарники с примерами пользовательского интерфейса уходят на хранение в Artifactory, а исходный код со ссылками на них — на сервер Bitbucket на ревью. 

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

  • После успешного ревью, как и раньше, изменения мержим в master-ветку.

  • Система CI/CD должна будет в процессе сборки научиться получать бинарники из Artifactory. В остальном pipeline останется без изменений.

  • Получившиеся сборки кода и документации как и прежде размещаются в Artifactory. Здесь важно отметить, что бинарники для собранной в HTML документации — это часть сборки. Поэтому они будут повторно размещены в Artifactory, что потребует дополнительных ресурсов на сервере.

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

  • index.adoc — файл с текстовым описанием пользовательского интерфейса;

index.adoc
index.adoc
  • images - папка со скриншотами;

  • images/index.png - скриншот пользовательского интерфейса, в котором отображается отчёт.

Источник: https://vc.ru/alfabank/94450-115-fz-prostymi-slovami-pochemu-banki-blokiruyut-karty-i-internet-bank-i-chto-delat-esli-eto-proizoshlo
Источник: https://vc.ru/alfabank/94450-115-fz-prostymi-slovami-pochemu-banki-blokiruyut-karty-i-internet-bank-i-chto-delat-esli-eto-proizoshlo

После сборки получим файл index.html, содержащий в т.ч. пример пользовательского  интерфейса, в котором отображается отчёт по клиенту на заданную дату.

Так выглядит index.html после сборки.

index.html
index.html

Таким образом, фронтовую и бэк-документацию можно вести рядом с кодом, даже если там есть бинарники с примерами пользовательского интерфейса. Данное решение было опробовано на моей локальной машине с использованием пробных версий Bitbucket и Artifactory. Далее планируется пилот на инфраструктуре Банка с использованием банковских систем и данных реальных проектов.

Итог

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

Если вы ведёте документацию рядом с кодом и столкнулись с описанной выше проблемой хранения бинарников (с примерами пользовательского интерфейса) или другими проблемами, будем рады, если поделитесь опытом в комментариях.

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


  1. fiddle-de-dee
    09.08.2022 22:34
    +1

    Спасибо за статью. Действительно при всех плюсах документация очень медленно переползает в исходники и действительно есть объективные причины, которые медленно преодолеваются.

    Именно вопрос скриншотов нам в некоторых проектах удалось решить по-другому. Всё равно конечный продукт (back+front) собирается в CI и всё равно e2e тесты бегают. Достаточно добавить тесты, которые создают автоматические скриншоты. У нас есть требование, чтобы все окна, требующие скриншот в документации, вызывались через URL. Поэтому на выходе работает всего один простой параметризованный тест. Понятно, всё равно могут быть бинарные файлы (например, какой-нибудь мем в документации.. meme as code пока вроде не придумали), тогда да, LFS.

    Вопрос ревизии MR, кстати, тоже можно решить. Достаточно на этапе сборки MR собрать выходной документ и сравнить с выходным документом предыдущей версии основной ветки. А файл сравнения уже будет содержать не текстовой diff, а diff выходного документа с картинками, форматированием, зачеркиваниями, отчеркиваниями и всем, всем, всем.


    1. alobzov Автор
      10.08.2022 01:09

      Спасибо за комментарий. Любопытный подход с генерацией скриншотов автотестами и их получением по URL.

      Мы в своё время смотрели в сторону генерации фронтовой документации полностью в автоматическом режиме с использованием собственной BDD-библиотеки Akita. Но всё же не пошли в эту историю ввиду существенных ограничений в части представления информации


  1. TatyanaSalnikova
    10.08.2022 09:12
    +1

    Спасибо за статью.

    Подскажите, какие преимущества у документации рядом с кодом, если по ней потом нет кодогенерации и проверки актуальности кода документации?


    1. alobzov Автор
      10.08.2022 09:55
      +1

      Хороший вопрос. Тоже им регулярно задаюсь.

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

      Мы как-то проводили оценку качества документации. Результаты показали, что документация рядом с кодом более актуальна, чем документация, ведущаяся в других системах.

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


      1. TatyanaSalnikova
        10.08.2022 11:23
        +1

        Хм, спасибо. На последних двух местах работы проверяют доки на полноту и актуальность через процесс: разработчик не берет в работу задачу без описания. Там же происходит и ревью.

        На мой взгляд, у этого решения есть плюсы:

        • документация сразу наглядна и доступна всем пользователям конфы (idea не надо устанавливать, опять же))

        • Меньше порог входа и, кажется, время на написание документации

        • Сам процесс эффективный, так как он предотвращает разработку фич без анализа и без оповещения всех заинтересованных в данном куске функционала. То есть меньше риск сделать фигню и/или кого-то поломать.

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


        1. alobzov Автор
          10.08.2022 11:34
          +1

          Это неплохая практика. Однако риск неактуальности документации сохраняется, т.к. реализация не всегда в точности соответствует постановке. Плюс постановка не всегда полна.

          Описанные преимущества действительно имеют место быть. Однако есть и недостатки, связанные с возрастающим TTM для новых фич, т.к. разработка полной и всеобъемлющей постановки может потребовать довольно много времени. Нужно искать баланс


          1. TatyanaSalnikova
            10.08.2022 14:16

            Ну кстати ТТМ, как показывает практика, в итоге при таком подходе меньше.

            Так как иначе много багов и переделок.

            Но допускаю, что не везде.

            Риски неактульности сохраняются и для документации в коде, если не делать автоматических проверок. Но как писали ниже - с документацией рядом с кодом такие проверки легче внедрить.


    1. fiddle-de-dee
      10.08.2022 12:07
      +2

      Помимо удобного ревью разработчиком я бы назвал еще

      • Обновление документации может входить в definition of done

      • Править документацию быстрее, т.к. она лежит в том же проекте

      Ну и, конечно, документация в коде сама по себе создает условия для применения процедур автоматического обеспечения/контроля актуальности.

      Те же скриншоты у нас тоже сначала лежали в LFS-ной папочке. Потом, кстати, долго медитировали надо опытом Akita. И в конце родилась идея с URL. Причём родилась она сначала не для документации, а для упрощения тестирования и улучшения UX. Вообще, возник хороший принцип -- не принимать никаких архитектурных решений исключительно ради документации, но при оценке архитектурных решений учитывать критерий документируемости


  1. RomanBlinov
    11.08.2022 09:37
    +1

    Добрый день! Интересная статья, но в обозначенной проблеме я вижу один важный пробел, касающийся медленного и тяжелого развития docs as code в Вашем случае. Создается впечатление, что изначальная цель ведения документации в таком формате не обозначена. Для чего вообще требуется держать доки рядом с кодом? Я бы для начала сконцентрировался именно на вопросах необходимости переноса документации в репозитории из конфлюенс - это первый момент, который рекомендуют при начале подобных действий. Доки в гите - вещь сложная и неоднозначная. В нашей компании (Zyfra) мы осознали данную необходимость, в первую очередь, в связи с тем, что CI/CD - это наш основной процесс доставки кода клиенту, вместе с ним уходят и доки, разворачиваются в виде портала у заказчика, плюс портал развернут на наших серверах и мы можем его сделать доступным из глобальной сети. В данном случае вопрос заполненности репозиториев картинками не очень актуален, не так уж они много месте жрут. Зато есть быстрый и удобный инструмент работы с доками без необходимости выдачи доступов и т.п. танцев с бубном. Кстати, такой вопрос, а как Вы даете пользователям доки из конфлюенс? Или каждый раз при необходимости экспортируете?


    1. alobzov Автор
      11.08.2022 10:15

      Спасибо за комментарий и вопрос.

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

      Что касается вопроса. Пользователи документации - внутренние сотрудники Банка, в первую очередь, члены команд разработки и специалисты функционального сопровождения. Наиболее частая конфигурация в Confluence такая. Есть пространство канала (например, Альфа-Бизнес Мобайл). Внутри пространства разделы с продуктами. Потребителю документации достаточно один раз получить доступ к пространству канала, чтобы начать знакомиться с документацией по составляющим его продуктам. Каких-то проблем с получением доступов в этой части не встречал


      1. RomanBlinov
        11.08.2022 10:29

        Спасибо за ответ. Но тогда как-то пропадает необходимость переноса пользовательской документации в репозитории, и вести доки для внутреннего пользования действительно удобнее в конфлюенс, и все материалы, содержащие пользовательские истории, скриншоты и т.п. проще держать во внутренней базе знаний с настроенными макросами для переиспользования, цитирования и др., а для обеспечения консистентности проще назначить пару хороших редакторов, которые будут отслеживать процессы разработки и обновления ПО. Это будет дешевле, и не надо париться над репозиториями, мердж-реквестами, черепиками и другим шаманством. Опять же, не надо дополнительно обучать сотрудников. Все-таки docs as code - это парадигма работы с внешним заказчиком и с интернет-ресурсами.


        1. alobzov Автор
          11.08.2022 10:49

          Согласен, везде есть свои преимущества и недостатки. Однако пара редакторов в масштабах банковского ИТ - это ничто. Отдел редакторов - вопрос экономической целесообразности. Тем более, если эти люди вне команд разработки и имеют слабое представление об устройстве разрабатываемого продукта


          1. RomanBlinov
            11.08.2022 11:05
            +1

            Да, согласен, конечно, "на вкус и цвет...". Я бы, со своей колокольни, порекомендовал подумать в сторону концепции документирования docs as part of development team, частью которой является docs as code, и подумать над тем, как плотнее включить писателей в процесс разработки - это к "если эти люди вне команд разработки и имеют слабое представление об устройстве разрабатываемого продукта" - просто тогда будет значительно меньше узких мест с актуализацией документации.


  1. Puppets
    11.08.2022 10:17

    Спасибо за статью.

    Есть пару вопросов) Если над одной частью системы работают одновременно 2 аналитика, и вносят изменения в схему PlantUML. Корректно ли потом происходит мердж или бывают ошибки рендеринга PlantUML ?

    Есть ли опыт работы в BitBucket со схемами BPMN 2.0 ( в формате XML) ? Если есть, то там аналогичный вопрос про мердж.


    1. alobzov Автор
      11.08.2022 10:27

      Отвечая на первый вопрос, конфликты поможет решить система контроля версий.

      Что касается второго. С описанием BPMN в формате XML не сталкивался. Однако XML - это текст. Поэтому ситуация будет аналогичной первому кейсу


      1. Puppets
        11.08.2022 12:31

        Насколько я знаю, BPMN 2.0 как раз тем и примечателен, что его можно перевести в XML. Например в Camunda modeler можно посмотреть описание схемы в XML.

        Что же касается первого вопроса. Я понимаю что система контроля версий может разрешить) Просто хотел узнать были ли у вас конкретно случаи, что параллельно в одну и туже схему PlantUML вносят изменения, а после слива в мастер ветку PlantUML не рендерится из за кривого мерджа ?


        1. alobzov Автор
          11.08.2022 12:46

          Нет, таких случаев не встречал