使用 doxygen 记录代码的最佳技巧?

And*_*son 308 c c++ documentation doxygen

我的团队开始使用 doxygen 记录我们的 C 代码,特别关注我们的公共 API 标头。doxygen 中似乎有很多灵活性和不同的特殊命令,这很棒,但如果没有反复试验,就不清楚什么是好事,什么是坏事。

您最喜欢的标记代码的方式是什么?您必须做什么和不应该做什么?
请提供您的重要提示,每个答案一个,以方便投票。

我希望定义 API 文档的整个方法,包括提供一个模板来让团队的其他成员开始。到目前为止我有这样的事情:

/**
 * @file   example_action.h
 * @Author Me (me@example.com)
 * @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);
Run Code Online (Sandbox Code Playgroud)

Éti*_*nne 92

您不需要也不应该在指令中写入文件名@file,doxygen 会自动读取文件名。写入文件名的问题是,当您重命名文件时,您@file也必须更改指令。

大多数时候提供@author信息@date也是无用的,因为源代码控制系统比手动编辑文件要好得多。

@brief如果您使用以下 Doxygen 语法并在 doxygen 的配置中启用 JAVADOC_AUTOBRIEF,则也不必编写:

/*! Short Description on the first line

    Detailed description...
    ...
*/
void foo(void) {}
Run Code Online (Sandbox Code Playgroud)

函数指令@name在大多数情况下也是 100% 冗余并且完全无用。仅当有人修改函数名称而不是 doxygen 时,它才会带来错误@name

  • \file 是必要的,但不是文件名,这就是我所说的;) (7认同)
  • doxygen 文档说“让我们重复一遍,因为它经常被忽视:要记录全局对象(函数、typedef、枚举、宏等),您必须记录定义它们的文件。换句话说,必须至少有是此文件中的 /*! \file */ 或 /** @file */ 行。” 似乎表明 \file 可能是必要的。然而,这可能只是被误解。值得澄清。 (4认同)
  • 请艾蒂安在您的答案中添加一个使用“\file”而不带文件名的文件开头的示例。我认为您需要设置“JAVADOC_AUTOBRIEF = YES”以避免使用“@brief”。你可否确认?您对提供文件摘要有什么建议?干杯 (2认同)

And*_*ent 60

使用 @mainpage编写描述性主页(为此目的,在单独的头文件中)。正如我的示例所示,请考虑将其作为主要类/函数和模块的指南。

另一个样本

当我重新在线获取上面链接的 oofile doxygen 主要内容时,这里有一个使用 Markdown 格式的当前客户工作的示例。使用 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.
Run Code Online (Sandbox Code Playgroud)

  • 链接失效了,看不懂你的意思。我建议要么将答案扩展为独立的,要么修复死链接。 (7认同)

And*_*ent 54

使用将代码组织到模块中。

请记住,您可以将几乎所有内容放入多个组中,以便它们可用于提供语义标记,如 Stack Overflow 中的标记。例如,您可以将事物标记为特定于给定平台。

您还可以使用组来匹配IDE 中的文件夹层次结构,如我的 RB2Doxy 示例输出所示。

嵌套时组工作得很好 - 我有一个OOFILE 源的大例子。

  • 损坏的链接... (6认同)
  • 我希望我能给这个问题和其他涉及团体多于一票的答案。Doxygen 无法告诉您代码中未包含的任何内容。但是,它可以以不同的顺序呈现信息或过滤信息。组是您可以在注释中添加的最有用的东西之一,因为它可以让 doxygen 为您提供通过在编辑器中打开源文件无法获得的东西 - 代码的显着重组视图。 (2认同)

kra*_*mer 49

我在代码中使用的一些命令:

  • \todo { paragraph describing what is to be done }对于跟踪待办事项很有用,将在包含您的待办事项列表的最终文档中创建一个页面。
  • \c <word>使用打字机字体显示参数。使用它来引用代码单词。在您的示例中,我会在“TRUE”和“FALSE”之前使用它。
  • \a , \warning , \see:参见http://www.stack.nl/~dimitri/doxygen/commands.html#cmdc了解说明

  • 谢谢,里面有一些有用的东西。\c 不适用于问题中的 TRUE/FALSE,因为它使用 retval,而不是 return。所有 retval 都会创建一个表,其中命令后的第一个单词是返回值,因此使用 \c 只会为您提供一个“\c”表。 (2认同)

小智 36

一个好的“最佳实践”(尽管并不总是可以实现)是为每个 API 提供简短的、有效的示例,并使用 \includelineno (或 \include 表示没有行号)将它们拉入帮助中。这些可以是单元测试,如果它们被编写为用户可以理解它们(即,不连接到更大的测试工具)。一个很好的副作用是,对 API 的更改会破坏示例,因此它们必须保持最新。

您可以用文字描述 API,但没有什么比查看实际代码更能了解如何使用它了。


And*_*ent 28

当我发现自己在更高分辨率的屏幕上编辑代码时,我在 Doxygen 命令上从使用反斜杠改为使用 @ 前缀。不那么吵闹的反斜杠现在发现自己太难辨认 Doxygen 命令了。


And*_*ent 27

如果您确定您的团队将遵循这样的重量级模板,那么可以如图所示使用它。

否则,它看起来像 JavaDoc。Doxygen 的优点之一是它无需使用如此强大的标记即可完成出色的工作。您不需要使用@name,并且使用JAVADOC_AUTOBRIEF设置您可以跳过@brief - 只需确保注释的第一行是合理的简短描述即可。

