Effective Java(3rd)-Item56 为所有公开的API元素编写doc注释

  如果API要可用,就必须对其进行文档化。传统上,API文档是手工生成的,保持与代码的同步是一件苦差事。Java编程环境使用Javadoc实用程序简化了这一任务。Javadoc使用特殊格式的文档注释(通常称为doc注释)从源代码自动生成API文档。
  虽然doc注释约定不是正式语言的一部分,但它们实际上构成了每个Java程序员都应该知道的API。这些约定在如何编写Doc注释web页面[Javadocguide]中进行了描述。虽然自Java 4发布以来这个页面没有更新,但它仍然是一个非常宝贵的资源。在Java 9中添加了一个重要的doc标签,{@index};Java 8中的一个,{@implSpec};Java 5中有两个,{@literal}和{@code}。上述web页面中缺少这些标记,但将在本项目中讨论。
  要正确地记录API,必须在每个导出的类、接口、构造函数、方法和字段声明之前加上doc注释。如果一个类是可序列化的,还应该记录它的序列化形式(item87 )。在缺少doc注释的情况下,Javadoc所能做的最好的事情就是将声明复制为受影响API元素的唯一文档。使用缺少文档注释的API是令人沮丧和容易出错的。公共类不应该使用默认构造函数,因为无法为它们提供doc注释。要编写可维护的代码,还应该为大多数未导出的类、接口、构造函数、方法和字段编写doc注释,尽管这些注释不需要像导出API元素那样完整。

  方法的doc注释应该简洁地描述方法与其客户机之间的契约。除为继承而设计的类中的方法(item19 )外,契约应该说明方法做了什么,而不是它如何做它的工作。doc注释应该枚举方法的所有前置条件(这些条件必须为真,以便客户机调用它们)和后置条件(这些条件是在调用成功完成后才为真)。通常,先决条件是通过@throw标签的未检查异常隐式描述的;每个未检查异常对应于一个先决条件违反。此外,可以在前置条件及其@param标记中指定受影响的参数。

  除了前置条件和后置条件外,方法还应该记录任何副作用。副作用是系统状态的一个可观察到的变化,它不是实现后置条件所明显需要的。例如,如果一个方法启动了一个后台线程,文档应该注意它。
  要完整地描述方法的契约,doc注释应该为每个参数都有一个@param标记,一个@return标记(除非方法有一个void返回类型),以及一个@throw标记(对于方法抛出的每个异常,无论是否是可检查的)( item74 )。如果@return标记中的文本与方法的描述相同,则可以忽略它,这取决于您所遵循的编码标准。

  按照惯例,@param标记或@return标记后面的文本应该是一个名词短语,描述参数或返回值所表示的值。算术表达式很少用来代替名词短语;有关示例,请参见BigInteger。@throw标记后面的文本应该包含单词“if”,后跟描述引发异常的条件的子句。按照惯例,@param、@return或@throw标记后面的短语或子句不以句号结束。以下的doc注释说明了所有这些约定:

image.png

  请注意在这个doc注释中使用HTML标记(<p> 和<i>). 。Javadoc实用程序将doc注释转换为HTML, doc注释中的任意HTML元素最终会出现在生成的HTML文档中。有时候,程序员甚至会在他们的doc注释中嵌入HTML表,尽管这种情况很少见。
  还要注意在@throw子句中的代码片段周围使用Javadoc {@code}标记。这个标记有两个目的:它使代码片段以代码字体呈现,并且它抑制了代码片段中HTML标记和嵌套Javadoc标记的处理。后一个属性允许我们在代码片段中使用小于号(<),即使它是一个HTML元字符。要在doc注释中包含多行代码示例,使用Javadoc {@code}标记封装在HTML<pre>标记中。换句话说,在代码示例之前加上字符<pre>{@code and follow it with }</pre>.这保护线在代码中中断,并消除了转义HTML元字符的需要,但不需要转义at符号(@),如果代码示例使用注释,则必须转义@。
  最后,请注意doc注释中使用的单词“this list”。按照惯例,“this”指的是在doc注释中为实例方法使用方法时调用方法的对象。
  正如第15项中提到的,当您为继承设计一个类时,您必须记录它的自用模式,以便程序员知道覆盖它的方法的语义。这些自用模式应该使用在Java 8中添加的@implSpec标记来记录。回想一下,普通的doc注释描述了方法与其客户机之间的契约;相反,@implSpec注释描述了方法与其子类之间的契约,允许子类依赖于实现行为(如果它们继承了方法或通过super调用方法)。下面是它在实践中的样子:


