Code Review理論與實戰 (轉)

amyz發表於2007-08-15
Code Review理論與實戰 (轉)[@more@]

 :namespace prefix = o ns = "urn:schemas--com::office" />

 

 

 

 

 


 

 

 

 

Code Review 理論與實戰

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Code Review是一種透過複查程式碼提高程式碼質量的過程,在XP方法中佔有極為重要的地位,也已經成為工程中一個不可缺少的環節。本文透過對Code Review的一些概念和的探討,就如何進行Code Review和Code Review中應該注意什麼提出一些建議。 本文中涉及的問題大部分針對類程式碼。同時本文不涉及Code Review過程和組織。

關鍵詞: Code Review,JAVA, ,程式碼質量 ,軟體工程

簡介

的目的

凡事知其然還要知其所以然,我們首先需要知道什麼是Code Review和我們使用它的目的是什麼。Code Review是一種用來確認方案設計和程式碼實現的質量保證機制,透過這個機制我們可以對程式碼,測試過程和註釋進行檢查。Code Review主要用來在軟體工程過程中改進程式碼質量,透過Code Review可以達到如下目的:

在專案早期就能夠發現程式碼中的

幫助初級開發人員學習高階開發人員的經驗,達到知識共享

避免開發人員犯一些很常見,很普通的錯誤

  保證專案組人員的良好溝通

  專案或產品的程式碼更容易維護

知道了Code Review的目的,我們就可以看看如何做Code Review了,但在做Code Review前我們還有事要做,所謂預則立,不預則廢,就是說如果在進入Code Review之前我們不做些準備工作,Code Review很容易就變得沒有意義或是流於形式,這在我們周圍是有很多例子的啊。進入Code Review需要檢查的條件如下:

a)  Code Review人員是否理解了Code Review的概念和Code Review將做什麼

如果做Code Review的人員不能理解Code Review對專案成敗和程式碼質量的重要程度,他們的做法可能就會是應付了事。

b)  程式碼是否已經正確的build,build的目的使得程式碼已經不存在基本語法錯誤

我們總不希望高階開發人員或是主管將時間浪費在檢查連編譯都通不過的程式碼上吧。

c)  程式碼時功能是否正確

Code Review人員也不負責檢查程式碼的功能是否正確,也就是說,需要複查的程式碼必須由開發人員或質量人員負責該程式碼的功能的正確性。

d)  Review人員是否理解了程式碼

做複查的人員需要對該程式碼有一個基本的瞭解,其功能是什麼,是拿一方面的程式碼,涉及到或是通訊,這樣才能採取針對性的檢查

e)  開發人員是否對程式碼做了單元測試

這一點也是為了保證Code Review前一些語法和功能問題已經得到解決,Code Review人員可以將精力集中在程式碼的質量上。

需要做什麼

好了,進入條件準備好了,有人在這些條件中看到Code Review這也不負責,那也不檢查,不禁會問,Code Review到底做什麼?其實Code Review主要檢查程式碼中是否存在以下方面問題:程式碼的一致性、編碼風格、程式碼的問題、程式碼冗餘、是否正確設計以滿足需求(、功能等等),下邊我們一一道來。以下內容參考了《Software Quality Assurance: Documentation and Reviews》一文中的程式碼檢查部分。

.1完整性檢查(Completeness)

程式碼是否完全實現了設計文件中提出的功能需求

程式碼是否已按照設計文件進行了整合和Debug

程式碼是否已建立了需要的資料庫,包括正確的初始化資料

程式碼中是否存在任何沒有定義或沒有引用到的變數、常數或資料型別

程式碼的邏輯是否符合設計文件

程式碼中使用的格式、符號、結構等風格是否保持一致

  程式碼是否符合制定的標準

  所有的變數都被正確定義和使用

  所有的註釋都是準確的

  所有的都使用了正確的引數個數

