Лучшие советы по документированию кода с использованием doxygen?

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

Каковы ваши любимые способы разметки кода, каковы ваши ДОЛЖНЫ ДО ДОКУМЕНТЫ И НЕ НЕТ?
Пожалуйста, предоставьте свои верхние советы, по одному на каждый ответ, чтобы облегчить голосование.

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

/**
 * @file   example_action.h
 * @Author Me ([email protected])
 * @date   September, 2008
 * @brief  Brief description of file.
 *
 * Detailed description of file.
 */

/**
 * @name    Example API Actions
 * @brief   Example actions available.
 * @ingroup example
 *
 * This API provides certain actions as an example.
 *
 * @param [in] repeat  Number of times to do nothing.
 *
 * @retval TRUE   Successfully did nothing.
 * @retval FALSE  Oops, did something.
 *
 * Example Usage:
 * @code
 *    example_nada(3); // Do nothing 3 times.
 * @endcode
 */
boolean example(int repeat);

Ответ 1

Вам не нужно и не следует записывать имя файла в директиве @file, doxygen автоматически считывает имя файла. Проблема с записью имени файла заключается в том, что при переименовании файла вам также придется изменить директиву @file.

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

Вам также не нужно писать @brief, если вы используете следующий синтаксис Doxygen и включаете JAVADOC_AUTOBRIEF в конфигурации doxygen:

/*! Short Description on the first line

    Detailed description...
    ...
*/
void foo(void) {}

Директива @name для функций также на 100% избыточна в большинстве случаев и совершенно бесполезна. Это приводит только к ошибкам, когда кто-то изменяет имя функции, а не doxygen @name.

Ответ 2

Напишите описательную домашнюю страницу, используя @mainpage (в отдельном заголовочном файле только для этой цели). Рассмотрим, как показано в моем примере, как руководство для ваших основных классов/функций и модулей.

Другой пример

В то время как я получал вышеописанный основной контент oxygen oxygen обратно в онлайн, вот пример из текущей работы клиента с использованием формата Markdown. Используя Markdown, вы можете обратиться к главной странице в методе уценки (в настройках Doxygen), что отлично подходит для типичного файла readme.md, включенного в проекты с открытым исходным кодом.

Lingopal
========
Developer Documentation started when Andy Dent took over support in May 2014. 

There are a number of pages in Markdown format which explain key aspects:

- @ref doc/LingopalBuilding.md
- @ref doc/LingopalSigning.md
- @ref doc/LingopalDatabases.md
- @ref doc/LingopalExternals.md

See the <a href="pages.html">Related Pages list for more.</a>

-------------

_Note_

