Cyclomatic Complexity
1. 概念
a. 圈復雜度是一種衡量代碼復雜程度的標准。
b. 圈復雜度高的害處:
圈復雜度大說明代碼的判斷邏輯復雜,可能質量低;
需要的更多的測試用例,難於測試和維護;
程序的可能錯誤和高的圈復雜度有着很大關系。
c. 圈復雜度的表現:
代碼中分支循環語句多(if/else, switch/case, for, while),圈復雜度與分支循環語句個數正相關;
表達式復雜(含有三元運算符 )。
2. 圈復雜度的計算方法
(1)圈復雜度可以通過程序控制流圖計算,公式為:V(G) = e + 2 - n
e : 控制流圖中邊的數量
n : 控制流圖中節點的數量(包括起點和終點;所有終點只計算一次,多個return和throw算作一個節點)
(2)圈復雜度對應程序控制流圖中從起點到所有終點的路徑的條數,所以頁可以通過數路徑的方式獲得圈復雜度。
3. 圈復雜度計算實例
private int CalculateScore(int culture, String nation, boolean extend) { int result = 0; if (culture < 0) { throw new RuntimeException("分數不能小於0"); } else if (culture < 200) { return culture; } else { switch (nation){ case "漢": result = 0; break; case "蒙": case "回": case "維": case "藏": result = 10; break; default: result = 20; } } if (extend) { result += 10; } return result + culture; }
程序控制流圖:
(1) V(G) = 21 + 2 - 13 = 8;
(2) 數路徑:8條
4. 減小圈復雜度的方法
a. 提取函數 - 將獨立業務或模塊代碼獨立出來,封裝為函數,通過函數名詮釋代碼作用,做到見名知意。
b. 替換算法 - 復雜算法會導致bug可能性的增加及可理解性/可維護性的降低,如果函數對性能要求不高,提倡使用簡單明了的算法。
c. 分解條件式 - 復雜的條件表達式,使用函數進行封裝
d. 合並條件式 - 將一系列得到相同結果的條件表達式合並,可以的話封裝為函數
e. 合並重復的條件片段 - 不同條件的分支,有相同的處理,可以提煉出分支以外,或者封裝為函數
f. 移除控制標記 - 使用控制標簽作為條件的,使用break 和 return取代
g. 將查詢函數和修改函數分離 - 單一職責原則,強調函數的復用性而不是多用性
h. 函數攜帶參數 - 使用帶參函數,強調函數的復用性
i. 以明確函數取代參數 - 強調函數的功能的明確性