.4可修改性檢查(Modifiability)

  程式碼涉及到的常量是否易於修改(如使用、定義為類常量、使用專門的常量類等)

  程式碼中是否包含了交叉說明或資料字典,以描述程式是如何對變數和常量進行訪問的

  程式碼是否只有一個出口和一個入口(嚴重的異常處理除外)

  程式碼所用的開發語言是否具有定義良好的語法和語義

  是否程式碼避免了依賴於開發語言預設提供的功能

  程式碼是否無意中陷入了死迴圈

  程式碼是否是否避免了無窮遞迴

  程式碼是否採取措施避免執行時錯誤(如陣列邊界、被零除、值越界、堆疊溢位等)

  程式的每個功能是否都作為一個可辯識的程式碼塊存在

  迴圈是否只有一個入口

  程式碼是否對每個程式進行了唯一標識

  是否有一個交叉引用的可以用來在程式碼和開發文件之間相互對應

  程式碼是否包括一個修訂歷史記錄,記錄中對程式碼的修改和原因都有記錄

  是否所有的安全功能都有標識

  註釋是否足夠清晰的描述每個子程式

  是否使用到不明確或不必要的複雜程式碼,它們是否被清楚的註釋

  使用一些統一的格式化技巧(如縮排、空白等)用來增強程式碼的清晰度

  是否在定義命名規則時採用了便於記憶,反映型別等方法

  每個變數都定義了合法的取值範圍

  程式碼中的演算法是否符合開發文件中描述的數學模型

  程式碼中的實現技術是否便於測試

經驗檢查項

以下是在實踐中建立的檢查列表(checklist),透過分類和有針對性的檢查項,保證了Code Review可以有的放矢。

編碼規範方面檢查項

檢查項參照JAVA編碼規範執行,見《JAVA編碼規範(Java Code Conventions)》

設計方面檢查項

這幾點的範圍都很大,不可能在本文展開討論,有專門的書籍介紹這方面問題,當然在Code Review中主要靠經驗來判斷。

A)  類設計和抽象是否合適

B)  是否符合面向介面的思想

C)  是否採用合適的設計正規化

效能檢查在大多數程式碼中都是需要嚴重關注的方面,也是最容易出現問題的方面,常常有程式設計師寫出了功能和語法沒有絲毫問題的程式碼後,正式執行時卻在效能上表現不佳,從而不得不做大量的返工,甚至是推倒重來。

A)  在海量資料出現時,佇列,表,,在傳輸,等方面是否會出現問題,有無控制,如分配的塊大小,佇列長度等控制引數

B)  對hashtable,vector等集合類資料結構的選擇和設定是否合適,如正確設定capacity,load factor等引數,資料結構的是否是同步的

C)  有無濫用String物件的現象

D)  是否採用通用的執行緒池、物件池模組等cache技術以提高效能

E)  類的介面是否定義良好,如引數型別等,避免內部轉換

F)  是否採用記憶體或緩衝機制以提高

G)  併發訪問時的應對策略

H)  I/O方面是否使用了合適的類或採用良好的方法以提高效能(如減少序列化,使用buffer類封裝流等)

I)  同步方法的使用是否得當,是否過度使用

J)  遞迴方法中的疊代次數是否合適,應該保證在合理的棧空間範圍內

K)  如果呼叫了阻塞方法,是否考慮了保證效能的措施

L)  避免過度,對效能要求高的程式碼是否使用profile工具,如Jprobe等

  對於JAVA來說由於存在垃圾收集機制,所以記憶體洩漏不是太明顯,但使用不當,仍然存在記憶體洩漏的問題。而對於其它的語言,如C++等在這方面就要嚴重關注了。當然資料庫連線資源不釋放的問題也是廣大程式設計師最常見的,相信有很多的PM被這個問題折磨的死去活來。

A)  分配的記憶體是否釋放,尤其在錯誤處理路徑上(對非JAVA類)

B)  錯誤發生時是否所有的物件被釋放,如資料庫連線、Socket、檔案等

C)  是否同一個物件被釋放多次(對非JAVA類)

D)  程式碼是否儲存準確的物件reference計數(對非JAVA類)

執行緒安全問題實際涉及兩個方面,一個是效能,另一個是資源的一致性,我們需要在這兩方面做個權衡,現在就是到了權衡利弊的時候了。

A)  程式碼中所有的全域性變數是否是執行緒安全的

B)  需要被多個執行緒訪問的物件是否執行緒安全,檢查有無透過同步方法保護

C)  同步物件上的鎖是否按相同的順序獲得和釋放以避免死鎖,注意錯誤處理程式碼

D)  是否存在可能的死鎖或是競爭,當用到多個鎖時,避免出現類似情況:執行緒A獲得鎖1,然後鎖2,執行緒B獲得鎖2,然後鎖1

E)  在保證執行緒安全的同時,要注意避免過度使用同步,導致效能降低

A)  迴圈結束條件是否準確

B)  是否避免了死迴圈的產生

C)  對迴圈的處理是否合適,如迴圈變數,區域性物件,迴圈次數等能夠考慮到效能方面的影響

很多Code Review人員在面對程式碼中涉及到的資料庫可移植性和提高資料庫效能方面的衝突時表現的無所適從,凡事很難兩全其美的啊。

A)  資料庫設計或語句是否便於移植(注意和效能方面會存在衝突)

B)  資料庫資源是否正常關閉和釋放

C)  資料庫訪問模組是否正確封裝,便於管理和提高效能

D)  是否採用合適的事務隔離級別

E)  是否採用過程以提高效能

F)  是否採用PreparedStatement以提高效能

A)  socket通訊是否存在長期阻塞問題

B)  傳送接收的資料流是否採用緩衝機制

C)  socket超時處理,異常處理

D)  資料傳輸的流量控制問題

物件處理方面檢查項

這個檢查項的基礎是對JAVA物件有較深的理解,但現實是很多看過《Thinking in Java》的程式設計師,仍然在程式中無法區分傳值和傳引用,以及物件和reference的區別。這或許就是理論和實踐難以結合的問題啊。正所謂知而不行,非真知也。

A)  物件生命週期的處理,是否物件的reference已經失效,能夠設定為null,並被回收

B)  在物件的傳值和傳參方面有無問題,物件的clone方法使用是否過度

C)  是否大量經常的建立臨時物件

D)  是否儘量使用區域性物件(堆疊物件)

E)  在只需要物件reference的地方是否建立了新的物件例項

JAVA中提供了方便的異常處理機制,但普遍存在的是異常被捕獲,但並沒有得到處理。我們可以開啟一段程式碼,最常見的現象是進入某個方法後,一個大的try/catch將所有程式碼行括住,然後在catch中將異常列印到控制檯,而且該異常是Exception物件。

A)  每次當方法返回時是否正確處理了異常,如最簡單的處理,記錄日誌到日誌檔案中

B)  是否對資料的值和範圍是否合法進行校驗,包括採用斷言(assertion)

C)  在出錯路徑上是否所有的資源和記憶體都已經釋放

D)  所有丟擲的異常都得到正確的處理,特別是對子方法丟擲的異常,在整個呼叫棧中必須能夠被捕捉並處理

E)  當呼叫導致錯誤發生時,方法的呼叫者應該得到一個通知

F)  不要忘了對錯誤處理部分的程式碼進行測試,很多程式碼在正常情況下執行良好,而一旦出錯,整個就崩潰了

)方面檢查項

A)  方法的引數是否都做了校驗

B)  陣列類結構是否做了邊界校驗

C)  變數在使用前是否做了初始化

D)  返回堆物件的reference,不要返回棧物件的reference

E)  方法是否被良好定義,即是否儘量面向介面程式設計,便於維護和重構

A)  對命令列執行的程式碼,需要詳細檢查命令列引數

B)  類程式檢查是否對訪問引數進行合法性驗證

C)  重要資訊的儲存是否選用合適的演算法

D)  通訊時考慮是否選用安全的通訊方式

A)  日誌是否正常輸出和控制

B)  配置資訊如何獲得,是否有硬編碼

三、總結

透過在專案中實施Code Review將為我們帶來多方面的好處,表現在提高程式碼質量,保證專案或產品的穩定性,開發經驗的積累等,具體的實施當然也要看專案的實際情況,因為Code Review也是需要成本的,這方面屬於Code Review過程的問題,將在其他文章中進行探討。

四、參考資料

Java語言編碼規範(Java Code Conventions)  SUN

Software Quality Assurance: Documentation and Reviews  Dolores R. Wallace,Wendy W. Peng, Laura M. Ippolito

斯蒂夫 電子工業出版社

五、關於作者

陳建華, 從事移動互聯方面的應用開發, 地址: to:cqbbs@yeah">cqbbs@yeah.net

 


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752019/viewspace-959288/,如需轉載,請註明出處,否則將追究法律責任。

相關文章