敏捷開發的理念已經流行了很長的時間,在敏捷開發中的開發迭代階段中,我們可以通過五個步驟,來有效提高整個項目的代碼品質。
Java項目開發過程中,由於開發人員的經驗、Java代碼編寫習慣,以及缺乏統一的標準和管理流程,往往導致整個項目的代碼品質較差,難於維 護,需要較大的測試投入和周期等問題。這些問題在一個項目組初建、需求和設計均具有不完全可預期性和完備性的全新項目中將尤為突出。
1所示,敏捷開發過程經曆需求調研,用例分析和用例分解,進入開發迭代階段。在每個迭代過程中,可以採用以下步驟來保證和提高整個項目的代 碼品質:統一編碼規範、代碼樣式;靜態程式碼分析(staticcodereview);單元測試;持續整合;程式碼檢閱和重構 (Review&Refactor)。下文將針對每個步驟和其所使用的工具、方法進行詳細描述。
圖1.敏捷開發中的Java代碼品質保證步驟
步驟一:統一編碼規範、代碼樣式
規範統一的編碼會增加項目代碼的可讀性和可維護性,但實際情況往往是項目組內的Java代碼開發人員的編碼風格常常各不相同,這可能是由於不同 的經驗習慣或者缺乏編碼規範方面的學習造成的。這樣一來,其他項目成員或者維護人員在閱讀項目代碼時就需要花費更多的時間來理解代碼作者的意圖,所以制定 並採取統一的編碼規範就顯得很重要。編碼規範主要應包含以下幾個方面:
◆一般規則和格式規範。例如代碼縮排、程式塊規範、每行最大代碼長度等。
◆命名規則。例如包名、類名、變數、方法、介面、參數等命名規範
◆文檔規範。例如類檔案頭聲明、類注釋、成員變數和方法注釋等規範。
◆編程規範。例如異常、並發、多線程等方面的處理方式。
◆其他規範。例如日誌格式、屬性檔案格式,傳回值和訊息格式。
項目的編碼規範可以參考已有的一些Java編程規範書籍和其他相關資料並結合項目的本身來制定,可供參考的書籍有《Java編程風格》(英文書 名為:TheElementsofJavaStyle)。編碼規範要形成文檔,而且要簡潔明了,並組織項目成員一起學習,確保所有成員正確理解所有條目。
一旦編碼規範確定,就可以利用Eclipse自身提供的功能來控制碼樣式和格式。具體做法是,點擊Eclipse的 Windows->Preference功能表項目,在開啟的Preferences對話方塊的左側欄中找到Java節點下的子項CodeStyle(2),該項 和它的子項允許您對Java代碼的樣式進行控制。
圖2.Eclipse代碼樣式設定視窗
例如,為了使用自動格式化工具,可以在Eclipse提供的預設代碼格式配置的基礎上建立自訂的格式。在Formatter面板中,點擊 New,輸入新的名字並選擇一個預設的配置作為初始化格式,3所示。
圖3.建立新的代碼格式配置
單擊OK後就可以在新開啟的視窗中進行修改定製自己需要的格式。4所示。
圖4.建立新的代碼格式配置
修改完成後點擊Apply儲存所作修改。同時可以點擊Export將當前的格式定義匯出成一個XML檔案,這樣項目組的其他成員就可以很方便通 過點擊圖3中的Import按鈕來匯入該XML檔案來使用同一個代碼格式定義。
這樣每次在提交代碼到版本控制伺服器前就可以通過Eclipse介面裡的Source->Format菜單來對代碼進行格式化,從而 使整個項目的代碼具有相同的格式。同樣可以通過對CodeStyle下的其他項目進行設定來協助對Java代碼的樣式進行控制。將所有這些樣式檔案匯出成 XML檔案後,同編碼規範一起歸檔,供所有項目成員使用。
步驟二:靜態程式碼分析
在完成原始碼的開發以後,下面要進行的工作就是審視和測試代碼。除了通過運行測試代碼來檢查功能之外,還能利用一些靜態分析工具來快速、直接地 提高代碼品質。靜態程式碼分析工具並不需要運行代碼,可以直接對Java檔案和Class檔案進行分析,通過一些檢查條件的設定,快速找到代碼中的錯誤和潛 在缺陷。現在的靜態分析工具很多,有FindBugs、PMD、IBMRationalTool,等等。在這裡,選擇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外掛程式,方便在 EclipseIDE中進行測試覆蓋率分析。9,在測試案例寫好後,可以在右鍵點擊測試類別,選擇CoverageAs->JUnitTest。
圖9.運行測試覆蓋分析
單元測試跑完後,Coverage視圖中會顯示所選擇的測試的覆蓋率。雙擊開啟某一具體的類後,可以看到高亮顯示的覆蓋分析結果,10所 示。紅色代表測試沒有覆蓋到該行,黃色表示部分覆蓋,綠色的行表示該行在本次測試中被覆蓋到。
圖10.查看測試覆蓋分析結果
在Coverage視圖中可以通過點擊滑鼠右鍵將測試覆蓋分析的結果匯出成需要的格式,例如HTML。
圖11.匯出測試覆蓋分析結果
圖12顯示了匯出的report。
圖12.測試覆蓋分析報告
為了保證單元測試的有效性和品質,可以規定一個測試覆蓋率的下限,例如所有的包和類的覆蓋率必須達到80%以上。不過值得注意的是,不要單純追 求高覆蓋率,要同時注意測試案例的品質,如果測試案例本身就寫的有錯誤,那麼即使測試覆蓋率很高也沒有意義。
步驟四:持續整合
持續整合(ContinuousIntegration)是利用一系列的工具,方法和規則,做到快速的構建開發代碼,自動的測試化,來提高開發 代碼的效率和品質。利用自動構建工具,隨時都能把提交的代碼構建出來,提供一個可以測試使用的版本,讓使用者和開發人員同時看到相同的功能,儘早的發現問題 和錯誤,也可以儘快的得到測試人員和使用者的反饋。
要做到持續整合,就要利用一系列工具,把開發過程中的重複工作自動化。搭建自動的構建伺服器, 自動的進行單元測試和發布新版本,一個整合的伺服器可以提供構建過程的結果報告,自動通知開發人員構建結果,並且儲存曆史資料。 IBMRationalTeamConcert(RTC)可以提供工作任務的管理,專案計劃的安排,代碼版本管理控制,自動構建可用版本,產生構建結果報 告。這些過程構成了項目的持續整合過程,其中,版本的自動構建和代碼的自動單元測試是持續整合的關鍵過程,RTC在這些過程上提供了有力的支援。
自動構建
RTC提供了buildengine來負責構建build,首選,啟動buildengine,並和RTC伺服器建立了串連。再建立項目的 build定義。在這個定義中,需要設定編譯哪些模組的代碼,需要跳動哪個ANT檔案來啟動編譯,和一些編譯過程中的參數的設 定。當這些都準備好了,編譯對於項目而言,就變成一個簡單的事情。
可以看到,通過在build定義上,點擊請求構建,就可以觸發一次構建過程。選擇需要的構建參數,這個過程就會在後台運行。每一個開發人員,做 了稍許的代碼改變和提交,都可以觸發新的構建過程,來保證我們代碼的有效性。申請一個新的構建的過程13、圖14所示。
圖13.申請一個新的構建
圖14.構建申請介面
當構建結束後。RTC伺服器會提供構建結果報告。開發人員可以查詢到這次構建的詳細資料。
圖15.構建結果
整個開發過程中,構建版本的過程應該是無數次的,通過每次構建,都可以得到當時代碼的編譯情況,並且可以得到一個可啟動並執行軟體版本。在構建定義 上,RTC支援設定構建計劃。定時自動的觸發一次構建。
圖16.構建定義
自動單元測試
構建可以自動了,重點提高代碼品質的單元測試呢?如果每一天的代碼,每一個版本的代碼,都已經通過了我們的單元測試,這樣我們就能對代碼的品質 有了基本的保證。在構建指令碼的自動調用過程中,通過ANT的指令碼,可以加上JUnit,EMMA,FindBugs的ANT指令碼調用,每一次的構建,都可 以把這些檢查工作自動的進行一遍測試。這些測試都要產生測試結果報告,RTC不能提供這些報告的展示,就可以利用Hudson這個開源工具,整合測試報告 來方便查閱。
圖17.自動化的測試報告
步驟五:程式碼檢閱和重構
程式碼檢閱(CodeReview)是Java項目開發過程中的一個重要步驟,程式碼檢閱可以協助發現靜態程式碼分析過程中無法發現的一些問題,例如 代碼的編寫是否符合編碼規範,代碼在邏輯上或者功能上是否存在錯誤,代碼在執行效率和效能上是否有需要改進的地方,代碼的注釋是否完整正確,代碼是否存在 冗餘和重複。程式碼檢閱還可以協助新進入項目組的成員快速學習和瞭解項目,促進經驗分享,同時也能保證項目成員的良好溝通。程式碼檢閱主要包括兩種形式,同級 評審(PeerReview)和小組評審(GroupReview)。同儕審查主要指項目成員間的互相評審,小組評審是指通過召開評審會議,項目成員一起 對項目代碼進行評審。
為了提高程式碼檢閱的有效性和效率,可以藉助一些外部工具,比較常用的程式碼檢閱工具有Jupiter和CodeStriker。Jupiter是 一款開源的Eclipse外掛程式,允許成員將評審意見定位到真實代碼的具體行,由於程式碼檢閱的結果以XML檔案的形式儲存,所以可以把結果提交到版本管理伺服器進 行共用。圖18顯示了使用Jupiter進行程式碼檢閱的介面。
圖18.Jupiter程式碼檢閱介面
在程式碼檢閱任務建立後,Jupiter將程式碼檢閱分成三個階段,個人評審階段(IndividualPhase)、團隊評審階段 (TeamPhase)和問題修複階段(ReworkPhase)。在個人評審階段,評審成員將發現的代碼問題或者缺陷記錄下來,每個問題都會作為一個記 錄儲存在評審表格中。在團隊評審階段,團隊的全部或者部分成員會一起對個人評審階段發現的問題進行定性,如果問題確實存在,就將該問題分配給某個成員去解 決,並在Jupiter中將該問題設定成相應的狀態。在問題修複階段,團隊成員會修複屬於自己的問題,並將相應的記錄設定成已解決等正確的狀態。
Codestriker是一款基於Web的常用程式碼檢閱工具,對代碼的評審可以針對某一具體行,也可以針對整個代碼檔案,評審意見會被儲存在資料庫中。評審人員可以同時看到其他人的評論,代碼作者也可以針對某一具體的評 論回複。Codestriker支援郵件通知,還可以同版本控制伺服器進行整合,以跟蹤和顯示檔案內容的改變。圖19顯示了Codestriker的界 面。
圖19.Codestriker報告介面
在實踐中對所有代碼進行小組評審會比較費時,所以可以根據實際情況來挑選一些核心代碼進行小組評審,或者在項目的前期安排較多的小組評審,等項 目組的成員對程式碼檢閱的標準和要求有較好的理解,進行程式碼檢閱的經驗提高後,就可以逐漸減少小組評審的次數,從而達到大部分代碼即使只進行同儕審查也能保 證很好的品質。
通過程式碼檢閱發現的問題要通過代碼重構及時解決掉,較小的不涉及多人代碼的重構可以由項目成員自己藉助Eclipse的重構功能完成,不同項目 成員寫的實現相同功能的不同代碼要通過討論整合成公用的類或者方法。比較複雜的或者比較高層次的重構工作,例如整個項目層面的程式碼群組織形式的改變需要由整 個項目組共同討論完成。
結論
軟體開發沒有一成不變、萬能通用的流程和方法,希望大家能從本文得到啟發和收益,結合您的實際項目特點,實踐以上步驟和方法,並加以完善和改 進,共同打造高效高品質的Java代碼,為您的項目成功奠定堅實的基礎。
【 發表評論 75條 】