1. 程式人生 > >敏捷開發中高質量 Java 程式碼開發實踐

敏捷開發中高質量 Java 程式碼開發實踐

本文將介紹在敏捷開發過程中如何通過採取一系列的步驟來保證和提高整個專案的程式碼質量,闡述了每一步可以利用的工具和最佳實踐,從而使開發過程更加規範化,成就高質量的程式碼。

概述

Java 專案開發過程中,由於開發人員的經驗、程式碼風格各不相同,以及缺乏統一的標準和管理流程,往往導致整個專案的程式碼質量較差,難於維護,需要較大的測試投入和週期等問題。這些問題在一個專案組初建、需求和設計均具有不完全可預期性和完備性的全新專案中將尤為突出。本文將結合敏捷開發週期短,變化快等特點,介紹如何通過在開發過程中採取一系列步驟來保證和提高整個開發團隊的程式碼質量,並闡述了每一步可以利用的工具和最佳實踐,從而使開發過程更加規範化,成就高質量的程式碼,減少測試的投入,並促進整個團隊的技能提高,最終提高開發效率和質量。

如圖 1 所示,敏捷開發過程經歷需求調研,用例分析和用例分解,進入開發迭代階段。在每個迭代過程中,可以採用以下五個步驟來保證和提高整個專案的程式碼質量:統一編碼規範、程式碼樣式;靜態程式碼分析(static code review);單元測試;持續整合;程式碼評審和重構(Review & Refactor)。下文將針對每個步驟和其所使用的工具、方法進行詳細描述。

圖 1. 敏捷開發中的 Java 程式碼質量保證步驟

步驟一:統一編碼規範、程式碼樣式

規範統一的編碼會增加專案程式碼的可讀性和可維護性,但實際情況往往是專案組內的 Java 程式碼開發人員的編碼風格常常各不相同,這可能是由於不同的經驗習慣或者缺乏編碼規範方面的學習造成的。這樣一來,其他專案成員或者維護人員在閱讀專案程式碼時就需要花費更多的時間來理解程式碼作者的意圖,所以制定並採取統一的編碼規範就顯得很重要。編碼規範主要應包含以下幾個方面:

1.一般規則和格式規範。例如程式碼縮排、程式塊規範、每行最大程式碼長度等。

2.命名規則。例如包名、類名、變數、方法、介面、引數等命名規範

3.文件規範。例如類檔案頭宣告、類註釋、成員變數和方法註釋等規範。

4.程式設計規範。例如異常、併發、多執行緒等方面的處理方式。

5.其他規範。例如日誌格式、屬性檔案格式,返回值和訊息格式。

專案的編碼規範可以參考已有的一些 Java 程式設計規範書籍和其他相關資料並結合專案的本身來制定,可供參考的書籍有《 Java 程式設計風格》(英文書名為:The Elements of Java Style)。編碼規範要形成文件,而且要簡潔明瞭,並組織專案成員一起學習,確保所有成員正確理解所有條目。

一旦編碼規範確定,就可以利用 Eclipse 自身提供的功能來控制程式碼樣式和格式。具體做法是,點選 Eclipse 的 Windows -> Preference 選單項,在開啟的 Preferences 對話方塊的左側欄中找到 Java 節點下的子項 Code Style(如圖 2),該項和它的子項允許您對 Java 程式碼的樣式進行控制。

圖 2. Eclipse 程式碼樣式設定視窗

例如,為了使用自動格式化工具,可以在 Eclipse 提供的預設程式碼格式配置的基礎上建立自定義的格式。在 Formatter 面板中,點選 New,輸入新的名字並選擇一個預設的配置作為初始化格式,如圖 3 所示。

圖 3. 建立新的程式碼格式配置

單擊 OK 後就可以在新開啟的視窗中進行修改定製自己需要的格式。如圖 4 所示。

圖 4. 建立新的程式碼格式配置

修改完成後點選 Apply 儲存所作修改。同時可以點選 Export 將當前的格式定義匯出成一個 XML 檔案,這樣專案組的其他成員就可以很方便通過點選圖 3 中的 Import 按鈕來匯入該 XML 檔案來使用同一個程式碼格式定義。

這樣每次在提交程式碼到版本控制伺服器前就可以通過 Eclipse 介面裡的 Source->Format 選單來對程式碼進行格式化,從而使整個專案的程式碼具有相同的格式。同樣可以通過對 Code Style 下的其他專案進行設定來幫助對 Java 程式碼的樣式進行控制。將所有這些樣式檔案匯出成 XML 檔案後,同編碼規範一起歸檔,供所有專案成員使用。

