使用doxygen编写代码的最佳技巧?

我的团队开始使用doxygen来logging我们的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); 

您不需要也不应该在@file指令中写入文件的名称,doxygen会自动读取文件的名称。 编写文件的名称的问题是,当你重命名文件,你将不得不改变@file指令。

提供@author@date信息在大多数情况下也是无用的,因为源代码pipe理系统比手动编辑文件要好得多。

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

 /*! Short Description on the first line Detailed description... ... */ void foo(void) {} 

函数的@name指令在大多数情况下也是100%冗余的,完全没有用处。 它只会在有人修改函数的名字而不是doxygen @name时带来错误。

使用@mainpage编写一个描述性的主页 (为了这个目的,在一个单独的头文件中)。 考虑一下,如我的例子所示,使其成为您的主要类/函数和模块的指南。

另一个样本

当我将上面链接的主要内容doxygen内容恢复到在线状态时,以下是一些使用Markdown格式的客户端工作的示例。 使用Markdown,您可以参考markdown中的readme.md (在Doxygen设置中),这对于开源项目中包含的典型readme.md文件非常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. 

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

请记住,您几乎可以将所有内容放到多个组中,以便可以使用堆栈溢出中的标记来提供语义标记。 例如,您可能将某些东西标记为特定于特定平台的东西。

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

嵌套时,组可以正常工作 – 我有一个OOFILE源的大例子。

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

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

一个好的“最佳实践”(尽pipe并不总是可以实现)是为每个API提供简短的工作示例,并使用\ includelineno(或\ include为无行号)将它们拖入帮助中。 这些可以是unit testing,如果它们是写的,所以用户可以理解它们(即,不挂钩到更大的testing工具)。 作为一个好的副作用,对API的改变将会破坏样本,所以它们必须保持最新。

你可以用文字来描述一个API,但是没有什么比看到实际的代码来理解如何使用它。

当我发现自己在更高分辨率的屏幕上编辑代码时,我已经从使用反斜杠到Doxygen命令的@前缀。 不是那么嘈杂的反斜杠现在发现自己太难以做出Doxygen命令。

如果你确定你的团队会遵循这样一个重量级的模板,那么就使用它,如图所示。

否则,它看起来像JavaDoc。 Doxygen的好处之一是它不需要使用如此强大的标记就能完成一项工作。 你不需要使用@name和JAVADOC_AUTOBRIEF设置,你可以跳过@brief – 只要确保注释的第一行是一个合理的简要描述。

我更喜欢描述性的名字,而不是强制性的文档,并鼓励人们添加评论,只有当他们增加重要的价值。 这样一来,有价值的评论就不会被所有的噪音淹没

如果你在代码中有错误,或者你发现错误,你也可以像这样在代码中标记:

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

当你运行doxygen时,你会得到一个单独的Bug List,像Todo List这样的列表

如果你有一个真正的大项目 – 足够大,Doxygen运行超过一个小时 – 你可以把它分成多个模块, Doxygen稍后使用标签文件连接在一起 。

例如,如果你有一个包含20个项目的大型MSVC解决scheme,你可以使目录成为自己的Doxygen运行,然后使用标签文件将输出粘贴到一起,就像链接器粘在一起一样.libs使可执行文件。

您甚至可以更直接地使用链接隐喻,并使每个Doxyconfiguration文件对应一个.vcproj文件,以便每个项目(例如.lib或.dll)都有自己的Doxy输出。

对于复杂的项目,可以使用单独的文件进行模块pipe理,这可以控制组和子组。 整个层次可以在一个地方,然后每个文件可以简单地填充到子组。 例如:

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

简单地把一个小组的定义包括在另一个小组的{}内,使其成为该小组的一个孩子。 然后在代码和头文件函数可以被标记为他们在任何组的一部分,这一切都只是在完成的文档中工作。 它使重构文档更容易匹配重构代码。

我使用一个颠覆后提交钩子来拉出已更改的目录,将它们写入一个文件,然后每天晚上我会自动重新生成我们的networking服务器上的doxygen html,所以我们总是有最新的docco。

我想要logging的每个项目都有一个小小的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服务器,使用钩子:

 @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 

这将删除重复的条目,find所有具有.doxy项目文件的项目,并在其上运行doxygen。 Voila:完整的文档,在networking服务器上始终是最新的代码。

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

自动构build和发布您的文档。 作为自动构build文档的一部分,要注意警告,它非常容易编写糟糕的结构doxygen注释。

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

不要打扰@author或@date(@date在另一篇文章中提到)。 这些都是由版本控制系统处理的。

总是包括你的类的描述。 试着说出一个类是如何被使用的,或者为什么被使用,而不仅仅是它是什么(它通常只是反映名字)。

如果在\ defgroup中这样做是有意义的,则将您的成员函数和字段分组。 这是非常有用的,即使你不多说。

如果您担心有些团队成员会避免logging文档,或者您只想要最less量的文档,则可以在doxygenconfiguration中启用这些文档。

 WARNINGS = YES WARN_IF_UNDOCUMENTED = YES WARN_IF_DOC_ERROR = YES 

作为你的doxygen构build过程的一部分,将警告保存到一个文件中,并尝试获取并保持警告计数尽可能低(如果这是合理的,则为0)。 如果你这样做,每个公共和受保护的类成员将需要至less一个@brief,@param为每个函数参数和@return。 这对于描述大多数API来说已经足够了,而且不会阻碍其他活的代码库。

当然,只要符合最低项目标准,就应该鼓励人们根据自己的需要逐个logging文件。 不要将最小值设置得太高,那么最终可能得不到有用的文档。

例如,在我们的项目中,其他编码人员可能碰到的所有东西都应该logging下来。 启用警告让我们看看我们的目标有多接近。 我们也尝试使用@internal来描述我们为什么要做我们的一些私人成员。

如果您发现configuration指令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] } 

注意:snippet从EXAMPLE_PATH中获取文件,而不是源path所在的位置。 您将不得不在EXAMPLE_PATH指令中放置来自INPUT指令的相同文件和path列表。

对于需要5分钟以上生成的大型项目,我发现很有必要为单个文件生成doxygen并在Web浏览器中查看它。

虽然引用文件外的任何内容都不会解决,但仍然可以看到基本格式正常。

这个脚本需要一个文件,项目doxyconfiguration和运行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")