定義軟體度量與程式碼分析。介紹常見的度量指標。自動產生度量數據。
書名:軟體構築美學
作者:Kyle Baley,Donald Belcham
譯者:蔡煥麟,張簡才祿
發行公司:悅知文化,精誠資訊股份有限公司
度量不是為了直接處理特定問題。
它們的主要功用,是讓你能夠發現由其他現象所導致的問題。
何謂軟體度量與程式碼分析?
軟體度量就是一些測量項目,像是程式碼行數、類別總數、繼承深度等等。
運用這些度量來分析你的程式碼。
程式碼分析分為兩種:靜態與動態。
靜態程式碼分析
在程式未執行的狀態下,對程式碼進行分析。
常見的有:程式碼行數、類別耦合度,以及循環複雜度。
動態程式碼分析
程式執行時所進行的分析。
常見的有:程式碼涵蓋範圍,應用程式執行期間所走過的程式碼的比例。
另一種:分析記憶體的使用率,以及檢查記憶體洩漏的問題。
為什麼需要程式碼度量?
答案是:你並不需要,或者你也許不需要。
即時沒有程式碼分析,你的專案也可能活得好好的。
但可以讓你有條理的整理程式碼。
比如說,藉由分析統計的結果,你可以看到哪些類別的耦合度最高,然後也許你會實作依賴注入,來降低耦合度。
利用瑕疵報告來分析程式碼,從趨勢中研判哪些地方需要重構。
用靜態程式碼分析來強制架構方面的設計限制。
常用的度量指標
程式碼涵蓋範圍(code coverage) 循環複雜度(cyclomatic complexity) 類別耦合度(class coupling)
程式碼涵蓋範圍
監控程式碼執行的過程,顯示剛才有執行到(或有涵蓋到)的程式碼,以及最重要的是哪些程式碼沒有執行到。
程式碼涵蓋範圍的真正威力所在,是當它和單元測試或整合測試一起搭配運用的時候。
在測試結束時,程式碼涵蓋工具會自動產生一份報告。
單單了解程式碼的執行狀況,就能夠讓你提高對程式碼的信心。
循環複雜度
用來測量程式碼的複雜度,讓我們了解應用程式內部結構多複雜。
像 if 敘述、for 迴圈、switch 敘述,和邏輯運算子等等,都會增加程式的循環複雜度。
複雜度的值不重要,重點在於你對測量數據的解釋必須維持一致,並且訂出一個合理的門檻值。
高循環複雜度可能代表程式碼比較難維護,而維護又意味著必須修改程式碼。
類別耦合度
代表類別之間的耦合程度。
傳入耦合度:有多少類別依賴我?
傳出耦合度:我依賴多少類別?
高耦合度代表程式碼不易修改,當你要修改程式碼時,都會引發一連串的修改,稱為漣漪效應。
為了提高程式碼的可維護性,必須盡量減少漣漪效應產生的衝擊。
內聚力
與耦合度有關的度量是內聚力,類別有很高的內聚力,即表示其功能與責任是緊密結合的。
有大量低內聚力的類別,通常都比較難維護。
高內聚力雖然是好事,但並不代表你就應該丟掉所有的 HelperMethods 類別,或將你的網路服務拆成多個類別。
與主序帶之距離(distance from main sequence)
你的組件離理想的主序帶有多遠?
抽象度與不穩地度的組合。
抽象度指的是程式的所有類別內,有多少是抽象類別。
抽象度(A):某個組件沒有任何抽象類別或介面,則 A = 0,若完成沒有具象類別,則 A = 1。0(具象)1(抽象)
耦合度(I):耦合度 = 傳出耦合度 / (傳出耦合度 + 傳入耦合度)。0(穩定)1(不穩定)。
理想組件的抽象度與不穩定度的總和為 1 。我們說他在抽象與不穩定之間取得平衡。
A + I = 1 所涵蓋的區域即所謂的主序帶。
痛苦地帶(zone of pain)與無用地帶(zone of uselessness)
無用地帶:代表組件是抽象且不穩定的。也就是說,組件中有需多抽象類別或介面,而且它們依賴外部型別的程度非常高。
痛苦地帶:代表組件是具象且穩定的。也就是說,組件包含許多具象類別,而且有很多外部組建依賴它們,非常缺乏彈性。
繼承深度
代表某個類別的繼承階層有多深、或有幾層。
常見的名稱為『繼承樹的深度』(depth of inheritance tree)。
類別的繼承深度越深,通常就越難維護。
可維護性指數
直覺之處在於,它是用來測量程式碼有多容易維護的指標。
迷人之處在於,他能夠透過量化方法來將原來為質性的東西以數字呈現。
MI = 171 -(5.2 x ln(HV 程式碼複雜度))-(0.23 x CycCom 循環複雜度)-(16.2 x ln(LOC 程式碼行數))。
此度量的參考價值已經不高。
成為統計的奴隸
程式碼度量本身也有一些陷阱。
極端狀況:開發團隊太在意這些統計數字,只依數據行事,而不管對專案有沒有幫助
舉例來說:程式碼涵蓋範圍達 80% 建置才是成功。
您的專案為 81%,但經過重構後,刪除不必要的程式碼,變為 79%
但你的單元測試已經涵蓋100%,但你的建置是失敗的
有三種方法可以處理此問題
- 把剛剛的重構復原,讓他回原先的 80%
- 修改測試程式,直到程式碼涵蓋範圍到 80%
- 降低程式碼涵蓋範圍的基準
您應該選擇第三個方法。
不要讓自動化建置程序依賴任何統計數字,無論它是程式碼涵蓋範圍、類別耦合度,還是其他度量指標。
為了避免開發人員太過專注於程式碼的度量指標,而忘了真正該注意的,其實是程式碼本身。
軟體度量的用途如同曳光彈,是用來指引,而非規範。
實作統計分析
自動計算程式碼涵蓋範圍
度量指標與CI
程式碼涵蓋範圍整合至你的 CI 程序,但請別再將其他程式碼度量指標也一併整合至 CI
你不會想要在每次簽入時,都產生一次度量結果,因為產生統計資料需要花費很多時間
比較好的做法,用另一個獨立的自動化程序,依照週期,例如每週執一次等等。
重點是讓每次產生的統計資料跟上一次的結果有些明顯的差異,以便觀察其中的變化。
其他自動執行的工作
以下是一些可以考慮自動執行的動作(括號是建議使用的工具)
- 從 XML 註解產生說明文件( Sandcastle 或 Docu)
- 強制寫碼規範( FxCop 或 StyleCop )
- 檢查重複的程式碼( Simian-Similarity Analyser )
- 程式碼產生器( CodeSmith 或 MyGeneration)
- 資料轉移、測試資料庫的建立( SQL Data Compare/ SQL Packager / SQL script
只要能夠減少人工的操作錯誤,讓你專注於提高生產力,都值得考慮將它們納入自動化程序
總結
當您意識到『我為什麼要一直做這件事呀?』請問再自己『為什麼我們不把它自動化呢?』
程式碼度量,它們幫你挑出問題,剩下的工作就是找出正確的處理方法了。
目的都是幫您改善軟體的可維護性。