image.png

  Java 9开始,Javadoc实用程序仍然忽略@implSpec标记,除非您通过命令行开关-标记“implSpec:a:Implementation Requirements:”。希望在后续的版本中可以纠正这个错误。
  不要忘记,您必须采取特殊的操作来生成包含HTML元字符的文档,比如小于号(<)、大于号(>)和与号(&)。将这些字符放到文档中最好的方法是用{@literal}标记包围它们,这将抑制HTML标记和嵌套Javadoc标记的处理。它类似于{@code}标记,只是它不以代码字体呈现文本。例如,这个Javadoc片段:


image.png

  生成文档:“如果|r| < 1,则几何级数收敛。”使用相同的结果文档,{@literal}标记可以放在小于号周围,而不是整个不等式周围,但是doc注释在源代码中可读性较差。这说明了doc注释在源代码和生成的文档中都应该是可读的。如果不能同时实现这两个目标,生成的文档的可读性将超过源代码的可读性。
  每个doc注释的第一个“句子”(定义如下)成为注释所属元素的摘要描述。例如,255页doc注释中的摘要描述是“返回列表中指定位置的元素”。摘要描述必须独立地描述它总结的元素的功能。为了避免混淆,类或接口中的任何两个成员或构造函数都不应具有相同的摘要描述。特别注意重载,对于重载,通常使用相同的第一句话是很自然的(但在doc注释中是不可接受的)。
  如果预期的摘要描述包含句点,请小心,因为句点可能会提前终止描述。例如,以短语开头的doc注释"“A college degree, such as B.S., M.S. or Ph.D.”将在总结描述的结果““A college degree, such as B.S., M.S.” ”问题是摘要描述在第一个句点结束,然后是空格、制表符或行结束符(或第一个块标记)[Javadoc-ref]。这里是缩写“M.S.”中的第二个句号后面跟着一个空格。最好的解决方案是用{@literal}标记来包围违规的句点和任何相关的文本,这样源代码中的句点后面就不会有空格了:

image.png

  说摘要描述是doc注释中的第一句话有点误导人。按照惯例,它很少应该是一个完整的句子。对于方法和构造函数,摘要描述应该是一个动词短语(包括任何对象),描述方法执行的操作。例如:


image.png

  如这些例子所示,使用第三人称陈述句时态(“return the number”)而不是第二人称祈使句(“return the number”)。
  对于类、接口和字段,摘要描述应该是一个名词短语,描述由类或接口的实例或字段本身表示的事物。例如:


image.png

  在Java 9中,客户端索引被添加到Javadoc生成的HTML中。这个索引以页面右上角的搜索框的形式出现,它简化了导航大型API文档集的任务。当您在框中键入时,您将得到一个匹配页面的下拉菜单。API元素(如类、方法和字段)是自动索引的。有时,您可能希望索引对您的API很重要的其他术语。为此添加了{@index}标记。对doc注释中出现的术语进行索引,就像将其包装在这个标签中一样简单,如下面的片段所示:

  • This method complies with the {@index IEEE 754} standard.

  泛型、枚举和注释在doc注释中需要特别注意。当记录泛型类型或方法时,请确保记录所有类型参数:

image.png

  在记录枚举类型时,一定要记录常量、类型和任何公共方法。注意,如果文档很短,你可以把整个文档注释放在一行:

image.png

  在记录注释类型时,一定要记录任何成员和类型本身。用名词短语记录成员,就好像它们是字段一样。对于类型的摘要描述,请使用动词短语,它表示当程序元素具有此类注释时的含义:

