Как стать автором
Обновить
26.99
СВД ВС
Надежность. Безопасность. Реальное время

Подход к ведению документации на ОС: наш опыт

Время на прочтение8 мин
Количество просмотров4K

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

Предыстория

При работе над документацией к ЗОСРВ «Нейтрино» и другим нашим продуктам требовалось спроектировать такое решение, которое было бы достаточно гибким для того, чтобы документировать разные сущности (драйверы, библиотеки, утилиты, функции API) и при этом сохраняло максимальную лаконичность и простоту для разработчиков. Код ЗОСРВ «Нейтрино» преимущественно написан на языке С, поэтому нам был необходим парсер исходного кода. Требовалось размещать разметку документации не только в файлах исходного кода, но и в standalone-файлах. Вдобавок, у нас имелся багаж из некоторого количества документации с разметкой Doxygen, которую нельзя было потерять, и еще лучше – не переделывать. Поэтому за основу был взят старый добрый Doxygen, поскольку он максимально прост и нетребователен, и при этом предоставляет достаточную функциональность для нашего видения того, как должна в итоге выглядеть на экране типовая страничка, как она должна быть оформлена. Были опробованы еще несколько решений, например, Sphinx и AsciiDoc. Первый не умеет парсить код на С, однако в нём есть возможность использовать в конечном итоге тот же Doxygen для парсинга, а со вторым просто не сложилось.

Исторически, наша справка использует Eclipse в качестве средства доставки контента до читателя. Данный сервер не является обязательным фактором, однако пока имеется внутренний набор legacy-документов, отказываться от которых мы не спешим. Сервер заворачивает разделы документации в JAR-архивы. Особенности формирования JAR-архивов заключаются в наличии специальных служебных файлов, в частности, файла с содержанием (иерархии). Здесь уже стандартные механизмы Doxygen трудноприменимы, и требовались серьёзные доработки, выродившиеся в отдельную систему автоматической генерации справочных материалов, которая использует Doxygen не более чем как парсер и генератор отдельных конечных страниц выходного формата.

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

Итак, для поддержания документации на проект в актуальном состоянии со стороны команды необходимо и достаточно проводить качественный code-review, особенно в части публичных интерфейсов. Поскольку code-review и так является обязательным, алгоритм работы как отдельного разработчика, так и команды, изменился не сильно.

Рабочий процесс

Чтобы сопровождать наши программные продукты, система генерации справки должна была решать следующие поставленные задачи:

Для реализации поставленных задач было решено использовать связку из нескольких технологических решений.

Из репозиториев проекта берутся необходимые файлы, которые ведутся разработчиками и которые содержат в себе специальную разметку – разметку в синтаксисе Doxygen с расширениями уже нашей разработки. Содержимое этих файлов будет конвертироваться в выходной формат (это может быть HTML, либо PDF) при помощи нашей системы генерации справки на основе Doxygen. Если говорить исключительно о генерации страниц документации, то упрощённо она представляет собой препроцессирование файлов, вызов Doxygen, затем постпроцессирование уже выходных файлов. Запуск такой конвертации, сборка ее результатов и развертывание получившегося архива с готовой справкой на серверах выполняется при помощи системы непрерывной интеграции CI/CD. При этом у разработчиков имеется простой веб-интерфейс в системе CI/CD, что позволяет им не вникать в механизмы генерации справки.

Некоторые преимущества, которые мы получили

Контроль покрытия документацией

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

Получение сведений о текущем состоянии API (количество сущностей) выполняется в динамике с использованием LLVM/clang для анализа исходников библиотек.

Динамическое связывание страниц

Давайте рассмотрим некоторые расширения стандартного синтаксиса Doxygen. На изображении ниже можно увидеть локальное внутристраничное оглавление, и первый раздел из этого локального оглавления (“Блочные устройства”). Этот раздел содержит в себе две таблицы. Обратите внимание, что функции находятся в первой таблице, а пользовательские типы - во второй. Такое разбиение выполняется автоматически как раз при помощи механизма динамического связывания. Помимо этого, описания сущностей, которые вы видите в правом столбце таблицы подхватываются автоматически из тех страниц, на которые ведет соответствующая ссылка в левом столбце. При изменении описания на странице куда ведет ссылка, новое описание мы увидим и здесь.

Этот же механизм динамического связывания используется и для ведения журнала изменений продукта от версии к версии. На изображении ниже по левую сторону можно увидеть журнал изменений для ЗОСРВ «Нейтрино» редакции 2021 относительно редакции 2020. Внутри этого журнала есть разбиение по компонентам, например, драйверам и библиотекам. Справа же располагается конкретный список изменений по каждому компоненту внутри группы компонентов “Сервисы и менеджеры”. Гораздо удобнее просматривать новости релиза в одном месте, а не собирать их по всей справке. Журнал изменений фиксирует добавление, изменение или удаление компонентов, или отдельных их составляющих (опций у утилит, параметров у функций), а также любые другие изменений, которые внесли разработчики вручную, чтобы особенно подчеркнуть и обратить внимание пользователей.

