这就是另一个为什么文档很重要的理由:它能避免人们多次跑来问你你这复杂的算法是怎样运作的,或者为什么管理器中增加的汉堡没有同样被加到职工管理器的统计中去。在一个团队中,文档可以避免以下问题:
在工作的时候被打断,之后难以返回继续工作;
寻找可以回答问题的人,因为让其他成员知道了解自己是否能够回答问题;
等待某个队员有时间回答他们的问题。
所以写文档可以帮助团队提高生产力并专注于开发。
让成功更进一步
这一点更加主观些。写Javadoc让我非常有成就感,因为当我再次使用我的API的时候,我写代码有文档参考,这帮我确保我没有忘记任何小细节。尽管我通常不会忘记,知道有文档在支撑我的记忆力也是件很棒的事。
看到IntelliJIDEA展示我的文档让我有“嘿,看,我就像是专业的,我做的东西太棒了,我甚至有文档噢”的感觉。在某些程度上的确是这样,不是吗?因为当你在使用一个lib,其中的log(Strings,inti)没有任何命名良好的参数描述,你一定像我一样在想“这个究竟是什么玩意儿?”。
不知道你怎样想的,我反正是觉得新的Javadoc设计特别赞。我认为让自己的文档整洁是非常棒的事。但是正如我说的,这只是我个人的感受。
写Javadoc的小技巧
在Javadoc中你有一下很好的标签可以使用:
@author
@version
@param
@return
@exception/@throws
@see
@since
@serial/@serialField/@serialData
@deprecated
但是这篇文章的目的并不是详细解释所有标签,而是作为文档作者和开发人员,我想分享我在写我的Javadoc时使用的技巧。
使用@link和@linkplain来指向某些代码
在我的Javadoc中,如果有依赖关系或者对文档有用,我会提及其它类和方法。为了使方法和类的浏览更简便,你可以使用@link。它是这样工作的:
{@linkBurgersManager}指向一个类
{@linkBurgersManagerburgersmanager}指向带有标签的类
{@link#eat(Burger,boolean)}指向此类中的某个方法
{@link#eat(Burger,boolean)eat}指向此类中带有标签的某个方法
{@linkBurgersManagers#eat(Burger,boolean)}指向其他类中的某个方法
{@linkBurgersManagers#eat(Burger,boolean)burgersmanagereat}指向其他带有标签的类的某个方法
@link和@linkplain的区别是后者不会生成等宽字体的代码。
使用@code来表明代码段
通常你会在Javadoc中发现一段代码,用来说明怎样使用方法和类,或者提供其它例子。为了正确显示代码,并防止一些像这样的标记被打断,你可以使用@code。
{<ahref='http://www.jobbole.com/members/java12'>@code</a>
List<Burger>burgers=newArrayList<>();
for(intindex=0;index<10;index++){
burgers.add(newBurger(“Burger#”+index));
}
}
@code会为你生成标记。
使用@value来在文档中插入字段值
当你有一个常量,我可能想要它的值在文档中显示出来。有两个选择:
自己插入这个值。但是如果这个值改变了,你必须更新你的文档,如果你绝对不会忘记这点,那你可以放心选择这个做法;
使用@value来为你插入值,这样你就不用手动更新你的文档。
对我来说第二个选择是利用Javadoc工具的最佳方法,我会讨论这个方法。实际上,使用单一属性特别有用:
/** *Thedefaultvalueforthisfieldis{@value}. *这个域的默认值是{@value}. */ publicstaticfinalStringBURGER_SHOP_NAME="Thierry'sshop"; 但你也可以指向其它常量,比如: /** *Thedefaultvalueforthisfieldis{@value}whenthevalue *of{<ahref='http://www.jobbole.com/members/57845349'>@link</a>#OWNER}is{@value#OWNER}. *这个域的默认值是{@value}当 *{<ahref='http://www.jobbole.com/members/57845349'>@link</a>#OWNER}的值为{@value#OWNER}. */ publicstaticfinalStringBURGER_SHOP_NAME="Thierry'sshop"; /** *Thedefaultownerofthisawesomeburgershop. *这家很棒的汉堡店的默认店主. */ publicstaticfinalStringOWNER="Thierry"; |
用@since来表明此特性的生效时间
通常,在你的代码中表明类或者方法何时开始生效非常有用。为此使用@since标签并在其后注明该特性执行的版本/年份:
/** *Thisawesomeclassisfordoingawesomethings *这个棒呆了的类是用来做些棒呆了的事 *<ahref='http://www.jobbole.com/members/chchxinxinjun'>@since</a>burger-core-0.1 *@version0.2 */ publicclassBurgersManager{ /** *Allowstoeatburgers *可以吃汉堡 *<ahref='http://www.jobbole.com/members/chchxinxinjun'>@since</a>burger-core-0.2 */ publicvoideat(Burgerburger,booleanfast){ //TODO } } |
你可以看到,我把它用在了方法和类上,并且不止包含了版本号。事实上,现在我们的应用有很多不同的模块,这些模块可以有不同生命周期,即版本。说某个方法或者类从0.2版本开始生效并没有特别的意思。那么究竟是什么的0.2版本?这就是为什么我总是用一个相关的@since来帮助我的同事第一眼就明白这些是什么时候开始生效的。
不止如此,这个标签的一个好处就是它可以帮你创建发布说明。等会儿,啥?不,并不是使用你最喜欢的IDE,比如IntelliJIDEA,然后查找包含“@sinceburger-core-0.2″的文件。然后瞧,你可以找到自那个版本之后添加的所有方法和类。当然,这无法告诉你被更新的方法和类,而只会告诉你新添加的东西。但是你应该看到,这么简单的窍门多有用。
不要匿名,使用@author
我非常讨厌的一件事:开发人员不承认自己的代码,并且不表明是他们为了一个糟糕的原因写了这糟糕的代码。如果你写了一段代码,要么承认它,要么去当经理。你可以用@author来表明你是这个类或者方法的作者。我认为把这标签既放在类上也放在方法上比较好,因为一个类的方法可能不是都是类的作者写的。
另一个好习惯就是,把一个方法或类的所有作者都加上。试想一下,你和你的同事写了一个很棒的方法,而标签表明你是这个方法的唯一作者。有一天你去度假了,有人在读你的方法,但不是很明白并且想要一些细节。而是因为你被标为唯一的作者,他们不知道这个信息可以从和你一起写代码的同事那里很容易就获得。你知道我要说什么了,对吧?要记得给代码加@author来表明作者。
对非void方法要使用@return
我要说这一点对我来说非常有意义。有时候我看到类似以下例子中的代码就要跪了。
/**Gettheaddress.
*@return
*/
publicStringgetAddress(){/*…*/}
为什么!?说真的,为什么你不填好@return?“因为只是一行而已,就是获得地址”。
不不不,请不要这样。如果你那样回答,是因为你的文档。怎么说呢,因为你的文档欠佳。是的,因为你可以很简单地写出一个更好的版本,而不是像以上你见到的糟糕的文档,看:
/** *Gettheaddressofthisburgershop.Theaddressisofthefollowingformat: *{<ahref='http://www.jobbole.com/members/java12'>@code</a>addressline1 *addressline2 *zipcodecity} *@returntheaddressofthisburgershopor{<ahref='http://www.jobbole.com/members/java12'>@code</a>null}ifnotfilled. */ /** *获取汉堡店的地址。地址格式: *{<ahref='http://www.jobbole.com/members/java12'>@code</a>地址行1 *地址行2 *邮编城市} *@return汉堡店的地址,如果没有填地址返回{<ahref='http://www.jobbole.com/members/java12'>@code</a>null}. */ |
好太多了,对吧?这样你的文档就有用了。我一直试着寻找给代码写文档的合适方法,因为有时候读者只读@return的内容,有时候也会读@return上面的内容,你添加一些说明就可以简单地避免疑惑。
用@param说明参数的含义
有什么比看到方法使用一个像i这样的意义不明的参数而不加任何文档更加沮丧呢?有时候你可以通过方法的名字来猜到这个参数的目的,可是有时候就不行。所以在你的文档里,你应该使用@param来表明这个参数的含义,并说明可能的有效值。在我们的例子中,i可以是日志的级别:INFO,DEBUG或者TRACE。这个标签另一个很有用的例子就是当这个值对应的是一个索引。有些情况下索引从0开始,有些情况下从1开始。@param就是用来描述这一区别的标签。
生成文档
在代码中有文档是非常好的,但是现在你必须生成文档。所以你可以使用JDK提供的Java文档工具来生成它。
通过执行类似这样的命令:
javadoc{packages|source-files}[options]
你可以指定想要生成文档的包名或文件名,多个名字用空格分隔。
以下简要描述了一些jJavadoc工具能够接受的选项:
-author:在生成的文档中生成@author用
-d:要在当前目录之外生成文档的目录
-nodeprecated:不为被标为@deprecated的代码生成文档
-protected:包含protected和public类和类成员
-private:包含private类和类成员
-public:只包含public类和类成员
像IDE之类的工具也可以生成你的文档,但是如果它很好地格式化并且可以提供预览。
一些像Maven和Gradle这样的依赖管理工具也带有生成文档的阶段或任务。这很棒,因为你的文档可以一直紧随代码的发布来生成,这样它就一直是最新的。
总结
文档对于你的整个团队非常重要。它能帮你理清你在写什么代码,更重要的是,你为什么这样实现它。
希望这篇文章能让你想要写出更好的文档。如果是这样的话请告诉我你是否写了文档,你是怎样写的。