快捷搜索:  as  test  1111  test aNd 8=8  test++aNd+8=8  as++aNd+8=8  as aNd 8=8

官方金沙娱网站下载:采用 Javadoc 形式的集成文档有利有弊



级别:中级

Brian Goetz(brian@quiotix.com)

首席顾问,Quiotix Corp

2002 年 10 月

Java 说话按照 Javadoc 注释约定采纳了一种集成的措施来进行 API 文档体例。Javadoc 对象可以赞助天生好的 API 文档,然而大年夜多半 Java API 文档却很糟糕。由于它是源代码的一部分,以是 API 的文档体例职责终极照样落到了工程师身上。在本文中,Brian 对 Java 文档体例实践确当前状态进行了严峻的品评,同时供给了一些关于若何编写更有用的 Javadoc 的准则。

对付大年夜多半 Java 类库来说,Javadoc 是独一的文档。而且,除了商业软件组件之外,许多 Java 类不会用到 Javadoc。虽然 Javadoc 作为 API 参考对象很出色,但对付懂得类库是若何组织的和应该若何应用它来说,它却是一种十分差劲的措施。并且即便用了 Javadoc,它平日只包孕有关措施完成了什么的最基础信息,而轻忽了诸如差错处置惩罚、参数及返回值的感化域和范围、线程安然、锁定行径、前置前提、后置前提、不变前提或副感化之类的紧张特点。

向 Javadoc 进修

对付包括大年夜多半开放源码包和大年夜多半内部开拓的组件在内的许多 Java 对象而言,实际环境是:包括 Javadoc 在内,险些所有类库或组件都不具有有效的文档。这就意味着开拓职员要从 Javadoc 进修应用对象,而且我们应该斟酌根据这一现实组织我们的 Javadoc。我常常开玩笑说:现在,Java 法度榜样员必要具备的最紧张的技能之一是纯熟地应用 Google 和 Javadoc 来对那些文档体例得十分糟糕的 API 进行“逆向工程”。这可能是真的,但却并不十分可笑。

大年夜多半 Java 包都有某种“根”工具,它是在获得该对象内的任何其它工具之前,必须创建的第一个工具。在 JNDI 中,该根工具是 Context,而在 JMS 和 JDBC 中,它是 Connection。假如有人奉告您 JDBC 中的根基工具是 Connection,以及若何得到这一工具,那么接着您很可能会从 Javadoc 中经由过程仔细不雅察 Javadoc 中可用的措施列表找到若何创建并履行 Statement,以及若何迭代天生的 ResultSet。但您若何知道得到 Connection 是您的第一步呢?Javadoc 在包内按照字母顺序组织类,在类中按照字母顺序组织措施。遗憾的是,Javadoc 中没有神奇的“从这里开始(Start Here)”暗号把读者带到浏览 API 的逻辑开始位置。

包描述

最靠近“从这里开始”暗号的是包描述,但它却很少获得有效的应用。假如将文件 package.html 与源代码一路放在一个包中,那么标准的 doclet 会将已天生的 package-summary.html 文件中的内容连同类列表一路放在该包内。遗憾的是,天生我们都很认识的 HTML 文档的标准 doclet 却无法使包描述易于找到。假如您单击左上窗格中的某个包,那么这会在左下窗格中孕育发生措施列表,但并不会在主窗格中孕育发生包的择要 ? 必须单击左下窗格中的包名称来查看择要。但没紧要,终究大年夜多半包并没有包描述。

包文档是一个放置“从这里开始”文档的极好的地方,这一文档用来概述包做什么、主要摘如果什么以及从何处开始浏览包的 Javadoc。

类文档

除包文档之外,特定于类的文档对付赞助用户彻底懂得新对象也能起到紧张的感化。类文档当然应该包括此特定类做什么的描述,但还应该描述该类与包中的其它类若何关联,分外是要标识任何与该类相关的工厂类。例如,JDBC 中的 Statement 类文档应该阐明:Statement 是经由过程 Connection 类的 createStatement() 措施得到的。这样,假如一个新用户偶尔进入 Statement 页面,那么他会发明首先他必要得到 Connection。对每个类都利用这一约定的包会迅速为用户指出根工具,用户因而能够轻车熟路。