Процесс формирования Release Notes состоит из нескольких шагов. Во-первых, во многих репозиториях с исходниками размещается шаблон будущего Release Notes, который детализирует локальные изменения по-релизно и по-компонентно (включая внутренние заметки, которые будут вырезаны при публикации Release Notes). Данные шаблоны сливаются в один большой шаблон, с сохранением релизно-компонентного ранжирования. После этого со всех страниц документации собираются сведения об указанных разработчиками тэгах @since и @deprecated и добавляются в общий шаблон. Это позволяет избегать необходимости дублировать информацию на странице какой-нибудь утилиты и в Release Notes, при изменении её опций и т. п.

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

Генерация справки по зафиксированным версиям продукта

Ниже приведен скриншот веб-интерфейса системы непрерывной интеграции, которая позволяет разработчику выбрать под какую версию операционной системы генерировать справку, ниже можно выбрать - хотим ли мы получить на выходе документацию для внутреннего использования или же публичную. И ниже можно выбрать, на какой сервер мы можем разместить архив с получившейся документацией - на тестовый, на внутренний или на внешний официальный. При публикации на внешние сервера добавлены дополнительные проверки утечки внутренних сведений (@internal). Интерфейс достаточно простой и не нагружает разработчика подробностями генерации справки.

Блоки информации для внутреннего использования

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

Как мы документируем программные продукты

Рассмотрим более детально процесс документирования программного продукта при помощи инструмента генерации справки.

Документирование в файлах исходного кода

Предположим, что мы написали функцию сложения двух чисел с именем add(). Давайте рассмотрим процесс ее документирования. Находим в заголовочном файле прототип функции, и размечаем многострочный комментарий.

Для начала зададим имя выходного файла, которое нам требуется, и заголовок, который мы хотим видеть на странице и предваряем эту информацию тегом @page. Теперь добавим краткое описание функции при помощи тега @brief, буквально в одном предложении. Далее, выделим важную информацию с помощью блока подсказки @hint и отметим, что эта функция появилась в проекте, начиная с версии 2.0.

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

Итак, в конце мы добавляем тематическую ссылку и связываем эту страницу с базовой страницей. Поскольку у нас это математическая функция (сложение), то логично поместить ее в страницу с API нашего проекта в раздел "Математические функции".

Готово, мы задокументировали нашу функцию!

Документирование отдельно от исходного кода

Только что мы рассмотрели один из вариантов написания разметки справки - в файле исходного кода проекта. Допустим, тот комментарий, что мы только что написали, находится вместе с функцией add() в файле header.h. При применении системы автоматической генерации у нас на выходе получится страница add.html, которая будет содержать информацию о функции add(). На каждую сущность в заголовочном файле (другие функции, классы, типы), для которой требуется страница справки, необходимо разметить аналогичный собственный комментарий.

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

Что дальше?

Однако, получения единичных изолированных справочных страниц недостаточно. Необходимо иметь дерево, по которому можно перемещаться по разным страницам. Так, функцию add() можно поместить в страницу API, а утилиту utility в страницу со списком утилит. Подразумевается, что одна страница является главной по отношению к нескольким другим, она содержит некую общую информацию и содержит ссылки на страницы с более узкоспециализированной информацией. В свою очередь, страницы с API и с утилитами можно объединить в какую-то основную, головную страницу для всего проекта. Таким образом можно получить дерево, по которому можно перемещаться внутри справки. Динамическое связывание выполняет эту задачу.

Как ознакомиться с результатами

Продемонстрировать результаты работы системы генерации в рамках статьи нереально, поскольку страниц очень большое количество, поэтому предлагаем вам ознакомиться с результатами более детально, перейдя на сайт нашей организации - ООО "СВД ВС". Также можно перейти сюда с домашней страницы сайта kpda.ru, перейдя в раздел "Помощь -> Документация", располагающийся наверху.

Одним из перспективных направлений развития нашей системы является генерация документации в формате PDF. То есть аггрегирование отдельных статей, страниц в один большой структурированный документ с титульным листом и содержанием, который можно листать как книгу. Наличие такого документа избавляет нас от необходимости поддержки множества серверов, плюс к этому документ можно распечатать и поставлять заказчикам. Генерация PDF (через LaTeX) интересна как с точки зрения фиксирования информации по определенной версии продукта, так и с точки зрения стандартизации и автоматизации оформления справочных материалов.

В данный момент PDF-документ по ЗОСРВ «Нейтрино» не размещён на нашем официальном сайте, однако, он будет публиковаться, начиная со следующего релиза ЗОСРВ «Нейтрино» в порядке эксперимента, так как там еще есть чем позаниматься в части структуры и стилей. Документы в формате PDF уже в полной мере поставляются заказчикам по некоторым программным продуктам, например, по ПК ЦКИ для ЗОСРВ «Нейтрино».

Спасибо за уделённое время и внимание!

Теги:
Хабы:
Всего голосов 4: ↑4 и ↓0+4
Комментарии4

Публикации

Информация

Сайт
www.kpda.ru
Дата регистрации
Дата основания
Численность
51–100 человек
Местоположение
Россия
Представитель
Игорь Дерябин