Javadoc 最佳實踐
本文來源:https://ericfu.me/javadoc-coding-standards/
Javadoc 是 Java 編程中很重要的一部分,然而卻很少有人談?wù)撊绾稳懞靡粋€的 Javadoc。如果想寫好 Javdoc,首先最好有一份代碼規(guī)范。
Javadoc 代碼規(guī)范
我之前嘗試過一些 Javadoc 的標(biāo)準(zhǔn)。考慮到每個人喜好不同,我這里只想談?wù)勛罨镜囊恍┰瓌t,不去涉及方方面面的細(xì)節(jié)。另外,我們只討論 Javadoc 的格式,其內(nèi)容不在本文范圍之內(nèi)。
這里有一份 Oracle 家的指南 要比本文詳細(xì)的多,不過大部份要求都是一致的。
以下所有條目我都盡可能說的簡明,并用一些例子去闡述。
讓 Javadoc 像代碼一樣可讀
當(dāng)你聽到 “Javadoc” 這個詞的時候,你首先想到的可能是 Javadoc 生成的 HTML 網(wǎng)頁,然而實際情況絕非如此。多數(shù)情況下,其他人都是在看源代碼的時候用到這些 Javadoc,比如你看同事的代碼、或是研究第三方庫的代碼。時刻記住:讓 Javadoc 像 Java 代碼一樣保持可讀性。
Public 和 Protected
所有 Public 和 Protected 方法都應(yīng)當(dāng)有相應(yīng)的 Javadoc。Package 和 Private 方法不強求,但是如果有幫助的話加上也很好。
如果子類覆蓋了父類中的某個方法,一般來說不需要 Javadoc,除非這個覆蓋的實現(xiàn)和原有的差別很大,這時候需要用 Javadoc 說明差異的那部分。@Override?注解不僅標(biāo)記了方法覆蓋,另一方面也是暗示讀者要參考原來方法上的文檔一起看。
使用標(biāo)準(zhǔn)的 Javadoc 風(fēng)格注釋
Javadoc 以?/**?開頭、以?*/?結(jié)尾,并且每行要以星號開頭:
/**
?*?Standard?comment.
?*/
public?...
/**?Compressed?comment.?*/
public?...
注意別用?**/?作結(jié)尾。
用簡單的 HTML tags 就行了,不需要 XHTML
Javadoc 用 HTML tags 來識別段落、列表等等。很多開發(fā)者可能覺得 XHTML(HTML 的一種“嚴(yán)格版本”)會更好,其實不然。XHTML 常常會多出一些 tag,這會導(dǎo)致代碼變得更復(fù)雜了,可讀性更差。
此外,Javadoc 的 parser 其實會幫你把沒閉合的 tags 自動閉合的,別擔(dān)心。
用單個??來分割段落
Javadoc 經(jīng)常會需要分成好幾段。所以問題來了:怎樣優(yōu)雅地加上段落標(biāo)記?答案是,在兩段之間寫上一行??就可以了,不用加?
/**
?*?First?paragraph.
?*?
?*?Second?paragraph.
?*?May?be?on?multiple?lines.
?*?
?*?Third?paragraph.
?*/
public?...
用單個??來標(biāo)記列表項
列表在 Javadoc 中也很常用,比如用來表示一組選項、一些問題等等。推薦的做法是用一個??作為每項的開頭,同樣不需要閉合。此外,別忘了加段落 tag:
/**
?*?First?paragraph.
?*?
?*?- the?first?item
?*? - the?second?item
?*? - the?third?item
?*?
?*?Second?paragraph.
?*/
public?...
首句很重要
Javadoc 的首句(用英文句號結(jié)束)也被作為這個 Javadoc 的摘要,在折疊的時候只會顯示這一句。因此首句必須是個總結(jié)性的描述,它最好簡潔有力,不能太長。
雖然沒有強制要求,我們建議首句自成一個段落,這讓代碼看起來更清晰。
對于英文注釋,推薦使用第三人稱來描述,比如 “Gets the foo”、“Sets the bar”、“Consumes the baz”。避免使用第二人稱,比如 “Get the foo”。
用 “this” 指代類的對象
當(dāng)你想描述這個類的一個實例(對象)的時候,用 “this” 來指代它,比如 “Returns a copy of this foo with the bar value updated”
別寫太長的句子
盡量讓一句話能容納在一行中,一般來說一行有 80 到 120 個字符。
新的句子就另起一行,這會讓代碼可讀性更好,也會讓以后改寫 Javadoc 容易很多。
/**
?*?This?is?the?first?paragraph,?on?one?line.
?*?
?*?This?is?the?first?sentence?of?the?second?paragraph,?on?one?line.
?*?This?is?the?second?sentence?of?the?second?paragraph,?on?one?line.
?*?This?is?the?third?sentence?of?the?second?paragraph?which?is?a?bit?longer?so?has?been
?*?split?onto?a?second?line,?as?that?makes?sense.
?*?This?is?the?fourth?sentence,?which?starts?a?new?line,?even?though?there?is?space?above.
?*/
public?...
正確使用 @link 和 @code
很多地方的描述需要涉及到其他類或方法,這時最好用 @link 和 @code。
@link 會最終變成一個超鏈接,它有以下幾種形式:
/**
?*?First?paragraph.
?*?
?*?Link?to?a?class?named?'Foo':?{@link?Foo}.
?*?Link?to?a?method?'bar'?on?a?class?named?'Foo':?{@link?Foo#bar}.
?*?Link?to?a?method?'baz'?on?this?class:?{@link?#baz}.
?*?Link?specifying?text?of?the?hyperlink?after?a?space:?{@link?Foo?the?Foo?class}.
?*?Link?to?a?method?handling?method?overload?{@link?Foo#bar(String,int)}.
?*/
public?...
@code 用來標(biāo)記一小段等寬字體,也可以用來標(biāo)記某個類或方法,但不會生成超鏈接。
建議在第一次提到某個類或方法的時候用 @link,此后直接用 @code 即可。
不要在首句中使用 @link
之前提到,Javadoc 的首句也被用作概要,首句中的超鏈接會讓讀者感到混亂。如果一定要在第一句話中引用其它類或方法,始終用 @code 而不是 @link,第二句開始再用 @link。
null、true、false 不必用 @code 標(biāo)記
null、true、false 這些詞在 Javadoc 中太常用了,如果每次都加上 @code,無論是對讀者還是作者都是個負(fù)擔(dān)。
使用 @param、@return 和 @throws
幾乎所有方法都會輸入幾個參數(shù)、輸出一個結(jié)果,@param 和 @return 就是用來描述這些輸入輸出參數(shù)的,@throws 用于描述方法拋出的異常。
如果有多個輸入?yún)?shù),@param 的順序也要和參數(shù)一致。@return 應(yīng)當(dāng)始終放在 @param 之后,然后才是 @throws。
為范型參數(shù)加上 @param
如果一個類或方法有范型參數(shù)(例如?),這些參數(shù)也應(yīng)當(dāng)被文檔化,推薦的做法是給??也加上一個 @param 說明。
在 @param 之前空一行
始終在 Javadoc 的內(nèi)容和 @param、@return 之間留個空行,這讓代碼的可讀性更佳。
用短語來描述 @param 和 @return
@param 和 @return 后面跟的的描述是個短語,而非完整的句子,因此它得用小寫字母開頭(經(jīng)常是 the),結(jié)尾也不需要用句號。
用 if-句來描述 @throws
@throws 通常跟著一個 “if” 句子來描述拋異常的情形,比如 “@throws IllegalArgumentException if the file could not be found”。
@param 的參數(shù)名之后空兩格
在源代碼中閱讀 Javadoc 的時候,如果參數(shù)名后面只有一個空格,讀起來會有點困難,兩個空格就好很多。另外,避免把參數(shù)按列對齊,否則參數(shù)改名、增減參數(shù)的時候會很麻煩。
/**
?*?Javadoc?text.
?*?
?*?@param?foo??the?foo?parameter
?*?@param?bar??the?bar?parameter
?*?@return?the?baz?content
?*/
public?String?process(String?foo,?String?bar)?{...}
寫明各參數(shù)和返回值的 null 行為
一個方法是否接受 null、會不會返回 null 對于其他開發(fā)者是十分重要的信息。除非是原始類型,@param 和 @return 都應(yīng)該注明它是否接受或返回 null。以下標(biāo)準(zhǔn)若適用請務(wù)必遵循:
“not null” 表明不接受 null,若輸入 null 可能導(dǎo)致異常,例如 NullPointerException “may be null” 表明可以傳入 null 參數(shù) “null treated as xxx” 表明 null 值等價于某個值 “null returns xxx” 表明如果輸入 null 則一定會返回某個值
定義清楚這些之后,不要再為 NullPointerException 寫 @throws。
/**
?*?Javadoc?text.
?*?
?*?@param?foo??the?foo?parameter,?not?null
?*?@param?bar??the?bar?parameter,?null?returns?null
?*?@return?the?baz?content,?null?if?not?processed
?*/
public?String?process(String?foo,?String?bar)?{...}
有人可能想在某個地方(像是類或包的 Javadoc)集中定義 null 相關(guān)行為,但我們不建議你這么做,因為這對別人并沒有幫助。方法上的 Javadoc 很容易就能看到,而類或包層級的 Javadoc 要去翻一遍才能找到。
其他簡單的約束條件也建議寫到 Javadoc 里,比如 “not empty, not null”。原始類型也可以加上邊界約束,比如 “from 1 to 5” 或 “not negative”
給 Specification 加上 implementation notes
如果某個接口允許第三方來實現(xiàn),而你為這個接口寫了個正式的規(guī)格說明(specification),這時候考慮加個 “implementation notes” 章節(jié)。這通常出現(xiàn)在類的 Javadoc 上,用于描述一些不太好寫在特定方法上的東西,或者一些其他人不感興趣的東西。參考這個例子。
不要用 @author
@author 用來標(biāo)記類的作者,這個功能已經(jīng)過時了,不要用。版本控制系統(tǒng)(例如 git)會記住作者的。
例子
這個 ThreeTen 項目里有一些更完整的例子
總結(jié)
希望這些建議能幫你寫出更好的 Javadoc。當(dāng)然,這只是一份建議,你也可以選擇其他標(biāo)準(zhǔn)來參考。
最近面試BAT,整理一份面試資料《Java面試BAT通關(guān)手冊》,覆蓋了Java核心技術(shù)、JVM、Java并發(fā)、SSM、微服務(wù)、數(shù)據(jù)庫、數(shù)據(jù)結(jié)構(gòu)等等。 獲取方式:點“在看”,關(guān)注公眾號并回復(fù)?666?領(lǐng)取,更多內(nèi)容陸續(xù)奉上。 明天見(??ω??)?