由于 Javadoc 是环抱对特定类进行文档体例而设计的,是以在 Javadoc 中平日没有显着的位置来放置演示几个相关类一路应用的示例代码。但因为一味地偏重于特定类或措施的文档体例,我们掉去了评论争论若何组合包中内容的时机。假如对付根工具,在包文档或类文档中有一个演示一些基础用法的简单代码示例,则对付许多用户来说,将是异常有用的。例如,Connection 类文档可以有一个简单示例,该示例获取连接、创建预编译语句、履行该语句并迭代结果集。从技巧上说,这可能不属于 Connection 页面,由于它还描述了包中的其它类。然而,尤其是当结合了上面那种引用当前类所依附的类的技巧时,用户才能异常迅速地找到获取简单的实用示例的道路,不管类的组织要领若何。

糟糕的文档 == 糟糕的代码

对付大年夜多半 Java 类库来说,除了那些作为打包组件出售的商业产品之外,要么没有 Javadoc,要么异常糟糕。因为存在的事实是对付大年夜多半包来说,Javadoc 是我们拥有的独一文档,这基础上意味着使我们自己陷入了这样的逆境:除了作者之外,其他人没法应用我们的大年夜部分代码 ? 假如不付出重大年夜的“考古”一样的努力,至少会这样。

因为文档现在是代码的一部分,是以我觉得是软件工程社区形成一个共识的时刻了,这便是,纵然代码很出色,假如文档很糟糕,也应该被觉得是差劲的代码,由于不能有效地重用。单元测试不久前还声望不佳,只是到了近来它才受到了许多工程师的青睐,就和它一样,为了改良我们临盆的软件的靠得住性和可重用性,API 文档也必须成为开拓历程的一个集成部分。

编写 Javadoc 便是某种形式的代码反省

编写合理的 Javadoc 也会孕育发生副感化,它迫使我们进行某种形式的代码反省,来钻研类的体系布局和它们之间的关系。假如单个包、类或措施很难体例文档,那么或许可以考试测验同时对多个包、类或措施进行文档体例,这应该是个提示,即可能它必要从新设计。

文档的自我反省方面使得某些方面加倍紧张,即在开拓历程中尽早编写 Javadoc,然后跟着代码的赓续开拓,按期对其进行反省,而不是仅仅等待代码完成再编写文档(假如有残剩光阴的话)。后一种策略十分常见,它将编写文档拖到项目着末,而那韶光阴安排十分首要,开拓职员的压力也很大年夜。结果官方金沙娱网站下载再常见不过了,便是图 1 所示的那种一文不值的文档,它只供给了“文档假象”。用户官方金沙娱网站下载真正必要的是懂得该类的事情道理,而该文档却没有供给任何这样的信息。

清单 1. 范例的一文不值的 Javadoc

/**

* Represents a command history

*/

public class CommandHistory {

/**

* Get the command history for a given user

*/

public static CommandHistory getCommandHistory(String user) {

. . .

}

}

那么好的文档包括哪些内容呢?

上面描述的组织技巧(在类描述中引用相关类或工厂类,也包括了包概述和代码样本)是形成优秀文档的好起头。它有助于新用户应用 Javadoc 懂得新对象。

但体系布局的概述只完成了义务的一半。另一半则是具体地解释措施做什么和不做什么、在什么前提下运行以及它们若何处置惩罚差错前提。大年夜多半 Javadoc 都没有完全供给所需的信息,即就是那些充分描述了措施在期望环境下的行径的 Javadoc 也是如斯,这些缺少的信息包括:

措施若何处置惩罚差错前提或分歧要求的输入

若何将差错前提传回给调用者

可能会抛出哪个特定非常的子类

哪些值对付输入是有效的

类不变前提、措施前置前提或措施后置前提

副感化

在措施之间是否有紧张联接

类若何处置惩罚多个线程同时造访一个实例的环境。

