Написание документации к коду задача не самая простая и уж точно не самая приятная, но к счастью существуют инструменты которые могут существенно упростить эту процедуру. Для этих целей я использую инструмент Doxygen и именно о нем пойдет речь.
Что такое Doxygen?
Doxygen – это кроссплатформенная система документирования кода с поддержкой языков C++, C, Java, Objective-C, PHP, C# (список можно уточнить на сайте проекта).
Для создания документации достаточно просто писать комментарии в коде, придерживаясь нескольких простых правил.
Doxygen умеет анализировать исходный код проекта и создавать удобную документацию в формате HTML, Latex, RTF, XML, man, CHM.
Общие соображения
- Написание документации должно быть максимально простым, чтобы разработчики не "забывали" это делать. Отсюда вывод, что сложность форматирования комментариев должна быть минимальной.
Хорошо:
namespace A { /** Имя класса Описание класса */ class B { }; }
Плохо:
namespace A { /** * Имя класса * * Описание класса */ class B { }; }
Почему второй вариант хуже? Очевидно, из-за необходимости выравнивать комментарии на одном уровне с комментируемой сущностью, а также из-за избыточных символов *. Это может показаться надуманным, но при написании комментариев из нескольких строк проблема проявляется, а при поддержке кода и вовсе становится кошмаром. Вы можете возразить, что подобный стиль делает код "рваным", но в любом случае комментирование интерфейсов делает код менее читаемым. К счастью все современные редакторы кода позволяют легко свернуть блоки с комментариями, что позволит взглянуть на код без помех.
- Много документации – плохо, так как мало кто будет читать длинные мануалы. Из этого следует, что документированы должны быть только открытые (public) и защищенные (protected) интерфейсы. Закрытые (private) интерфейсы – часть внутренней реализации и не должны быть в руководстве.
Что нам понадобится?
Нам понадобится сделать две вещи:
- Установить Doxygen, если он еще не установлен.
- Установить Graphviz. Graphviz – это свободно распространяемый пакет утилит для визуализации данных. Нам он нужен для того, чтобы Doxygen мог показать в документации отношения наследования, графы вызовов и прочую информацию в виде наглядных изображений.
Использование Doxygen
Использовать Doxygen просто – для этого надо просто запустить программу указав ей путь к файлу с настройками. Файл с настройками представляет собой простой текстовой файл, который можно редактировать как в текстовом редакторе, так и с помощью специальных программ, например Doxygate.
В настройках описывается внешний вид документации, какие сущности и отношения между ними следует включать в нее, имя проекта, путь к анализируемым файлам и так далее.
Я предпочитаю редактировать этот файл вручную, тем более, что его достаточно настроить один раз под свои потребности и затем в новых проектах изменять одну строку – имя проекта. В конце заметки будет представлен используемый мной конфигурационный файл.
Комментирование в стиле Doxygen
Doxygen поддерживает несколько стилей комментариев. Я придерживаюсь следующего:
/**
Комментарии
*/ |
Обратите внимание, что последовательность символов /** сообщает программе, что начинается комментарий предназначенный для нее. Начиная с этого места и до завершающих символов */ следуют комментарии.
Есть несколько директив, которые помогают Doxygen составить грамотную документацию. Вот основные:
@brief | Краткое описание комментируемой сущности. Пример: @brief Функция для поиска пользователя в базе данных |
@detailed | Подробное описание сущности, то что будет показано, когда вы нажмете в документации рядом с коротким описанием ссылку "Подробней". На мой взгляд использоваться должно как можно реже, в силу того, что короткое описание должно точно отражать идею использования сущности, а использование ее не должно сопровождаться неожиданными предусловиями. Пример: @detailed Данная функция делает выборку из базы данных по имени пользователя и возвращает структуру с информацией о нем. Ожидается, что соединение с базой данных установлено и пользователь существует |
@param | Параметры передаваемые функции. Пример: @param name Имя пользователя |
@return | Возвращаемое функцией значение. Пример: @return Информация о пользователе |
@throw | Исключения выбрасываемые функцией. Пример: @throw DatabaseError Если произошла ошибка при подключении к базе данных |
Пример комментариев для класса:
/** @brief Класс для работы с базой данных @detailed Осуществляет подключение к базе при создании и закрывает соединение при уничтожении */ class Database { public: /** @brief Конструктор @param connectionString Строка подключения к базе данных @throw ConnectionError Если подключение не удалось */ explicit Database(const std::string& connectionString); /** @brief Поиск пользователя в базе данных @detailed Данная функция делает выборку из базы данных по имени пользователя и возвращает структуру с информацией о нем. Ожидается, что соединение с базой данных установлено и пользователь существует @param name Имя пользователя @return Информация о пользователе @throw DatabaseError Если произошла ошибка при подключении к базе данных @throw InvalidRequest Если пользоваделя в базе не существует */ CustomerPtr GetCustomer(const std::string& name); }; |
Этого достаточно для 99% кода, но остается вопрос комментирования на уровне проекта, а не файла. Для этого служат следующие директивы:
@mainpage | Основная страница проекта, то с чего начинается просмотр документации. Пример: @mainpage Приложение для учета пользователей |
@page | Дополнительные страницы проекта. Я рассматриваю их как логически обособленные части проекта. Пример: @page Database Database Утилиты для работы с базой данных |
@ref | Ссылки на страницы проекта, с их помощью можно организовать например ссылки с главной страницы проекта на страницы подпроектов. Пример: @ref Database Утилиты для работы с базой данных |
Для организации четкой структуры я рекомендую в каждом подпроекте создавать файл description.h в котором будет директива @page, описание для чего нужен этот подпроект и принципы работы с ним.
В свою очередь в корне проекта я также создаю файл description.h в котором немного рассказано о проекте в целом и приведены ссылки на его части:
/**
@mainpage Приложение для учета пользователей
Состоит из следующих частей:
- @ref Database Утилиты для работы с базой данных
*/ |
Чтобы привести фрагмент кода (например пример работы с классом) используется конструкция @code — @endcode:
/**
Пример использования Foo:
@code
Foo f();
f.Run();
@endcode
*/ |
Списки можно создавать с помощью символа — (минус). Пример:
/**
Список:
- Первый пункт
- Второй пункт
*/ |
Перечисления я оформляю так:
/** @brief Режимы устройства */ enum Mode { Mode_On, /**< Включено */ Mode_Off /**< Выключено */ }; |
В большинстве случаев приведенных директив достаточно, с полным списком вы можете ознакомиться в руководстве.
Ложка дегтя
Обратите внимание! Очень ВАЖНО перед объявлением пространства имен повторять его имя в комментарии Doxygen. Похоже на баг (версия 1.6.2), но без этого содержимое пространства не попадет в документацию. Пример:
/** namespace A @brief Пространство имен A */ namespace A { } |
Символ @ в конструкции namespace отсутствует!
Файл с настройками Doxygen
Как уже упоминалось, для работы Doxygen нужен файл с настройками. Программа умеет создавать файл с параметрами по умолчанию:
doxygen -g |
После этого будет сгенерирован файл с именем Doxyfile содержащий настройки по умолчанию. Вы можете отредактировать его под свои нужды, что сделать довольно просто благодаря содержащимся в нем пояснениям.
Рассмотрю некоторые из пунктов которые я изменяю:
PROJECT_NAME | Имя проекта. |
QUIET | Допустимые значения YES и NO. Я ставлю YES, для того чтобы предупреждения не терялись среди обилия информации о работе программы. |
WARN_NO_PARAMDOC | YES для вывода предупреждений о недокументированных аргументах функции. |
INPUT | Путь к анализируемому коду. Я рекомендую в корне проекта создать директорию docs содержащую Doxyfile с настройками, в таком случае значение этого параметра будет ../ |
FILE_PATTERNS | Шаблон для имени анализируемых файлов. Поскольку документироваться должны только открытые интерфейсы, то очевидно, что следует анализировать только заголовочные файлы: *.h |
RECURSIVE | Рекурсивно анализировать файлы в поддиректориях – YES. |
EXCLUDE_PATTERNS | Исключение из анализа директорий соответствующих маске. Пример: EXCLUDE_PATTERNS = */.svn/* */build/* */tests/* */sources/* |
HAVE_DOT | YES, если установлен Graphviz и требуется визуализация связей. |
Очень разумно будет один раз написать свою конфигурацию для Doxygen и в новых проектах менять лишь один параметр – PROJECT_NAME.
Мой конфигурационный файл приведен чуть ниже. Он настроен на вывод предупреждений если не были документированы какие-либо сущности.
Файлы к заметке
Мой Doxyfile.
Проект с комментариями для Doxygen.
Пример готовой документации в формате HTML сгенерированной Doxygen.
Для создания документации перейдите в директорию docs и запустите doxygen.
Спасибо! Очень полезная инфа.
Apple
25 февраля 10 20:52
Спасибо! Хоть и использовал doxygen, некоторые вещи делал криво.
Только в листингах исправьте &
Obey-Kun
26 февраля 10 2:23
Благодарю за внимательность!
Максим Тремпольцев
26 февраля 10 20:49
Спасибо, за хороший материал
Академик
4 марта 10 5:28
Есть вопрос как к специалисту, пользующемуся doxygen. При генерации документации, если в проекте наряду с классами присутствуют статические структуры, doxygen включает перечень структур в раздел описания классов. Может быть подскажете значение какого ключа в конфигурационном файле следует поменять для того чтобы перечень структур не появлялся в перечне описания классов?
Дмитрий
1 июня 10 15:10
Дякую за хорошу інформацію. Дуже допомогло
traveller
3 июля 10 19:30
Спасибо, мне было полезно это почитать!
Tim
6 августа 10 0:10
Абсолютно ублюдочный стиль комментариев. За такое надо бить ногами.
Просто какая-то рубрика «вредные советы».
Если чо,
1) @brief можно явно не писать, да и @detailed при определенной настройке тоже;
2) doxygen убирает лишние пробелы, так что никакой необходимости писать комментарий от начала строки нет, так что спокойно можно выравнивать комментарии вместе с кодом, как все нормальные люди и делают.
Kerbadun
24 января 11 4:00
Если ты попробуешь прочесть статью, то узнаешь почему выбран именно такой стиль.
Максим Тремпольцев
24 января 11 11:28
Все нормальные редакторы делают это за программиста :)
ikalnitsky
28 августа 11 12:24
Хорошая статья, спасибо! Сам только сел с ним разбираться)
zendframework
3 октября 11 15:26
Вообще, тоже всегда был против начала строки комментариев со звёздочки. Пока не пришлось пользоваться поиском одной IDE, в которой в результатах поиска выводились только те строки в которых найдено совпадение.
И вот при поиске в своём коде постоянно не мог понять, то ли закомментированный код, то ли рабочий.
В коде других разработчиков использовавших звёздочки, таких проблем не возникало.
Павел
11 сентября 13 18:36
??????????????? ?????????????? [url=http://ddyfl.swu.edu.cn/zzyggglxy/upload/monclerdown.html]?????? ????? ???[/url] ????? ???????????????????????? [url=http://www.gfrasidence.com/category-c-13.html]CELESTE STEIN[/url] ?????????????????????????????? [url=http://www.onlineshoptokyoja.com/category-c-41.html]http://www.onlineshoptokyoja.com/category-c-41.html[/url] ?? ??????????????????????????? [url=http://www.salvage3selvage.com/category-c-9.html]????? ????[/url] ??????????????????????????? ?? [url=http://www.tropicalfloralshirts.com/category-c-30_31.html]http://www.tropicalfloralshirts.com/category-c-30_31.html[/url] ?????????????????????????????????????????????? ?????????????
TydayAxonalal
10 февраля 14 1:04
> Абсолютно ублюдочный стиль комментариев. За такое надо бить ногами.
Абсолютно ублюдочный комментатор. Не можешь по-человечески без оскорблений критику донести, нех ходить по чужим сайтам.
А за статью спасибо.
Ирина
6 мая 14 15:14
https://mahnograd.com/gde-kupit-royal-canin-urinary-dlya-koshek.html
./,.
Edwinacelf
19 мая 22 10:08
пленочный теплый пол
ManuelHit
2 июня 22 10:35