步驟二:靜態程式碼分析

在完成原始碼的開發以後,下面要進行的工作就是審視和測試程式碼。除了通過執行測試程式碼來檢查功能之外,還能利用一些靜態分析工具來快速、直接地提高程式碼質量。靜態程式碼分析工具並不需要執行程式碼,可以直接對 Java 檔案和 Class 檔案進行分析,通過一些檢查條件的設定,快速找到程式碼中的錯誤和潛在缺陷。現在的靜態分析工具很多,有 FindBugs、PMD、IBM Rational Tool,等等。在這裡,選擇 FindBugs 作為靜態程式碼分析工具。FindBugs 可以和日常開發工具 Eclipse 進行整合,在開發過程中,就可以方便的開始靜態程式碼的檢查。通過檢查 Class 檔案或者 JAR 檔案,將位元組碼和一組缺陷模式進行對比,來發現可能存在的程式碼問題。在 Eclipse 的開發環境中,用外掛安裝的方式安裝了 Findbugs 後,在 Eclipse 的配置選項中就會多出來 FindBugs 的配置選項。可以對自己的專案進行配置,選擇需要的 Detector 檢查程式碼。

圖 5. FindBugs 的配置選項

設定好自己的規則後,在需要檢查的程式碼資料夾上點選右鍵,就可以啟動 FindBugs 檢查。程式碼可以是一個專案,也可以只是幾個檔案。

圖 6. 執行 FindBugs

檢查完畢後,會出現 FindBugs 檢視,把所有檢查的結果根據錯誤分組展示。點選結果裡面的每一個錯誤,會自動開啟對應的程式碼。當根據規則改正了所有的錯誤,或者說潛在錯誤,這些程式碼也就通過了靜態程式碼檢查。FindBugs 的檢查結果可以是 XML 檔案,也可以是文字檔案,便於專案的整合管理和檢查儲存。

圖 7. FindBugs 檢查結果

步驟三:單元測試

單元測試用例設計和評審

單元測試是軟體開發過程中重要的質量保證環節,在此環節中,設計和評審對於保證整個單元測試過程的完整性和有效性來說十分重要。設計階段需要具體考慮要對哪些程式碼單元進行測試,被測單元之間的關係,測試策略,以及單元測試用例設計等,並最終輸出《單元測試用例設計》文件,用來指導具體的單元測試執行。在用例設計中,通過對程式碼單元輸入和期待輸出的定義來保證該單元的功能正確性,邊界值的測試和異常測試非常重要。同時也配合測試用例和功能塊的匹配方法來衡量用例設計的完整性。

在用例設計完成之後,下一步的工作就是進行測試用例的評審。個人的理解和經驗始終是有限的,用例評審可以借集體之力,對用例設計進入查漏補缺,進一步保證測試用例的有效性。由於單元測試屬於白盒測試範疇,它主要通過對程式碼的邏輯結構進行分析來設計測試用例,因此,評審員的選擇最好以理解程式碼邏輯結構為前提,如果評審員來自相關模組,還能夠有效的發現模組相關性和依賴性所帶來的問題。

模擬物件技術

在實際專案中,開發人員自己的程式碼往往需要和其他的程式碼模組或系統進行互動,但在測試的過程中,這些需要被呼叫的真實物件常常很難被例項化,或者這些物件在某些情況下無法被用來測試,例如,真實物件的行為無法預測,真實物件的行為難以觸發,或者真實物件的執行速度很慢。這時候,就需要使用模擬物件技術(Mock),利用一個模擬物件來模擬我們的程式碼所依賴的真實物件,來幫助完成測試,提高測試覆蓋率,從而提高程式碼質量。模擬物件技術利用了在面向介面的程式設計中,由於程式碼直接對介面進行呼叫,所以程式碼並不知道引用的是真實物件還是模擬物件,這樣就可以順利的完成對程式碼的測試。

模擬技術有很多種,如 jMock,EasyMock,Mockito,PowerMock 等等。其中 Mockito 消除了對期望行為的需求,避免了這些程式碼的大量初始化。

圖 8. Mockito 示例

在模擬物件過程中,先模擬一個需要呼叫的 List 物件 LinkedList,再設定這個物件的行為,當呼叫 get(0) 的時候,返回”first”。這樣,測試程式碼就可以利用這個物件來測試我們的功能程式碼,需要呼叫和返回值的時候,可以順利的得到模擬物件的返回值。也需要對模擬物件進行錯誤情況的模擬,保證程式碼對錯誤的處理的正確性。

