代碼檢查可以采用不同的形式。有些企業使用正式的同級評審(peer review),在該評審過程中,開發人員要為代碼提供同級評價,并提供改進意見;其他一些企業使用結對編程;還有一些人則考慮使用高級設計決策和推薦的代碼改進。有些團隊會在將代碼提交到版本控制存儲庫之前,讓其他開發人員用 “桌面檢查” 的形式審查他們的代碼。
不論企業采用哪種方式進行代碼檢查,有一件事是肯定的:它們幾乎都是手工過程。正如我多年所觀察到的,手工過程很容易出錯,如果工作緊張,就會忘記自己正在做什么。但是,軟件檢查不必總是手工完成;實際上,有一大堆開源工具和商業工具(我稱之為軟件檢查器),可以用它們很方便地對代碼進行靜態分析(這些工具也稱為靜態分析工具)。
使用軟件檢查器,代碼檢查可以通過 Ant 或 Maven 這樣的構建工具來自動完成。通過使用這種自動化,一些低級的源代碼細節(如編碼標準、復雜性和重復程度等)的處理成為了機器的職責。這種職責轉移通過將重點轉向更高級的開發方面(比如設計和長期維護問題)提高了人們手工檢查的效率。
![]() |
|
用軟件檢查器來解決問題
軟件檢查器有很多,范圍從復雜的商業工具到簡單的開源替代工具。但是,我發現其中三個特別有用,它們是 CheckStyle、CPD 和 JavaNCSS (請參閱 參考資料):
![]() |
|
檢查器樣式標準
我參與了幾家公司的委員會,花了很多時間來定義編碼標準。有一次,我們定義了幾乎沒人 遵守的 25 頁的編碼標準文檔。結果,我們的代碼審查非常痛苦,因為團隊要花時間來挑錯,看看開發人員是否使用了兩個空格規則(與四個空格規則相對),以及是否將參數聲明為 final
。如果把這些低級檢查工作交給軟件檢查器,我們會節省許多寶貴的時間。
使用自動的源代碼檢查工具(如 CheckStyle)可以提供執行可配置規則集的簡單途徑,規則集可以根據項目的編碼標準而定。此外,可以通過 CheckStyle 插件在 IDE 中運行 CheckStyle,CheckStyle 通過它的 Ant 任務或 Maven 插件直接集成到構建腳本中。CheckStyle 發現的所有規則偏離都會以報告的形式顯示,清楚地指出哪一個文件違規。除此之外,還可以將 Ant 和 Maven 配置成與 CheckStyle 相呼應,這樣,在違反規則時,構建工作就會失敗。
例如,清單 1 演示了 Ant 構建腳本的一個代碼段,它運行 CheckStyle 生成 HTML 報告。請注意 failOnViolation
屬性,在這里它被設為 false
。如果將該屬性設為 true
,則在發現任何 源代碼違規時,構建都會失敗。
|
在清單 1 中,config
被設置成 cs-rules.xml
,這表示將根據源代碼目錄(在 fileset dir
屬性中)以遞歸的方式運行規則文件。xslt
任務接受根據 formatter toFile
屬性生成的文件。該任務使用 XSL 文件 checkstyle.xsl 將清單 1 生成的 XML 轉換成一個可讀的 HTML 文件,XSL 文件 checkstyle.xsl 包含在 CheckStyle 安裝文件中。
清單 2 是 CheckStyle 規則文件的示例片段。CheckStyle 可以在代碼基上運行 120 多個規則。
|
每個 CheckStyle 規則都是一個模塊。例如,LineLength
模塊建立的規則是:所有行中的字符都不得超過 120 個字符,否則 CheckStyle 就生成錯誤。
可以用定制規則擴展 CheckStyle,所以也可以容易地實施編碼規則。而且,它是自動執行的!
圖 1 顯示了使用 Ant 生成的 CheckStyle 報告的一個示例,這是 清單 1 中所演示的 xslt
任務:
![]() |
|
用 CPD 進行重復性檢查
面向對象編程的一個主要目的是通過創建可以適應不同上下文的可重用對象來促進重用。但是,通常使用的是 “復制-粘貼” 編程,并將它偽裝成 “重用”。有時,出現這種情況是因為開發人員不知道有可重用的組件,而其他時候,則是因為提供了“快速修復”。所以,如果需要進行修改,則必須將更改應用到所有 副本和變體中(當然,如果沒有工具很難完成)。這種手工方式帶來了維護困難并很容易導致遺漏,甚至會帶來缺陷。
CPD 是流行的開源靜態分析工具 PMD 的一部分,它報告代碼基中重復行的數量。此外,CPD 的標志閾值是可配置的,這意味著可以修改 CPD 建議的重復行數。例如,如果將閾值設置成 100 個標志,CPD 就會在至少 重復了 100 個標志的時候顯示一個實例。不過請記住,源代碼總是會包含一些重復部分;CPD 只是為團隊提供了一種調查值得考慮的代碼重復 領域的手段,在這個領域內,可以采取糾正措施,例如有目的的重構。
清單 3 演示將 CPD 用于 Ant 的實際使用。CPD 任務需要的第一個選項是 minimumTokenCount
屬性,該屬性用于指定要比較的標志的數量(最小值是一個標志)。另外,可以設置 CPD 忽略某些代碼選項,例如標識符和標量。在這個示例中,Ant fileset
類型指定了 CPD 文件應該分析哪些文件,以及應該忽略哪些文件。
|
如圖 2 所示,cpd.xml 是用清單 3 中的 outputFile
屬性產生的輸出。以后我還將向 CPD 添加 XSL,以生成 HTML 報告。
除了最明顯的復制-粘貼違規之外,在所有地方手工查找重復代碼也非常具有挑戰性。但是,使用諸如 CPD 之類的工具,就可以迅速找出重復代碼,然后對此進行改進。
![]() |
|
用 JavaNCSS 檢查復雜性
許多研究已經證實,隨著方法中路徑數量的增加,理解和維護同一方法的難度也隨之增加。結果,代碼越難以理解和維護,就越容易出現缺陷。
JavaNCSS 是一個免費工具,提供了不同的代碼測量,例如非注釋性源代碼語句(或代碼行)的數量、所有分析過的方法的圈復雜度量值(cyclomatic complexity number)。清單 4 演示了 JavaNCSS 的使用,可以看到,它不是很難使用。只要將 JavaNCSS 指向一個包含源代碼的目錄,讓它自己處理就行了!
|
像多數軟件檢查器一樣,這里生成了一個 XML 文件,可以通過 XSLT 很容易地將它轉換成一個 HTML 報告,就像圖 3 中所做的那樣:
理解應用程序代碼復雜性可沒有那么容易。實際上,在某些情況下,復雜性的值可能會令人誤解。例如,有些工具為 switch
語句提供較高的值。但是我發現,使用 JavaNCSS 這樣的工具,有助于降低高復雜性的領域,最終提高代碼的可理解性和可維護性。
![]() ![]() |
![]()
|
對每個更改都進行檢查,將缺陷控制在限度內
每當團隊成員向版本控制存儲庫提交更改時,代碼就會發生改變。但它是怎么改變的呢?被修改的代碼是受到復制-粘貼工作的影響嗎?復雜性會增加嗎?了解這些的惟一方式就是在每次簽入 時都運行軟件檢查器。此外,在持續的基礎上接受目前為止討論過的每種風險的反饋,這是一種自動 讓代碼基進行健康檢查的一種可靠方式!
Cruise 與 CI
CruiseControl 是 Java™ 社區使用最廣的開源 CI 工具之一。這個工具被配置成在后臺運行,用于檢索版本控制存儲庫,例如 CVS。在發現源代碼更改時(例如,有人簽入了代碼),CruiseControl 就會執行源代碼簽出,并運行預定義的構建腳本。
所以,只要 版本控制存儲庫中發生了變化,團隊就可以運行 CheckStyle、CPD 和 JavaNCSS 這樣的軟件檢查器。這種能力允許團隊長時間地進行監視和執行檢查,通過使用許多 CI 工具,團隊可以使用報告、電子郵件甚至使用 Ambient Orb 這樣的設備生成報告(參見 圖 5)。
清單 5 演示了使用 CruiseControl 的配置文件(通常名為 config.xml)在 CruiseControl 控制板上顯示 CheckStyle 報告的結果。其他軟件檢查器使用類似的語法將結果合并到 CruiseControl 儀表板中。
|
圖 4 顯示了用 CruiseControl 和 CheckStyle 生成的示例報告。請注意,可以配置 CruiseControl,顯示其他工具(像 CPD 和 JavaNCSS)的報告,而且通過對每個源代碼更改 都運行這些報告,團隊可以實時地積極改進代碼,不必等到周期末期。
Ambient 反饋
對于使用 CI 工具持續運行軟件檢查器而言,最酷的事就是團隊有了無數任意使用的通知機制。有時,構建可能并沒有失敗,但是有些事 的變化要求早些而不是晚些采取糾正行動。例如,實際上可以很容易地配置一個設備(就像 Ambient Orb),在代碼復雜度有所上升時,或者在違反一定數量的代碼標準時,使用該設備改變顏色。
清單 6 使用了 Ambient Orb Ant 任務和 Ruby 腳本,在 20 個以上的類超過 300 個源代碼行(SLOC)時,就改變 Orb 的顏色和動畫。在這個示例中,我選擇在類滿足條件時將 orb 的顏色改成 magenta
,將動畫改成 crescendo
。
|
圖 5 演示了代碼基中有太多較大的類時,orb 看起來的樣子:
使用這種 Ambient Orb 通知方法,就不會收到無窮盡的電子郵件,只要看一眼 SLOC Threshold Orb,就可以快速了解我有多少個大型類,它們提醒我要重定向重構工作。當然,組合 ambient orb 與軟件監視器(稍帶些創意)也會創造無窮的可能性!
![]() ![]() |
![]()
|
在合適的時候自動化
請記住,可以選擇許多不同的軟件檢查器。雖然這里分析了三個我喜歡的軟件檢查器,但我還是被 JDepend、PMD 和 FindBugs 工具(后兩個檢查器在 developerWorks 上已詳細討論過)所打動。一旦開始持續檢查過程,插入一個新的檢查器只是幾分鐘的事而已。
持續檢查不會也不應該消除手工軟件檢查;但是,通過對版本控制存儲庫中的每個更改都運行一套自動檢查工具,將要執行的 這些手工檢查會帶來更高的生產率和效率。而且,持續檢查帶來的額外好處有:風險在每一步上都可以降低,而不必等到項目后期。
下一個月,我將深入研究一些更有趣的持續集成工具,例如 CruiseControl、Luntbuild 和 Continuum,并讓您確定哪一個工具最適合您。自動化從未 這么有趣過!
![]() ![]() |
![]()
|
描述 | 名字 | 大小 | 下載方法 |
---|---|---|---|
Software Inspection examples in Ant | j-ap08016.zip | 2MB | HTTP |