Javadoc 约定供给了 @param 标记,它让我们除了能够对参数的名称和类型体例文档之外,还可以对其意义体例文档。然而,并不是所有的措施都能很好地吸收参数的任何值。例如,虽然可以合法地向任何获取工具参数的措施通报空值(null)而不违反类型反省规则,但并不是所有的措施都能在传入空值时正常事情。Javadoc 应该显式地描述有效的参数范围,假如它盼望某个参数非 null,那么它应该这样描述,而假如它期望参数值在某个范围内,例如某种长度的字符串或大年夜于 0 的整数,那么它也应该那样描述。并非所有措施都仔细反省其参数的有效性;不进行有效性反省也没有体例关于可吸收的输入范围的文档,这二者的结合为劫难埋下了隐患。

返回代码

Javadoc 使得描述返回值的意义变得很轻易,但正如措施参数一样,@return 标记应该包括对可能返回的值范围的具体描述。对付工具取值的返回类型而言,它会返回空值吗?对付整数取值的返回类型而言,结果会限定在一个已知值或非负值的聚拢上吗?任何返回代码都有特殊意义吗,例如从 java.io.InputStream.read() 返回 -1 表示文件停止符?返回代码会被用来表示例如假如无法找到表项则返回空值那样的差错前提吗?

非常

标准 doclet 复制措施的 throws 子句,但 Javadoc @throws 标记应该更为详细。例如,NoSuchFileException 是 IOException 的子类,但 java.io 中的大年夜多半措施却只被声明为抛出 IOException。然而,措施可能自力于其它 IOException 而抛出 NoSuchFileException,这是调用者要懂得的很有用的事实 ? 它应该被包括在 Javadoc 中。还应该指出抛出各类非常类的实际差错前提,以便调用者知道在给定非常被抛出时该采取什么矫正步伐。应该用 @throws 标记对措施可能抛出的每个经反省的或未经反省的非常体例文档,并对激发抛出非常的前提体例文档。

前置前提、后置前提和不变前提

当然,您应该对措施对工具状态的影响体例文档。但您可能必要体例得更具体一些,描述措施的前置前提、后置前提和类不变前提。前置前提是在调用措施前对工具状态的约束;例如,调用 Iterator.next() 的前置前提是 hasMore() 为真。后置前提是措施调用完成后对工具状态的约束,例如在调用 add() 之后 List 不能为空。不变前提是对工具状态的一种约束,它包管该状态始终为真,例如 Collection.size() == Collection.toArray().length()。

诸如 jContract 之类的按左券设计(Design-by-contract)对象容许您应用特殊注释指定前置前提、后置前提和类不变前提,这类对象然后天生额外代码来强制这些约束。无论您是否应用对象来强制这些期望前提,对这些约束体例文档可以让用户知道要安然地应用类,他们可以做些什么。

副感化

无意偶尔候,措施除了改变工具状态之外还会有其它副感化,例如改变相关工具、JVM 或底层谋略平台的状态。例如,所有履行 I/O 的措施都有副感化。有些副感化是无害的,例如保留类处置惩罚的哀求的记数。别的一些副感化则会对法度榜样机能和精确性孕育发生重大年夜影响,例如改动通报给措施的工具的状态,或存储对该工具的引用的副本。诸如改动相关工具的状态或存储对作为措施参数通报的工具的引用之类的副感化应该体例文档。

措施联接

措施联接意味着类中的两个措施互相依附,并且都对对方的行径做了假定。发生措施联接的一种常见情形是:措施在内部应用同一个类的 toString 措施,并假定 toString 将以特其余措施款式化工具状态。假如该类已经子类化并且 toString 措施被重写了,那么这种情形可能引起问题;另一个措施会忽然不能正常事情,除非它也被重写。假如您的措施依附于其它措施的实现行径,那么必要对那些依附性体例文档。而且,假如类已子类化,那么可以以同等的要领重写两种措施以便使子类仍能正常事情。

线程安然