測試覆蓋率分析

為了衡量單元測試的質量和覆蓋的範圍,需要對單元測試的程式碼進行測試覆蓋分析。常用的衡量測試覆蓋率的指標主要有語句覆蓋率、分支覆蓋率、路徑覆蓋率、條件覆蓋率和方法覆蓋率等。具體採用哪些指標可以根據專案的實際情況來定,以避免因過高的指標增加了程式碼開發人員的工作量而影響了專案整體的進度。

EMMA 是一款比較流行的開源 Java 測試覆蓋率分析工具,支援類、方法、程式碼行、基本程式碼塊等多種型別的測試覆蓋率分析,支援將覆蓋率分析結果匯出為多種格式的報告,並採用多種顏色來高亮顯示不同的覆蓋率狀態。EclEmma 是一款基於 EMMA 的 Eclipse 外掛,方便在 Eclipse IDE 中進行測試覆蓋率分析。如圖 9,在測試用例寫好後,可以在右鍵點選測試類,選擇 Coverage As -> JUnit Test.

圖 9. 執行測試覆蓋分析

單元測試跑完後,Coverage檢視中會顯示所選擇的測試的覆蓋率。雙擊開啟某一具體的類後,可以看到高亮顯示的覆蓋分析結果,如圖 10 所示。紅色代表測試沒有覆蓋到該行,黃色表示部分覆蓋,綠色的行表示該行在本次測試中被覆蓋到。

圖 10. 檢視測試覆蓋分析結果

在 Coverage 檢視中可以通過點選滑鼠右鍵將測試覆蓋分析的結果匯出成需要的格式,例如 HTML。

圖 11. 匯出測試覆蓋分析結果

圖 12 顯示了匯出的 report。

圖 12. 測試覆蓋分析報告

為了保證單元測試的有效性和質量,可以規定一個測試覆蓋率的下限,例如所有的包和類的覆蓋率必須達到 80% 以上。不過值得注意的是,不要單純追求高覆蓋率,要同時注意測試用例的質量,如果測試用例本身就寫的有錯誤,那麼即使測試覆蓋率很高也沒有意義。

步驟四:持續整合

持續整合(Continuous Integration)是利用一系列的工具,方法和規則,做到快速的構建開發程式碼,自動的測試化,來提高開發程式碼的效率和質量。利用自動構建工具,隨時都能把提交的程式碼構建出來,提供一個可以測試使用的版本,讓使用者和開發人員同時看到相同的功能,儘早的發現問題和錯誤,也可以儘快的得到測試人員和使用者的反饋。

要做到持續整合,就要利用一系列工具,把開發過程中的重複工作自動化。搭建自動的構建伺服器,自動的進行單元測試和釋出新版本,一個整合的伺服器可以提供構建過程的結果報告,自動通知開發人員構建結果,並且儲存歷史資料。IBM Rational Team Concert (RTC) 可以提供工作任務的管理,專案計劃的安排,程式碼版本管理控制,自動構建可用版本,生成構建結果報告。這些過程構成了專案的持續整合過程,其中,版本的自動構建和程式碼的自動單元測試是持續整合的關鍵過程,RTC 在這些過程上提供了有力的支援。

自動構建

RTC 提供了 build engine 來負責構建 build,首選,啟動 build engine,並和 RTC 伺服器建立了連線。再建立專案的 build 定義。在這個定義中,需要設定編譯哪些模組的程式碼,需要跳動哪個 ANT 檔案來啟動編譯,和一些編譯過程中的引數的設定。當這些都準備好了,編譯對於專案而言,就變成一個簡單的事情。

可以看到,通過在 build 定義上,點選請求構建,就可以觸發一次構建過程。選擇需要的構建引數,這個過程就會在後臺執行。每一個開發人員,做了稍許的程式碼改變和提交,都可以觸發新的構建過程,來保證我們程式碼的有效性。申請一個新的構建的過程如圖 13、圖 14 所示。

圖 13. 申請一個新的構建

圖 14. 構建申請介面

當構建結束後。RTC 伺服器會提供構建結果報告。開發人員可以查詢到這次構建的詳細資訊。

圖 15. 構建結果

整個開發過程中,構建版本的過程應該是無數次的,通過每次構建,都可以得到當時程式碼的編譯情況,並且可以得到一個可執行的軟體版本。在構建定義上,RTC 支援設定構建計劃。定時自動的觸發一次構建。