我更喜欢描述性名称,而不是强制执行文档并鼓励人们仅在评论增加重要价值时才添加评论。这样,有价值的评论就不会被所有噪音淹没。

  • 如果您尝试遵循模板,您将不可避免地在实际代码中收到很多注释,例如“这是类的简要描述”,因为人们忘记返回并在注释中添加内容。没有什么比这些类型的评论更好的了。 (7认同)
  • 如果您将文档设置为可选,您就有机会审核是否添加了它,特别是使用 Doxygen 快速检查更改设置以警告未记录的类。我还建议使用 Doxygen 的 XML 输出,这样您就可以解析常见平淡字符串的注释。 (4认同)

eaa*_*n01 25

如果代码中存在错误或发现错误,您也可以在代码中进行标记,如下所示:

/** @bug The text explaining the bug */
Run Code Online (Sandbox Code Playgroud)

然后,当您运行 doxygen 时,您会得到一个单独的 Bug 列表以及诸如待办事项列表之类的列表


Cra*_*rks 15

如果您有一个非常非常大的项目(大到 Doxygen 运行需要一个多小时),您可以将其分割成多个模块,然后Doxygen 使用标记文件将这些模块链接在一起

例如,如果您有一个包含 20 个项目的大型 MSVC 解决方案,您可以将目录设置为其自己的 Doxygen 运行,然后使用标记文件将输出粘合在一起,就像链接器将 .libs 粘合在一起以生成可执行文件一样。

您甚至可以更字面地理解链接隐喻,使每个 Doxy 配置文件对应于一个 .vcproj 文件,以便每个项目(例如 .lib 或 .dll)获得其自己的 Doxy 输出。


gbj*_*anb 15

我使用 subversion post-commit 挂钩来提取已更改的目录,将它们写入文件,然后每天晚上我都会在我们的网络服务器上自动重新生成 doxygen html,以便我们始终拥有最新的 docco。

\n\n

我想要记录的每个项目都有一个小project.doxy 文件,其中包含每个项目的设置以及主doxygen 设置的包含内容 - 例如:

\n\n
PROJECT_NAME           = "AlertServer"\nPROJECT_NUMBER         = 8.1.2\nINPUT                  = "C:/Dev/src/8.1.2/Common/AlertServer"\nHTML_OUTPUT            = "AlertServer"\n@INCLUDE = "c:\\dev\\CommonConfig.doxy"\n
Run Code Online (Sandbox Code Playgroud)\n\n

对于 Windows SVN 服务器,使用钩子:

\n\n
@echo off\nfor /F "eol=\xc2\xac delims=\xc2\xac" %%A in (\'svnlook dirs-changed %1 -r %2\') do echo %%A >> c:\\svn_exports\\export.txt\n
Run Code Online (Sandbox Code Playgroud)\n\n

然后每晚运行:

\n\n
@echo off\n\nrem ---------------\nrem remove duplicates.\ntype nul> %TEMP%.\\TEMP.txt\n\nfor /F "eol=\xc2\xac delims=\xc2\xac" %%a in (c:\\svn_exports\\export.txt) do (\n findstr /L /C:"%%a" < %TEMP%.\\TEMP.txt > nul\n if errorlevel=1 echo %%a>> %TEMP%.\\TEMP.txt\n)\n\ncopy /y %TEMP%.\\TEMP.txt export_uniq.cmd >nul\nif exist %TEMP%.\\TEMP.txt del %TEMP%.\\TEMP.txt\n\n\nrem ---------------\nrem fetch all the recently changed directories into the svn_exports directory\n\nfor /F "eol=\xc2\xac delims=\xc2\xac" %%A in (c:\\svn_exports\\export_uniq.cmd) do (\n  svn export "file:///d:/repos/MyRepo/%%A" "c:/svn_exports/%%A"  --force \n)\n\n\nrem ---------------\nrem search through all dirs for any config files, if found run doxygen\n\nfor /R c:\\svn_exports %%i in (*.doxy) do c:\\tools\\doxygen\\bin\\doxygen.exe "%i"\n\n\nrem ---------------\nrem now remove the directories to be generated.\ndel /F c:\\svn_exports\n
Run Code Online (Sandbox Code Playgroud)\n\n

这会删除重复的条目,找到所有具有 .doxy 项目文件的项目,并在它们上运行 doxygen。瞧:网络服务器上有完整的文档记录,始终是最新的代码。

\n


And*_*son 13

对于复杂的项目,拥有一个单独的模块管理文件可能很有用,该文件控制组和子组。整个层次结构可以位于一个位置,然后每个文件可以简单地填充到子组中。例如:

/**
 * @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.
 */

// @}
Run Code Online (Sandbox Code Playgroud)

只需将一个组的定义包含在另一个组的 { } 中即可使其成为该组的子组。然后,在代码和头文件中,函数可以被标记为它们所在组的一部分,并且这一切都可以在完成的文档中工作。它使得重构文档以匹配重构代码变得更加容易。


cdi*_*ins 10

使用很多很多的链接。这可以使用“另请参阅”链接(\see 或 @see,如果您愿意)来完成,并确保您通过正确的类名使用文档中其他类名的任何引用。例如,如果您将 FUZZYObject 类称为“对象”,则在其后面立即写上该类的名称(例如“frazzle the objects (FUZZYObject)”)。


Joh*_*gle 9

自动构建和发布您的文档。作为自动构建文档的一部分,请注意警告,很容易写出结构不良的 doxygen 注释。


cdi*_*ins 8

\example尽可能多地使用。它将 API 元素自动链接到示例代码。


Jim*_*shr 8

不要理会@author 或@date(@date 在另一篇文章中提到过)。这些都由修订控制系统处理。


cdi*_*ins 7

始终在您的课程中包含描述。尝试说出一个类是如何使用的,或者为什么使用它,而不仅仅是它是什么(通常只是反映了名称)。