image.png

  包级别的doc注释应该放在名为packageinfo.java的文件中。除了这些注释之外,package-info.java必须包含一个包声明,并且可能包含关于这个声明的注释。类似地,如果您选择使用模块系统( item15),模块级别的注释应该放在模块-info.java文件中。

  在文档中经常忽略的api的两个方面是线程安全性和可序列化性。无论类或静态方法是否线程安全,都应该记录它的线程安全级别,如项目82所述。如果一个类是可序列化的,您应该记录它的序列化形式,如第87项中所述。
  Javadoc具有“继承”方法注释的能力。如果API元素没有doc注释,Javadoc将搜索最特定的适用doc注释,优先选择接口而不是超类。搜索算法的详细信息可以在Javadoc参考指南[Javadoc-ref]中找到。您还可以使用{@inheritDoc}标记从超类型继承部分doc注释。这意味着类可以重用它们实现的接口中的doc注释,而不是复制这些注释。这个工具有潜力减少维护多个几乎相同的doc注释集的负担,但是它使用起来很棘手,并且有一些限制。这些细节超出了这本书的范围。
  关于文档注释,应该添加一个警告。虽然有必要为所有导出的API元素提供文档注释,但这并不总是足够的。对于由多个相互关联的类组成的复杂api,通常需要用描述API总体架构的外部文档来补充文档注释。如果存在这样的文档,相关的类或包文档注释应该包含到它的链接。
  Javadoc会自动检查是否符合本项目中的许多建议。在Java 7中,需要命令行开关-Xdoclint来获得这种行为。在Java 8和Java 9中,默认情况下启用了check。诸如checkstyle之类的IDE插件在检查是否符合这些建议方面走得更远[Burn01]。还可以通过HTML有效性检查器运行Javadoc生成的HTML文件来降低doc注释中出现错误的可能性。这将检测HTML标记的许多不正确用法。有几个这样的检查器可供下载,您可以使用W3C标记验证服务[W3C-validator]在web上验证HTML。在验证生成的HTML时,请记住,从Java 9开始,Javadoc就能够生成HTML5和HTML 4.01,尽管默认情况下它仍然生成HTML 4.01。如果希望Javadoc生成HTML5,请使用-html5命令行开关。
  本项目中描述的约定涵盖了基本内容。尽管撰写本文时已经有15年的历史,但编写doc注释的最终指南仍然是如何编写doc注释[Javadoc-guide]。
  如果您遵循本项目中的指导原则,生成的文档应该提供对API的清晰描述。然而,唯一确定的方法是阅读Javadoc实用程序生成的web页面。对于其他人将使用的每个API,都值得这样做。正如测试程序几乎不可避免地会导致对代码的一些更改一样,阅读文档通常也会导致对doc注释的一些较小更改。
  总之,文档注释是记录API的最佳、最有效的方法。应该认为所有导出的API元素都必须使用它们。采用符合标准约定的一致样式。请记住,在文档注释中允许任意HTML,并且必须转义HTML元字符。
本文写于2019.7.18,历时1天

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,088评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,715评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,361评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,099评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,987评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,063评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,486评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,175评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,440评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,518评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,305评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,190评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,550评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,152评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,451评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,637评论 2 335

推荐阅读更多精彩内容

  • [{"reportDate": "2018-01-23 23:28:49","fluctuateCause": n...
    加勒比海带_4bbc阅读 765评论 1 2
  • 目录: Android:Android 0.*Android 1.*Android 2.*Android 3.*A...
    敲代码的令狐葱阅读 3,730评论 0 2
  • 生活,很多人不满于生活的现状 其实当下的生活方式都是以往自己选择的 有些人目标很明确,要挣很多很多的钱 但当时没有...
    Mary妹善阅读 209评论 0 0
  • 问题——行动——转折 有一个自称张方林的山西太原经侦上网逃犯,打我支队值班室电话称要投案自首并留下联系电话,经核...
    Alice小香阅读 581评论 0 0
  • 小燕和她的男人离婚了,离婚的原因只有一句话:我已经完全死于他。 女人实际上非常重视感情。如果他们没有受到男人的伤害...
    少女心两三事阅读 221评论 0 0