前言
隨著軟體技術的不斷發展,開發人員正日益重視設計模式和實現模式。然而有效的注釋也是**的重要組成部分。世界級軟體大師kent beck(大名鼎鼎的junit作者)在其著作implementation patterns中指出」programs are read more often than they are written」大意是「**被閱讀的時間遠比寫出來的時間要多得多」。為**增加有效的注釋是一種提高**可讀性的方法。有效的注釋能夠幫助**閱讀者理解設計者思路,便於**的維護。對於缺少經驗的開發人員,他們往往不知道何時需要增加注釋,如何增加注釋,怎樣增加準確的注釋。如果增加**的注釋,反而會比沒有注釋更加糟糕,更加令人費解。
作者通過閱讀一些優秀開源框架的源**,分析其中注釋的技巧,對有效的注釋進行歸納和總結,總結出以下四個原則和20條方法注釋技巧。總結出來供有志於編寫可讀性好的**的開發人員參考。當然,更應當提倡編寫清晰的無需解釋的**——讓**自己說明自己。
注釋的原則
有效的注釋不是為拙劣的**雪中送炭,而是為優美的**錦上添花。如果**需要大量的注釋來解釋,這說明**的本身實現並不理想,更好的做法是對**進行重構。優秀的**與有效的注釋相輔相成、相得益彰。雖然優秀的**可以不需要注釋,但有效的注釋可以讓**更易理解,方便未來的維護。有效的注釋需要遵循四個原則:唯一性、說明性、簡單性和一致性。下面分別說明這四個原則。
唯一性,如果**能夠明確表達意圖,比如簡單的賦值語句和簡單的條件判斷,則沒有必要增加注釋,注釋也需要遵循dry原則(don』t repeat yourself)。
說明性,如果**難以說明意圖,則需要增加清晰的注釋幫助閱讀者理解。這一點要求開發人員始終能從**閱讀者的角度來編寫**和注釋,要考慮閱讀者是否能夠很容易理解**。如果覺得**中有特殊的技巧或是關鍵的語句,則應該立即增加注釋。這樣不僅減少將來理解**的時間,而且也及時記錄了設計思路,一舉兩得。
簡單性,注釋需要清晰明了,不宜過長。閱讀者重點關注的是**的功能,而不是欣賞注釋有多藝術。注釋不應當有喧賓奪主的嫌疑。
注釋的技巧
1、解釋為什麼,而非是什麼
假設**閱讀者都是開發人員(通常也只有開發人員才會去閱讀**),開發人員在修改bug,維護軟體時都需要閱讀**,那**的注釋也理所當然面向開發人員。既然合格的開發人員都已經熟悉語言語法,就沒有必要增加語法層面的注釋,而是需要增加注釋說明**為什麼這樣寫,這樣寫需要實現什麼功能。這樣的注釋既方便閱讀者理解**,也可以起到文件的功能。此類注釋在**中最為重要,使用最為頻繁。
2、增強變數含義說明
通常乙個公司或者專案中都會存在一些編碼規範,這些規範要求變數名不能超過約定的字數。於是開發人員不得不使用單詞縮寫,以滿足字數的限制,但這樣也降低了**的可讀性。一種彌補的方法就是增加注釋。如果**的變數名不足以說明其意義,增加注釋加以解釋可以方便閱讀者理解。
3、說明段落大意
如果乙個方法的實現比較複雜,但又必須在乙個方法中實現,可以通過**分段,並增加注釋解釋段落大意,從而使方法的結構更加清晰、更易理解。具體做法是對完成同一功能的**實施分段(**排版),然後對每個段落加以注釋,相當於給乙個段落作乙個概括。類似於我們在小學學習語文時給文章分段,然後概括段落大意。
此類注釋在單元測試中經常出現。在單元測試中,乙個方法中可能包括多個測試用例,此時分段增加注釋,告訴**閱讀者接下來這段**是何作用。乙個段落用一段注釋加以闡述。通常更好的做法是將乙個複雜的方法重構為多個功能明確的方法。具體做法請參考重構技巧。
4、解釋異常處理
異常處理是編寫**中經常遇到的問題。有時異常處理會包括特殊的業務意義,增加注釋可以清楚表達作者的意圖。例如,可以在異常處理中增加注釋說明什麼情況會出現此異常,可以針對某些異常做特殊處理(如忽略異常)。
5、解釋邊界值
很大程度上涉及邊界值的處理比較容易出錯——很多bug的出現都是因為邊界值處理不當的緣故。邊界值問題最顯著體現在是否包括邊界值的處理上。如果適當增加注釋說明什麼情況不包括邊界值,什麼情況包括邊界值,會使**一目了然,避免未來閱讀**時耗費太多的時間去揣摩。
6、解釋布林型變數的操作
雖然布林型變數只有兩個值,但是其代表的意義卻隨上下文環境而大相徑庭。所以在操作乙個布林型變數時,適當增加注釋說明操作的作用,會極大地提高**的可讀性。當然,使用合適的單詞命名布林型變數會讓**可讀性更強,如done/found/success/ok/error。
7、解釋可能出現的情況
一般地,乙個方法中會處理很多情況,可以針對每種情況增加一段注釋。此類注釋通常出現在if判斷條件之前,用於解釋何種情況執行if語句體。
8、說明特殊用法
如果**中使用了特殊的語法或者較少使用的api來實現功能,需要增加注釋說明,幫助閱讀者理解。
9、使用示例說明功能
有時示例比文字更能清楚表達功能。可以在注釋中使用示例說明功能。示例可以是輸出的結果,也可以是引數的結構。
10、解釋else和default條件
if-else結構中的else條件,以及switch-case-default結構中default語句包含的業務邏輯比較泛化,**閱讀者不易明確把握條件內容,需要增加注釋加以解釋。
11、針對每個條件注釋
如果判斷條件比較複雜,而且每個條件包含一種業務意義,此時可以分別為每個條件增加注釋,使閱讀者很方便理解業務邏輯。當然,更好的做法也是對**進行重構,使用方法名或者變數名來表達意圖。具體做法請參考重構技巧。
12、解釋提高效能的**
對於提高效能的**,如果實現並不完美或者存在潛在的缺陷,有改善的要求,可以增加注釋,說明**的特殊性和重要性,以引起閱讀者的注意,提醒未來維護**時重點關注,尋求更優實現。
13、解釋何時需要預設值
**中常常會出現預設值,在出現預設值時需要解釋什麼情況下使用,以及該預設值的作用。
14、解釋突兀**
如果某段**在方法中出現得比較突兀,使人不能明白其出現的作用,需要增加注釋說明其出現的必要性,必要時需要解釋其出現的時機和在**中位置。
15、注釋語言版本差別
部分功能因語言版本差別而有不同實現,需要通過注釋解釋差別,解釋不同版本的實現方式。
16、解釋**取捨原因
一種功能可能會有多種實現,但是有時必須使用特定的實現,此時需要說明取捨的原因,方便閱讀者理解。避免未來維護人員產生好奇而修改**。
17、避免誤解
功能實現時,如果兩處**非常相識,僅存在一些細微的差別,為了避免閱讀者將差別當成錯誤,需要增加注釋加以澄清。
例如下表中兩段**均包含範圍語句,前者為[0,size()),表示範圍包括0(閉括號),但不包括size()(開括號),後者為[0,size()],表示範圍包括0(閉括號),且包括size()(閉括號)。雖然閱讀者通過if條件判斷語句可以明白意圖,但是增加注釋後更加清楚,避免閱讀者誤解兩處不一致是程式設計有誤。
private void checkrange(int index)
} private void checkrangeincludingendpoint(int index) }
18、注釋短路語句
短路語句是提前結束方法執行的語句,一般用於處理特殊的邏輯。在短路語句處增加一段注釋解釋原因可以使**更加清晰,讓**閱讀者更易理解。
19、解釋批量null賦值操作
一般批量的null賦值操作具有特殊意義,應該增加注釋說明原因(當然除了物件的初始化操作)。
20、標記待實現/完善部分
如果**中存在未實現或者需要完善的部分,可以使用todo注釋,便於開發工具收集定位。
以上20個技巧中,「解釋為什麼,而非是什麼」是核心,其他技巧均在此技巧上演化而來,是方法注釋常用的輔助手段。
jsp 單行注釋多行注釋 C語言的注釋
c語言中,注釋有兩種型別 單行注釋 單行注釋通常用於對程式中的某一行 進行解釋,用 符號表示,後面為注釋的內容 示例 printf hello,worldn 輸出hello,world 多行注釋 多行注釋就是注釋中的 可以為多行,以符號 開頭,以符號 結尾 示例 printf hello,world...
mysql整段注釋 mysql的注釋
一直沒怎麼用過mysql資料庫,今天用mysqldump備份了一下表結構,記錄一下遇到的問題 1.mysqldump預設匯出沒有事務和儲存過程,如果想匯出這些可以用 e 和 r routines dump stored routines functions and procedures 2.mysq...
mysql整段注釋 mysql的注釋
一直沒怎麼用過mysql資料庫,今天用mysqldump備份了一下表結構,記錄一下遇到的問題 1.mysqldump預設匯出沒有事務和儲存過程,如果想匯出這些可以用 e 和 r routines dump stored routines functions and procedures 2.mysq...