代碼的環複雜度(Cyclomatic complexity,有時也翻譯成圈複雜度)是一種代碼複雜度的衡量標準,在1976年由Thomas J. McCabe, Sr. 提出。java
來看看計算公式。編程
代碼環複雜度 = E − N + 2編程語言
E = 程序控制流圖中邊的個數翻譯
N = 程序控制流圖中點的個數code
很容易得出這樣的結論:代碼環複雜度越高,越容易出bug。ci
能夠想象若是須要開發人員本身去把一段代碼的控制流圖畫出來,而後去數圖中邊和點的個數,這種作法效率過低了也容易出錯。開發
好消息是,有一款名爲Source Monitor的免費軟件,可以幫咱們來度量Java代碼的環複雜度。固然這款軟件也支持C++和C#。get
爲了說明如何使用這款軟件,我寫了一段簡單的Java代碼。it
package test; import java.util.ArrayList; public class monthTool { static ArrayList<String> monthCollection = new ArrayList<String>(); public static void main(String[] args) { monthTool tool = new monthTool(); tool.printV1(1); tool.printV2(2); tool.printV1(0); tool.printV2(-1); tool.printV3(3); tool.printV3(13); } public monthTool(){ monthCollection.add("Invalid"); monthCollection.add("January"); monthCollection.add("Febrary"); monthCollection.add("March"); monthCollection.add("April"); monthCollection.add("May"); monthCollection.add("June"); monthCollection.add("July"); monthCollection.add("August"); monthCollection.add("September"); monthCollection.add("October"); monthCollection.add("November"); monthCollection.add("December"); } public void printV1(int month){ System.out.println("Month is: " + getMonthNameV1(month)); } public void printV2(int month){ if( month >= 1 && month <= 12) System.out.println("Month is: " + getMonthNameV2(month)); else System.out.println("Please specify a valid month"); } public void printV3(int month) { System.out.println("Month is: " + getMonthNameV3(month)); } public String getMonthNameV2(int month){ if( month == 1) return "January"; else if( month == 2) return "Febrary"; else if( month == 3) return "March"; else if( month == 4) return "April"; else if( month == 5) return "May"; else if( month == 6) return "June"; else if( month == 7) return "July"; else if( month == 8) return "August"; else if( month == 9) return "September"; else if( month == 10) return "October"; else if( month == 11) return "November"; else if( month == 12) return "December"; else return "Invalid"; } public String getMonthNameV1(int month){ switch (month){ case 1: return "January"; case 2: return "Febrary"; case 3: return "March"; case 4: return "April"; case 5: return "May"; case 6: return "June"; case 7: return "July"; case 8: return "August"; case 9: return "September"; case 10: return "October"; case 11: return "November"; case 12: return "December"; default: return "Invalid"; } } public String getMonthNameV3(int month){ try { return monthCollection.get(month); } catch (java.lang.IndexOutOfBoundsException e){ return "Invalid"; } } }
其中我用了三種不一樣的方式實現了同一個邏輯,將一個表明月份的整數轉成了月份名稱。io
下面是Source Monitor的具體用法。
1. 建立一個新的項目:
這裏能看到全部Source Monitor支持的編程語言。
2. 指定您本地的Java項目文件地址:
3. 指定您的Java項目文件夾內,您但願SourceMonitor計算哪些Java文件的環複雜度。
4. 點OK,就能夠開始掃描啦。
很快Source Monitor就將咱們指定的Java文件的環複雜度計算完畢。點擊菜單「Display Method Metrics」來查看結果:
從環複雜度掃描結果能看出,明顯第三種從月份名稱集合裏經過ArrayList自帶的get方法取得月份名稱是最優的解法——環複雜度僅爲2。
也能夠經過圖表的方式更直觀得看到方法的環複雜度比較:
X軸的值表明每一個方法的環複雜度,Y軸表明這些環複雜度的不一樣值出現的次數。
好比下圖的意思是,環複雜度爲1的方法(X軸刻度爲1的節點)共有4個(Y軸刻度爲4),環複雜度爲2的方法(X軸刻度爲2的節點)有1個(Y軸刻度爲1)。以此類推。
要獲取更多Jerry的原創技術文章,請關注公衆號"汪子熙"或者掃描下面二維碼: