本文向大家介紹Code Review的主要內容,以及流行的檢查Code Conventions的工具。同時(shí),對于目前應用最為廣泛的CheckStyle的應用給出詳細的介紹,也列舉了很多使用CheckStyle的最佳實(shí)踐。
一、Code Review & Code Conventions
質(zhì)量是衡量一個(gè)軟件是否成功的關(guān)鍵要素。而對于商業(yè)軟件系統,尤其是企業(yè)應用軟件系統來(lái)說(shuō),除了軟件運行質(zhì)量、文檔質(zhì)量以外,代碼的質(zhì)量也是非常重要的。軟件開(kāi)發(fā)進(jìn)行到編碼階段的時(shí)候,最大的風(fēng)險就在于如何保證代碼的易讀性和一致性,從而使得軟件的維護的代價(jià)不會(huì )很高。
在軟件開(kāi)發(fā)的過(guò)程中,以下幾種情形隨處可見(jiàn):
1) 軟件維護時(shí)間長(cháng),而且維護人員的積極性不高:
做過(guò)軟件維護的開(kāi)發(fā)人員,尤其是在接手不是自己開(kāi)發(fā)產(chǎn)品的源碼的時(shí)候,即使有良好的文檔說(shuō)明,仍然會(huì )對代碼中冗長(cháng)、沒(méi)有注釋的段落“嘆為觀(guān)止”。理解尚且如此困難,何況要修改或者增加新的功能。因此,很多開(kāi)發(fā)人員不愿意進(jìn)行軟件維護的工作。
2)新的開(kāi)發(fā)人員融入團隊的時(shí)間比較長(cháng):
除了沒(méi)有良好的培訓、文檔等有效的機制以外,每個(gè)人一套的編碼風(fēng)格,也容易造成新成員對于已有代碼的理解不夠,甚至出現偏差。
編碼規范,作為解決以上問(wèn)題的方案已經(jīng)得到了很長(cháng)時(shí)間的應用。而在產(chǎn)品或者項目實(shí)際開(kāi)發(fā)的過(guò)程中,僅有Code Conventions是不能解決Code的問(wèn)題的。它往往和Code Review配合,作為代碼質(zhì)量保證的手段。
1.1. Code Review的層次與內容
Code Review就是審查代碼的質(zhì)量。根據形式分為兩種,一種是交叉代碼審查,就是自己的代碼由他人來(lái)檢查,就象檢查作業(yè)一樣;另一種是代碼會(huì )審,就是以會(huì )議的形式,大家共同審核代碼的質(zhì)量。
Code Review 的目的有:
·在項目早期就能夠發(fā)現代碼中的BUG;
·幫助初級開(kāi)發(fā)人員學(xué)習高級開(kāi)發(fā)人員的經(jīng)驗,達到知識共享;
·避免開(kāi)發(fā)人員犯一些很常見(jiàn),很普通的錯誤;
·保證項目組人員的良好溝通;
·項目或產(chǎn)品的代碼更容易維護;
一般情況下,Code Review的內容與層次如下:
·編碼風(fēng)格與代碼規范一致性:檢查代碼是否符合編碼規范,確保所有人寫(xiě)的代碼基本一致;
·代碼滿(mǎn)足基本的功能要求:檢查代碼的邏輯實(shí)現,以及單元測試的編寫(xiě)策略,確認實(shí)現功能性需求;
·代碼滿(mǎn)足性能等非功能性需求:非功能性需求一般不便于測試,需要借助一定的工具和Review人員的素質(zhì),針對編碼中對于性能影響的瓶頸給出解決方案;
·去除冗余,提高代碼可讀性:適當使用 Refactorying技術(shù),去除代碼中的Bad Smell;如果有需要,可以Refactorying to Pattern。
1.2. Code Conventions的尷尬境地
從Code Review的層次分析中我們可以看到,Code Conventions是其基礎。而實(shí)際的情況是,在軟件開(kāi)發(fā)中,兩者都淪為“宣傳口號”,而非切實(shí)執行的實(shí)踐。
造成這種情形的原因有二:
1. Code Conventions是開(kāi)發(fā)過(guò)程的“道德”而非“法律”:很多時(shí)候,由于沒(méi)有有效的工具或者輔助手段的支持,是否遵守編碼規范是依靠開(kāi)發(fā)人員的“道德素養”-自覺(jué)遵守,而非實(shí)際考核的指標;
2. Code Review的基石不牢:在第一種原因的影響下,Code Review執行的過(guò)程中,如果花費了大量的時(shí)間在代碼規范的檢查上,那么對于更為重要的程序執行邏輯、性能、易讀性等的評審投入的精力就有限的;而這種情況反過(guò)來(lái)也使得對于編碼規范的檢查,通常都是走過(guò)場(chǎng)。最后,還是每個(gè)人一套規范,只要最終交付的產(chǎn)品完成指定的功能就可以啦。
二、CheckStyle
面對以上描述的Code Conventions的尷尬境地,陸續有開(kāi)發(fā)人員提出了自己的解決方案。目前,對于JAVA的代碼規范的檢查,已經(jīng)有很多成熟的工具,例如CheckStyle、PMD以及Jalopy等[3]。其中,CheckStyle的應用非常廣泛,眾多開(kāi)源項目都使用它作為檢查代碼規范的工具,尤其是 Jakarta 的很多項目,例如Maven、 Torque等。
2.1. CheckStyle是什么?
CheckStyle是SourceForge下的一個(gè)項目,提供了一個(gè)幫助JAVA開(kāi)發(fā)人員遵守某些編碼規范的工具。它能夠自動(dòng)化代碼規范檢查過(guò)程,從而使得開(kāi)發(fā)人員從這項重要,但是枯燥的任務(wù)中解脫出來(lái)[1]。
2.2. CheckStyle檢驗的主要內容
CheckStyle默認提供一下主要檢查內容:
·Javadoc注釋
·命名約定
·標題
·Import語(yǔ)句
·體積大小
·空白
·修飾符
·塊
·代碼問(wèn)題
·類(lèi)設計
·混合檢查(包活一些有用的比如非必須的System.out和printstackTrace)
從上面可以看出,CheckStyle提供了大部分功能都是對于代碼規范的檢查,而沒(méi)有提供象PMD和Jalopy那么多的增強代碼質(zhì)量和修改代碼的功能。但是,對于團隊開(kāi)發(fā),尤其是強調代碼規范的公司來(lái)說(shuō),它的功能已經(jīng)足夠強大。
2.3. CheckStyle的主要運行方式
目前,CheckStyle的版本是3.0,與以前的版本不同,它的配置文件是基于XML而非Properties文件。
它的3.0版本提供了兩種運行的方式:
·命令行工具
·ANT任務(wù)
同時(shí),CheckStyle目前有很多針對流行IDE的插件,例如Eclipse、IntelliJ IDEA、JBuilder等。但是,大部分都是基于2.4的版本,新版本的特性不支持,同時(shí)配置也較為復雜。
因為一般情況下,如果與開(kāi)發(fā)過(guò)程與環(huán)境集成起來(lái),編碼規范的檢查會(huì )更加有效,因此,作為ANT任務(wù)的運行方式使用的更加普遍。
在A(yíng)NT的build.xml文件中添加CheckStyle任務(wù)的步驟如下:
1. 將checkstyle-all-3.1.jar拷貝到項目的LIB目錄;
2. 建立配置文件;
3. 聲明CheckStyle任務(wù):
| <taskdef resource="checkstyletask.properties" classpath="${lib}/checkstyle-all-3.1.jar"/> |
4. 建立CheckStyle任務(wù):
| <target name="checkstyle"> <checkstyle config="${config}/sun_checks.xml"> <fileset dir="${src}" includes=" **/*.java" /> </checkstyle> </target> |
2.4. 定制CheckStyle
CheckStyle的執行基于XML配置文件,它的主要組成部分是:
·Module:整個(gè)配置文件就是一棵Module樹(shù)。根節點(diǎn)是Checker Module。
·Properties:它來(lái)決定一個(gè)Module如何進(jìn)行檢查。每個(gè)Module都有一個(gè)默認值,如果不滿(mǎn)足開(kāi)發(fā)需求,可以設定其它的值。
下面是一個(gè)示例:
| <module name="MethodLength"> <property name="max" value="60"/> </module> |
它表示,如果方法或者構造函數的長(cháng)度超過(guò)60行,CheckStyle就會(huì )報錯。而默認值是150行。
以下是一段CheckStyle對于Maven項目源文件的檢查報告:
| Method ‘createExpression‘ is not designed for extension - needs to be abstract, final or empty. 91 Unable to get class information for JellyException. 91 Line has trailing spaces. 93 Line has trailing spaces. 104 Method ‘evaluate‘ is not designed for extension - needs to be abstract, final or empty. 113 Parameter context should be final. 113 Line has trailing spaces. 130 Method ‘getExpressionText‘ is not designed for extension - needs to be abstract, final or empty. 131 Line has trailing spaces. 134 Line has trailing spaces. 135 Method ‘toString‘ is not designed for extension - needs to be abstract, final or empty. 137 Method ‘isSupportAntVariables‘ is not designed for extension - needs to be abstract, final or empty. 156 Method ‘setSupportAntVariables‘ is not designed for extension - needs to be abstract, final or empty. 168 Parameter supportAntVariables should be final. 168 ‘supportAntVariables‘ hides a field. 168 Method ‘isValidAntVariableName‘ is not designed for extension - needs to be abstract, final or empty. 183 Parameter text should be final. 183 |
一般情況下,與IDE集成在一起使用的時(shí)候,點(diǎn)擊出錯的條目,可以跳轉到相應的代碼。

