Всем, кто создавал библиотеки или сервисы с публичным API, хорошо знакома боль, когда документация отстает от изменений в коде и рутинный процесс обновления документации на сайте становится настолько неинтересным, что про него просто забывают. Можно ли как-то автоматизировать генерацию технической документации (а в идеале, еще и создание руководства пользователя с возможностью навигации и красивыми картинками)? В этой статье мы обсудим возможности Dokka (Kotlin-инструмента для создания документации) и подходы к генерации артефактов документации с использованием плагинов Gradle.

Сначала подойдем к решению простой задачи — обновление документации публичных методов библиотеки. По традиции, идущей еще из Java, в исходный текст могут добавляться специальные виды комментариев, которые получили название Doc Comment и записываются с префиксом /** (важно использовать две звездочки) и суффиксом */. Doc Comment может добавляться как к файлу в целом, так и к классу, методу или свойству класса, описывает функциональность данного фрагмента кода и также может декларировать набор метаданных (например, @author для определения автора), а также описывать параметры и ожидаемые результаты метода (@param для указания парметра метода, @return для описания результата, @throws для уточнения возможных выбрасываемых исключений), а также связывать фрагменты между собой (@see). Похожий подход к блокам документации используется сейчас во многих языках программирования и есть даже кроссязыковые инструменты, анализирующие исходные тексты и создающие HTML или PDF-представление документации к библиотеке (например, Doxygen). Также для каждой технологии есть свой инструмент для создания документации на основе комментариев (javadoc в Java, PHPDocumentor для PHP). Для приложений на Kotlin рекомендуется использовать инструмент Dokka, который также поддерживает как комментарии JavaDoc, новый формат комментариев KDoc.

Основной способ интеграции генерации документации для проектов Kotlin — встраивание Dokka в Gradle, для этого необходимо добавить плагин, который добавит дополнительные задачи gradle (dokkaHtml, dokkaGfm, dokkaJavadoc, dokkaJekill):

plugins {
    id("org.jetbrains.dokka") version "1.7.10"
}

Создадим простую реализация класса Api:

/**
 * My Api Implementation
 *
 * @author Dmitrii Zolotov
 */
class MyApi {

    /**
     * @return API version
     */
    fun getVersion() = "v1.0"
}

И запустим сборку документации в формате html:

./gradlew dokkaHtml

Документация будет сгенерирована в build/dokka/html и может быть добавлена как артефакт сборки в CI. Если мы хотим получить вариант документации в PDF, одним из решений может быть создание Markdown документации (dokkaGfm или dokkaJekill) и дальнейшая конвертация в PDF с помощью gradle-плагинов, этот вариант мы рассмотрим позднее. Также можно создать документации в стилизации, привычной для java-разработчиков (задача dokkaJavadoc).

Функциональность Dokka может быть расширена с использование плагинов, например, можно подключить дополнение для включения в документацию mermaid-диаграмм (например, графов):

dependencies {
  dokkaPlugin("com.glureau:html-mermaid-dokka-plugin:0.3.2")
}

И добавим в документацию описание графа:

    /**
     * ```mermaid
     * graph LR
     *   A --> B
     *   B --> C
     *   C --> A
     * ```
     */
    fun buildGraph() {
    }

После выполнения dokka* задачи будет добавлено изображение графа, созданное mermaid. При необходимости использования других типов содержания можно разработать свой плагин, как расширение класса DokkaPlugin, который представляет из себя сочетание парсера и препроцессора HTML, которые могут подключать ресурсы в HTML (js, css) и создавать HTML-фрагмент на основе обнаруженного фрагмента в doc comment. Пример реализации можно посмотреть здесь.

Альтернативно можно использовать консольный вариант:

java -jar dokka-cli.jar -sourceset -src src/

Любой Javadoc-комментарий также является комментарием KDoc, но при этом в KDoc можно добавлять возможность помечать символы ссылками (в квадратных скобках), указывать название параметра непосредственно в @param[name], а также описывать расширенные языковые возможности Kotlin (например, @receiver для уточнения класс-получателя при описании функции-расширения).

Такой подход к описанию может быть полезен при описании программного интерфейса библиотек, но как быть с API? Здесь могут использоваться расширения, например Ktor OpenAPI Generator для Ktor, которые создают файл в формате OpenAPI 3.0 (json). Для преобразования документации в Markdown можно использовать внешний open source инструмент widdershins или плагин org.openapitools:openapi-generator-gradle-plugin:6.0.

Markdown-документы (которые могут также включать в себя дополнительные страницы для пользователя) могут быть преобразованы в PDF с помощью плагина io.smartio.gradle.plugin:

plugin {
  id "it.smartio.gradle.markdown" version "0.1.19"
}

Также можно выполнить преобразование документов Markdown в HTML:

plugin {
  id 'org.kordamp.gradle.markdown' version '2.2.0'
}

Таким образом, полученные артефакты документации из кода (предпочтительно GFM), из реализации сервера (Ktor -> OpenAPI -> Markdown) и инструкция пользователя могут быть преобразованы в единый формат (Markdown или, как возможный вариант, AsciiDoc) и в дальнейшем сконвертированы с помощью плагинов Gradle в HTML или PDF и сохранены как артефакты сборки для дальнейшей автоматической загрузки внутри CI/CD на соответствующий сервер.

Руководство пользователя и прочая сопроводительная документация тоже может располагаться в коде (например, в формате Markdown) и на нее могут быть указаны ссылки в комментариях к соответствующим методам и классам через аннотацию @see , чтобы сохранить связь функциональности в реализации и в руководстве по использованию, а также иметь возможность быстрого перехода к текстовому описанию, что может помочь поддерживать документацию в актуальном состоянии.


Скоро состоится открытое занятие «Основы классов и объектов». На этом занятии мы посмотрим на принципы проектирования классов и их реализации в Kotlin. Поймем, как объектно-ориентированное программирование работает изнутри, создадим свои структуры и посмотрим на возможности языка Kotlin. Спроектируем объектную модель данных. Записывайтесь по ссылке.

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