应该体例文档的最紧张的行径之一是线程安然,而对它险些从未体例文档。这个类是线程安然的吗?假如不是,那么是否可以经由过程用同步封装调用来使其线程安然吗?这些同步必须同特定管程相关联,照样任何不停应用的管程都可以应用呢?措施得到了对付类外部是可见的工具的锁吗?

线程安然实际上不是二进制属性;线程安然有几种可标识的等级。对线程安然体例文档,或者以致确定线程安然的等级并非老是很轻易。但未能进行官方金沙娱网站下载这一事情将导致严重的问题;在并发利用法度榜样中应用非线程安然类可能引起零星的故障,这些故障经常直到支配时才呈现(那时裸露利用法度榜样以便装入)。而且将额外锁定封装在已经是线程安然的类周围会影响机能,以致引起逝世锁。

Josh Bloch 在他的 Effective Java Programming Language Guide(参阅参考资料)一书中对类的线程安然等级体例文档供给了有用的分类法。可以按照线程安然递减顺序将类归到下列某一组:弗成变、线程安然官方金沙娱网站下载、有前提的线程安然、线程兼容和线程对立。

这种分类是一个极佳的框架,用于在并发造访环境下通报关于类行径的紧张信息。不管您是否应用这一分类法都不要紧,但您应该标识您的类意图显示的线程安然等级。我还建议:假如措施得到对一个工具的锁定,而该工具对付类自身的代码外部是可见的,那么您也应该就此体例文档,纵然这只是一个“实现细节”,以便帮忙做出全局锁定顺序(global-lock-order)决策并防止逝世锁。

停止语

对类的行径体例文档远远不光是对每个措施做什么给出一行描述。有效的 Javadoc 应该包括对下列内容的描述:

类若何互相关联

措施若何影响工具的状态

措施若何将掉足前提看护它们的调用者以及它们可能看护什么差错

类若何处置惩罚多线程利用法度榜样中的应用

措施的参数感化域及其返回值的范围

别的,糟糕的文档(或以致更糟糕,没有文档)会导致优秀的代码弗成用或弗成重用。经由过程在文档上花一些额外光阴,您将为您的用户(可能是您自己)避免无数的挫折。

参考资料

单击文章顶部或底部的评论争论来参加关于本文的论坛。

Sun 教程“How to Write Doc Comments for the Javadoc Tool”描述了 Javadoc 的规则和基滥觞基本理。

Josh Bloch 的 Effective Java Programming Language Guide 包孕了有关编写更好代码的大年夜量有用提示和指示原则。

Peter Haggar 的文章“Acquire multiple locks in a fixed, global order to prevent deadlock”(developerWorks,2000 年 9 月)描述了一种低落逝世锁风险的技巧,但这种技巧依附于对锁定行径的有效的文档。

JContract 是一种强制类左券和类约束的商业对象。

文章“Exceptional Practices”(JavaWorld,2001 年 8 月)供给了编写 throws 子句的指示原则。

Jeremy Roschelle 的文章“Doclet your servlet”(JavaWorld,2001 年 3 月)描述了可以如何应用定制 doclet 来为 servlet 更为具体的官方金沙娱网站下载文档。

John Farrell 在“Make bad code good”(JavaWorld,2001 年 3 月)中谈到了 Javadoc 在重构 Java 类方面的紧张性。

Scott Ambler 为体例措施文档供给了便捷的反省表(developerWorks,2001 年 8 月)。

Javadoc doclet API 让您编写定制 Javadoc 插件来天生不合形式的文档,或以致从 Javadoc 注释自动天生代码或模式。

在 developerWorks Java 技巧专区上查找几百篇同 Java 技巧有关的参考资料。

关于作者

Brian Goetz 是一名软件顾问,在以前的 15 年里,他不停是一名专业软件开拓职员。他是 Quiotix 的首席顾问,Quiotix 是一家位于加尼福利亚州洛萨图斯(Los Altos)市的软件开拓与咨询公司。在盛行的业界出版物中查阅 Brian 已出版和即将出版的文章。请经由过程 brian@quiotix.com 和 Brian 联系。

免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。

您可能还会对下面的文章感兴趣: