[代碼質量] 代碼層圈複雜度計算統計(轉)

轉載自: https://www.cnblogs.com/alterhu/archive/2012/03/28/2421643.htmlhtml

 

圈複雜度(Cyclomatic Complexity)是一種代碼複雜度的衡量標準。它能夠用來衡量一個模塊斷定結構的複雜程度,數量上表現爲獨立現行路徑條數,也可理解爲覆蓋全部的可能狀況最少使用的測試用例數。圈複雜度大說明程序代碼的判斷邏輯複雜,可能質量低且難於測試和維護。程序的可能錯誤和高的圈複雜度有着很大關係。工具

下面這個實例中,單元測試的覆蓋率能夠達到100%,可是很容易發現這其中已經漏掉了一個NPE的測試用例。case1方法的圈複雜度爲2,所以至少須要2個用例才能徹底覆蓋到其全部的可能狀況。單元測試

//程序原代碼,圈複雜度爲 2測試

public String case1(int num) {
    String string = null;
    if (num == 1) {
        string = "String";
    }
    return string.substring(0);
}

//上面代碼的單元測試代碼優化

public void testCase1(){
    String test1 = case1(1);
}

圈複雜度主要與分支語句(if、else、,switch 等)的個數成正相關。能夠在圖1中看到經常使用到的幾種語句的控制流圖(表示程序執行流程的有向圖)。當一段代碼中含有較多的分支語句,其邏輯複雜程度就會增長。在計算圈複雜度時,能夠經過程序控制流圖方便的計算出來。一般使用的計算公式是V(G) = e – n + 2 , e 表明在控制流圖中的邊的數量(對應代碼中順序結構的部分),n 表明在控制流圖中的節點數量,包括起點和終點(一、全部終點只計算一次,即使有多個return或者throw;二、節點對應代碼中的分支語句)。spa

                      圖一、各判斷語句的控制流圖插件

知道了如何計算圈複雜度,咱們來使用控制流圖從新計算一次case1方法的圈複雜度,其控制流圖以下圖。狀態1表示if(num == 1 )的條件判斷,狀態2表示string=」String」的賦值操做。能夠經過下面的控制流圖獲得 e = 3 ; n = 3;那麼全複雜度V(G) = 3 - 3 + 2 = 2,既case1的圈複雜度爲2。code

                            圖二、case1的控制流圖htm

 

在看一個計算全複雜度的例子。程序代碼以下:blog

public String case2(int index, String string) {
    String returnString = null;
    if (index < 0) {
        throw new IndexOutOfBoundsException("exception <0 ");
    }
    if (index == 1) {
        if (string.length() < 2) {
            return string;
        }
    return String = "returnString1";
    } else if (index == 2) {
        if (string.length() < 5) {
            return string;
        }
        returnString = "returnString2";
    } else {
       throw new IndexOutOfBoundsException("exception >2 ");
    }
    return returnString;
}                 

程序控制流圖:

圖三、case2的控制流圖

根據公式 V(G) = e – n + 2 = 12 – 8 + 2 = 6 。case2的圈複雜段爲6。說明一下爲何n = 8,雖然圖上的真正節點有12個,可是其中有5個節點爲throw、return,這樣的節點爲end節點,只能記作一個。

在開發中經常使用的檢測圈複雜度的工具,PMD,checkstyle均可以檢測到高複雜度的代碼塊。在代碼的開發中,配合各類圈複雜度的檢測插件,將高複雜度的代碼進行適當的拆分、優化,能夠大大提升代碼總體的質量,減小潛在bug存在。

相關文章
相關標籤/搜索