These pages, whilst readable by themselves, are designed to be run through the [Doxygen](http://www.doxygen.com) code documentation engine which builds an entire local cross-referenced set of docs. It uses a minor [extension of Markdown formatting.](http://www.stack.nl/~dimitri/doxygen/manual/markdown.html)

The settings to generate the documentation are `Lingopal.doxy` and `LingopalDocOnly.doxy`. The latter is used for quick re-generation of just these additional pages.

Ответ 3

Используйте Группы, чтобы упорядочить код в модулях.

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

Вы также можете использовать группы в соответствии с иерархией папок в среде IDE, как показано в моем примере RB2Doxy output.

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

Ответ 4

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

  • \todo { paragraph describing what is to be done } Полезно отслеживать todos, страница будет создана в окончательной документации, содержащей ваш список todo.
  • \c <word> Отображает аргумент с использованием шрифта пишущей машинки. Используйте это для обозначения слова кода. Я бы использовал его до "TRUE" и "FALSE" в вашем примере.
  • \a , \warning , \see: см. http://www.stack.nl/~dimitri/doxygen/commands.html#cmdc для описания

Ответ 5

Хорошая "лучшая практика" (хотя и не всегда достижимая) состоит в том, чтобы предоставить короткие рабочие примеры для каждого API и вытащить их в помощь с помощью \includelineno (или\include без номеров строк). Это могут быть модульные тесты, если они написаны, чтобы пользователи могли их понять (т.е. Не подключались к более крупному тестовому жгуту). Как хороший побочный эффект, изменения API будут разбивать образцы, поэтому они должны быть обновлены.

Вы можете описать API в словах, но нет ничего похожего на просмотр фактического кода, чтобы понять, как его использовать.

Ответ 6

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

Ответ 7

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

В противном случае он выглядит как JavaDoc. Одна из приятных вещей о Doxygen заключается в том, насколько хороша работа, без использования такой сильной разметки. Вам не нужно использовать @name и с настройкой JAVADOC_AUTOBRIEF, вы можете пропустить @brief - просто убедитесь, что первая строка комментария является разумным кратким описанием.

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

Ответ 8

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

/** @bug The text explaining the bug */

Когда вы запускаете doxygen, вы получаете отдельный список ошибок вместе с такими списками, как Todo List

Ответ 9

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

Например, если у вас есть большое решение MSVC с двадцатью проектами в нем, вы можете сделать каталог своим собственным Doxygen run, а затем использовать теги файлы для склеивания вывода так же, как компоновщик склеивается вместе .libs to сделать исполняемый файл.

Вы даже можете использовать метасвязь ссылок более буквально и сделать каждый конфигурационный файл Doxy соответствующим файлу .vcproj, чтобы каждый проект (например,.lib или .dll) получал свой собственный вывод Doxy.

Ответ 10

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

/**
 * @defgroup example Top Level Example Group
 * @brief    The Example module.
 *
 * @{
 */

/**
 * @defgroup example_child1 First Child of Example
 * @brief    1st of 2 example children.
 */

/**
 * @defgroup example_child2 Second Child of Example
 * @brief    2nd of 2 example children.
 */

// @}

Простое определение группы внутри {} другой группы делает ее дочерней группой. Затем в файлах кода и заголовков можно просто помечать как часть любой группы, в которой они находятся, и все это работает только в готовой документации. Это значительно упрощает рефакторинг документации, чтобы он соответствовал рефактору.

Ответ 11

Я использую крюк post-commit subversion, чтобы вытащить измененные каталоги, записать их в файл, а затем каждую ночь я автоматически перегенерирую doxygen html на нашем веб-сервере, чтобы мы всегда имели обновленный docco.

В каждом проекте, который я хочу документировать, есть небольшой файл project.doxy, который содержит параметры для каждого проекта и включает в себя основные настройки doxygen - например:

PROJECT_NAME           = "AlertServer"
PROJECT_NUMBER         = 8.1.2
INPUT                  = "C:/Dev/src/8.1.2/Common/AlertServer"
HTML_OUTPUT            = "AlertServer"
@INCLUDE = "c:\dev\CommonConfig.doxy"

Для Windows SVN-сервера используйте hook:

@echo off
for /F "eol=¬ delims=¬" %%A in ('svnlook dirs-changed %1 -r %2') do echo %%A >> c:\svn_exports\export.txt

а затем выполните эту ночь:

@echo off

rem ---------------
rem remove duplicates.
type nul> %TEMP%.\TEMP.txt

for /F "eol=¬ delims=¬" %%a in (c:\svn_exports\export.txt) do (
 findstr /L /C:"%%a" < %TEMP%.\TEMP.txt > nul
 if errorlevel=1 echo %%a>> %TEMP%.\TEMP.txt
)

copy /y %TEMP%.\TEMP.txt export_uniq.cmd >nul
if exist %TEMP%.\TEMP.txt del %TEMP%.\TEMP.txt


rem ---------------
rem fetch all the recently changed directories into the svn_exports directory

for /F "eol=¬ delims=¬" %%A in (c:\svn_exports\export_uniq.cmd) do (
  svn export "file:///d:/repos/MyRepo/%%A" "c:/svn_exports/%%A"  --force 
)


rem ---------------
rem search through all dirs for any config files, if found run doxygen

for /R c:\svn_exports %%i in (*.doxy) do c:\tools\doxygen\bin\doxygen.exe "%i"


rem ---------------
rem now remove the directories to be generated.
del /F c:\svn_exports

это удаляет повторяющиеся записи, находит все проекты, имеющие файл проекта .doxy, и запускает doxygen на них. Voila: полностью документированный, всегда обновляемый код на веб-сервере.

Ответ 12

Использует множество ссылок. Это можно сделать, используя также ссылки (\ see или @see, если хотите), и убедитесь, что вы используете какие-либо ссылки на другие имена классов в документации по их правильному имени класса. Например, если вы относитесь к классу FUZZYObject как к "объекту", то сразу же напишите ему имя класса (например, "обманите объекты (FUZZYObject)" ).

Ответ 13

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

Ответ 14

Используйте \example столько, сколько сможете. Он автоматически связывает элементы API с примером кода.

Ответ 15

Не беспокойтесь о @author или @date (@date упоминается в другом сообщении). Они оба обрабатываются системой контроля версий.

Ответ 16

Всегда включайте описание с вашими классами. Попробуйте сказать, как используется класс или почему он используется, а не только то, что он (как правило, просто отражает имя в любом случае).

Ответ 17

Группируйте свои функции и поля, если имеет смысл сделать это с помощью \defgroup. Это очень полезно, даже если вы не говорите много.

Ответ 18

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

WARNINGS               = YES
WARN_IF_UNDOCUMENTED   = YES
WARN_IF_DOC_ERROR      = YES

Как часть процесса сборки doxygen, сохраните предупреждения в файле и попытайтесь получить и удерживайте количество предупреждений как можно ниже (0, если это разумно). Если вы это сделаете, каждому публичному и защищенному члену класса потребуется по крайней мере @brief, @param для каждого аргумента функции и @return. Это достаточно хорошо, чтобы описать большинство API и не слишком много, чтобы обременять другие живые кодовые базы.

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

Например, в нашем проекте все другие кодеры, вероятно, будут касаться, должны быть задокументированы. Включение предупреждений позволяет увидеть, насколько мы близки к этой цели. Мы также пытаемся использовать @internal для описания того, что/почему мы делаем то, что делаем с некоторыми из наших частных членов.

Ответ 19

Если вы обнаружите, что директива конфигурации INLINE_SOURCES содержит слишком много кода в документации, вы можете вручную указать некоторые части кода, используя \snippet.

  /**
   * Requirment XYZ is implemented by the following code.
   * 
   * \snippet file.c CODE_LABEL
   */
  int D() 
  {
     //[CODE_LABEL]
     if( A )
     {
        B= C();
     }
     //[CODE_LABEL]
  }

note: snippet получает свои файлы из EXAMPLE_PATH, а не там, где находится исходный путь. Вам нужно будет поместить тот же список файлов и путей из INPUT директивы EXAMPLE_PATH.

Ответ 20

Для больших проектов, которые производят 5 + мин для создания, я сочла полезным с легкостью генерировать doxygen для одного файла и просматривать его в веб-браузере.

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

Этот script принимает один файл, а проект doxy config и запускает doxygen, я установил его для запуска из моей IDE.

#!/usr/bin/env python3
"""
This script takes 2-3 args: [--browse] <Doxyfile> <sourcefile>

  --browse will open the resulting docs in a web browser.
"""
import sys
import os
import subprocess
import tempfile

doxyfile, sourcefile = sys.argv[-2:]

tempfile = tempfile.NamedTemporaryFile(mode='w+b')
doxyfile_tmp = tempfile.name
tempfile.write(open(doxyfile, "r+b").read())
tempfile.write(b'\n\n')
tempfile.write(b'INPUT=' + os.fsencode(sourcefile) + b'\n')
tempfile.flush()

subprocess.call(("doxygen", doxyfile_tmp))
del tempfile

# Maybe handy, but also annoying as default.
if "--browse" in sys.argv:
    import webbrowser
    webbrowser.open("html/files.html")