Javadoc 最佳实践
Javadoc 是 Java 编程中很重要的一部分,然而却很少有人谈论如何去写好一个的 Javadoc。如果想写好 Javdoc,首先最好有一份代码规范。
Javadoc 代码规范
我之前尝试过一些 Javadoc 的标准。考虑到每个人喜好不同,我这里只想谈谈最基本的一些原则,不去涉及方方面面的细节。另外,我们只讨论 Javadoc 的格式,其内容不在本文范围之内。
这里有一份 Oracle 家的指南 要比本文详细的多,不过大部份要求都是一致的。
以下所有条目我都尽可能说的简明,并用一些例子去阐述。
让 Javadoc 像代码一样可读
当你听到 “Javadoc” 这个词的时候,你首先想到的可能是 Javadoc 生成的 HTML 网页,然而实际情况绝非如此。多数情况下,其他人都是在看源代码的时候用到这些 Javadoc,比如你看同事的代码、或是研究第三方库的代码。时刻记住:让 Javadoc 像 Java 代码一样保持可读性。
Public 和 Protected
所有 Public 和 Protected 方法都应当有相应的 Javadoc。Package 和 Private 方法不强求,但是如果有帮助的话加上也很好。
如果子类覆盖了父类中的某个方法,一般来说不需要
Javadoc,除非这个覆盖的实现和原有的差别很大,这时候需要用 Javadoc
说明差异的那部分。@Override
注解不仅标记了方法覆盖,另一方面也是暗示读者要参考原来方法上的文档一起看。
使用标准的 Javadoc 风格注释
Javadoc 以 /**
开头、以 */
结尾,并且每行要以星号开头:
1 | /** |
注意别用 **/
作结尾。
用简单的 HTML tags 就行了,不需要 XHTML
Javadoc 用 HTML tags 来识别段落、列表等等。很多开发者可能觉得 XHTML(HTML 的一种“严格版本”)会更好,其实不然。XHTML 常常会多出一些 tag,这会导致代码变得更复杂了,可读性更差。
此外,Javadoc 的 parser 其实会帮你把没闭合的 tags 自动闭合的,别担心。
用单个 <p>
来分割段落
Javadoc
经常会需要分成好几段。所以问题来了:怎样优雅地加上段落标记?答案是,在两段之间写上一行
<p>
就可以了,不用加 </p>
闭合它。
1 | /** |
用单个 <li>
来标记列表项
列表在 Javadoc
中也很常用,比如用来表示一组选项、一些问题等等。推荐的做法是用一个
<li>
作为每项的开头,同样不需要闭合。此外,别忘了加段落 tag:
1 | /** |
首句很重要
Javadoc 的首句(用英文句号结束)也被作为这个 Javadoc 的摘要,在折叠的时候只会显示这一句。因此首句必须是个总结性的描述,它最好简洁有力,不能太长。
虽然没有强制要求,我们建议首句自成一个段落,这让代码看起来更清晰。
对于英文注释,推荐使用第三人称来描述,比如 “Gets the foo”、“Sets the bar”、“Consumes the baz”。避免使用第二人称,比如 “Get the foo”。
用 “this” 指代类的对象
当你想描述这个类的一个实例(对象)的时候,用 “this” 来指代它,比如 “Returns a copy of this foo with the bar value updated”
别写太长的句子
尽量让一句话能容纳在一行中,一般来说一行有 80 到 120 个字符。
新的句子就另起一行,这会让代码可读性更好,也会让以后改写 Javadoc 容易很多。
1 | /** |
正确使用 @link 和 @code
很多地方的描述需要涉及到其他类或方法,这时最好用 @link 和 @code。
@link 会最终变成一个超链接,它有以下几种形式:
1 | /** |
@code 用来标记一小段等宽字体,也可以用来标记某个类或方法,但不会生成超链接。
建议在第一次提到某个类或方法的时候用 @link,此后直接用 @code 即可。
不要在首句中使用 @link
之前提到,Javadoc 的首句也被用作概要,首句中的超链接会让读者感到混乱。如果一定要在第一句话中引用其它类或方法,始终用 @code 而不是 @link,第二句开始再用 @link。
null、true、false 不必用 @code 标记
null、true、false 这些词在 Javadoc 中太常用了,如果每次都加上 @code,无论是对读者还是作者都是个负担。
使用 @param、@return 和 @throws
几乎所有方法都会输入几个参数、输出一个结果,@param 和 @return 就是用来描述这些输入输出参数的,@throws 用于描述方法抛出的异常。
如果有多个输入参数,@param 的顺序也要和参数一致。@return 应当始终放在 @param 之后,然后才是 @throws。
为范型参数加上 @param
如果一个类或方法有范型参数(例如
<T>
),这些参数也应当被文档化,推荐的做法是给
<T>
也加上一个 @param 说明。
在 @param 之前空一行
始终在 Javadoc 的内容和 @param、@return 之间留个空行,这让代码的可读性更佳。
用短语来描述 @param 和 @return
@param 和 @return 后面跟的的描述是个短语,而非完整的句子,因此它得用小写字母开头(经常是 the),结尾也不需要用句号。
用 if-句来描述 @throws
@throws 通常跟着一个 “if” 句子来描述抛异常的情形,比如 “@throws IllegalArgumentException if the file could not be found”。
@param 的参数名之后空两格
在源代码中阅读 Javadoc 的时候,如果参数名后面只有一个空格,读起来会有点困难,两个空格就好很多。另外,避免把参数按列对齐,否则参数改名、增减参数的时候会很麻烦。
1 | /** |
写明各参数和返回值的 null 行为
一个方法是否接受 null、会不会返回 null 对于其他开发者是十分重要的信息。除非是原始类型,@param 和 @return 都应该注明它是否接受或返回 null。以下标准若适用请务必遵循:
- “not null” 表明不接受 null,若输入 null 可能导致异常,例如 NullPointerException
- “may be null” 表明可以传入 null 参数
- “null treated as xxx” 表明 null 值等价于某个值
- “null returns xxx” 表明如果输入 null 则一定会返回某个值
定义清楚这些之后,不要再为 NullPointerException 写 @throws。
1 | /** |
有人可能想在某个地方(像是类或包的 Javadoc)集中定义 null 相关行为,但我们不建议你这么做,因为这对别人并没有帮助。方法上的 Javadoc 很容易就能看到,而类或包层级的 Javadoc 要去翻一遍才能找到。
其他简单的约束条件也建议写到 Javadoc 里,比如 “not empty, not null”。原始类型也可以加上边界约束,比如 “from 1 to 5” 或 “not negative”
给 Specification 加上 implementation notes
如果某个接口允许第三方来实现,而你为这个接口写了个正式的规格说明(specification),这时候考虑加个 “implementation notes” 章节。这通常出现在类的 Javadoc 上,用于描述一些不太好写在特定方法上的东西,或者一些其他人不感兴趣的东西。参考这个例子。
不要用 @author
@author 用来标记类的作者,这个功能已经过时了,不要用。版本控制系统(例如 git)会记住作者的。
例子
总结
希望这些建议能帮你写出更好的 Javadoc。当然,这只是一份建议,你也可以选择其他标准来参考。