圖 16. 構建定義

自動單元測試

構建可以自動了,重點提高程式碼質量的單元測試呢?如果每一天的程式碼,每一個版本的程式碼,都已經通過了我們的單元測試,這樣我們就能對程式碼的質量有了基本的保證。在構建指令碼的自動呼叫過程中,通過 ANT 的指令碼,可以加上 JUnit,EMMA,FindBugs 的 ANT 指令碼呼叫,每一次的構建,都可以把這些檢查工作自動的進行一遍測試。這些測試都要生成測試結果報告, RTC 不能提供這些報告的展示,就可以利用 Hudson 這個開源工具,整合測試報告來方便查閱。

圖 17. 自動測試報告

步驟五:程式碼評審和重構

程式碼評審(Code Review)是 Java 專案開發過程中的一個重要步驟,程式碼評審可以幫助發現靜態程式碼分析過程中無法發現的一些問題,例如程式碼的編寫是否符合編碼規範,程式碼在邏輯上或者功能上是否存在錯誤,程式碼在執行效率和效能上是否有需要改進的地方,程式碼的註釋是否完整正確,程式碼是否存在冗餘和重複。程式碼評審還可以幫助新進入專案組的成員快速學習和了解專案,促進經驗分享,同時也能保證專案成員的良好溝通。程式碼評審主要包括兩種形式,同級評審(Peer Review)和小組評審(Group Review)。同級評審主要指專案成員間的互相評審,小組評審是指通過召開評審會議,專案成員一起對專案程式碼進行評審。

為了提高程式碼評審的有效性和效率,可以藉助一些外部工具,比較常用的程式碼評審工具有 Jupiter 和 Code Striker。Jupiter 是一款開源的 Eclipse 外掛,允許成員將評審意見定位到真實程式碼的具體行,由於程式碼評審的結果以 XML 檔案的形式儲存,所以可以把結果提交到版本管理伺服器進行共享。圖 18 顯示了使用 Jupiter 進行程式碼評審的介面。

圖 18. Jupiter 程式碼評審介面

在程式碼評審任務建立後,Jupiter 將程式碼評審分成三個階段,個人評審階段 (Individual Phase)、團隊評審階段(Team Phase)和問題修復階段(Rework Phase)。在個人評審階段,評審成員將發現的程式碼問題或者缺陷記錄下來,每個問題都會作為一個記錄儲存在評審表格中。在團隊評審階段,團隊的全部或者部分成員會一起對個人評審階段發現的問題進行定性,如果問題確實存在,就將該問題分配給某個成員去解決,並在 Jupiter 中將該問題設定成相應的狀態。在問題修復階段,團隊成員會修復屬於自己的問題,並將相應的記錄設定成已解決等正確的狀態。

Codestriker 是一款基於 Web 的常用程式碼評審工具,對程式碼的評審可以針對某一具體行,也可以針對整個程式碼檔案,評審意見會被儲存在資料庫中。評審人員可以同時看到其他人的評論,程式碼作者也可以針對某一具體的評論回覆。Codestriker 支援郵件通知,還可以同版本控制伺服器進行整合,以跟蹤和顯示檔案內容的改變。圖 19 顯示了 Codestriker 的介面。

圖 19. Codestriker 報告介面

在實踐中對所有程式碼進行小組評審會比較費時,所以可以根據實際情況來挑選一些核心程式碼進行小組評審,或者在專案的前期安排較多的小組評審,等專案組的成員對程式碼評審的標準和要求有較好的理解,進行程式碼評審的經驗提高後,就可以逐漸減少小組評審的次數,從而達到大部分程式碼即使只進行同級評審也能保證很好的質量。

通過程式碼評審發現的問題要通過程式碼重構及時解決掉,較小的不涉及多人程式碼的重構可以由專案成員自己藉助 Eclipse 的重構功能完成,不同專案成員寫的實現相同功能的不同程式碼要通過討論整合成公共的類或者方法。比較複雜的或者比較高層次的重構工作,例如整個專案層面的程式碼組織形式的改變需要由整個專案組共同討論完成。

結論

軟體開發沒有一成不變、萬能通用的流程和方法,希望大家能從本文得到啟發和收益,結合您的實際專案特點,實踐以上步驟和方法,並加以完善和改進,共同打造高效高質量的 Java 程式碼,為您的專案成功奠定堅實的基礎。

http://www.uml.org.cn/codeNorms/201504214.asp