在具有多个出口点的代码圈复杂(Cyclomatic Complexity in piece of c

2019-08-17 13:39发布

我有这个方法验证密码:

/**
 * Checks if the given password is valid.
 * 
 * @param password The password to validate.
 * @return {@code true} if the password is valid, {@code false} otherwise.
 */
public static boolean validatePassword(String password) {
    int len = password.length();
    if (len < 8 || len > 20)
        return false;
    boolean hasLetters = false;
    boolean hasDigits = false;
    for (int i=0; i<len; i++) {
        if (!Character.isLetterOrDigit(password.charAt(i)))
            return false;
        hasDigits = hasDigits || Character.isDigit(password.charAt(i));
        hasLetters = hasLetters || Character.isLetter(password.charAt(i));
    }
    return hasDigits && hasLetters;
}

让我们专注于圈复杂度号码:这是它的价值?

指标1.3.6说,这是7,但我真的不能找到七个独立的路径:我只找到5! 和维基百科没有帮助了多少,怎么了,我想用这个公式π - s + 2

我有2个if的,1 for和3个出口点,但我坚持:做我都数不过来的切入点? 我应该算两次第一if因为它有两个条件?

编辑:

好了,现在我发现,圈数是7,这意味着,有7条独立的路径,所以我应该能够找到7个不同的测试情况下,如果我将涵盖的代码100%,是吗?

好了,我仍然无法找到的最后一个! 我发现这些:

  1. 有效期:asdf1234
  2. 太短:asdf123
  3. 太长:asdfsgihzasweruihioruldhgobaihgfuiosbhrbgtadfhsdrhuorhguozr
  4. 无效字符:ASDF * 123
  5. 所有位数:12345678
  6. 无数字:asdfghjk
  7. 跆拳道???

Answer 1:

我认为,诀窍是,逻辑运算符进行计数。

基于把你的度量链接(的http://metrics.sourceforge.net/下麦凯布圈复杂度部分):

1个初始流

3个决策点(如果,如果)

3个条件逻辑运算符(||,|| ||)

总:7



Answer 2:

我觉得这里的最主要的是,条件语句做短路,这是控制流的一种形式。 什么帮助是重新编写代码来作出这样的明确。 做程序分析时,这种正常化的是常见的。 一些临时正常化(不正规和一台机器就不会产生这一点,但它横跨得到点)将让你的代码如下所示:

public static boolean validatePassword(String password) {
    int len = password.length();

    //evaluate 'len < 8 || len > 20'
    bool cond1 = len < 8;
    if (!cond1) cond1 = len > 20;
    //do the if test
    if (cond1)
        return false;

    boolean hasLetters = false;
    boolean hasDigits = false;
    //for loops are equivalent to while loops
    int i = 0;
    while(i < len) {
        if (!Character.isLetterOrDigit(password.charAt(i)))
            return false;

        //evaluate 'hasDigits || Character.isDigit(password.charAt(i))'
        bool hasDigitsVal = hasDigits;
        if (!hasDigitsVal) hasDigitsVal = Character.isDigit(password.charAt(i));
        //hasDigits = ...
        hasDigits = hasDigitsVal

        //evaluate 'hasLetters || Character.isLetter(password.charAt(i))'
        bool hasLettersVal = hasLetters;
        if (!hasLettersVal) hasLettersVal = Character.isLetter(password.charAt(i));
        //hasLetters = ...
        hasLetters = hasLettersVal;

        i++;
    }

    //evaluate 'hasDigits && hasLetters'
    bool cond2 = hasDigits;
    if (cond2) cond2 = hasLetters;
    //return ...
    return cond2;
}

请注意如何||&&运营商基本上只是添加if语句代码。 还要注意,你现在有6 if语句和一个while循环! 也许这就是你要找的7?


关于多个出口点,这是一个红鲱鱼。 考虑每一个函数为具有一个出口节点,该函数的末尾。 如果你有多个return语句,每个return的语句将得出一个边缘到出口节点。

void foo() {
    if (cond1) return a;
    if (cond2) return b;
    return c;
}

该图是这样的,在这里-----val----> EXIT是指具有的值离开功能val

START -> cond1 ------------------------a------------> EXIT
           |                                            |
         cond2 ------------------------b----------------+
           |                                            |
         return -----------------------c----------------|

如果重新编写代码,那么你基本上只是添加另一种“回归前”节点时,那么转到出口节点:

void foo() {
    int val;
    if (cond1) {
        val= a;
    }
    else {
        if (cond2) {
            val= b;
        }
        else {
            val= c;
        }
    }
    return val;
}

现在,它看起来像这样:

START -> cond1 ---> val=a --------------------------> return ----val----> EXIT
           |                                            |
         cond2 ---> val=b ------------------------------+
           |                                            |
           + -----> val=c ------------------------------+

它仍然是复杂,代码只是丑陋。



Answer 3:

由于很好地解释在这里 :

圈复杂度=(2 + IFS +环路+案例 - 返回)其中:

 * ifs is the number of IF operators in the function, * loops is the number of loops in the function, * cases is the number of switch branches in the function (without default), and * return is the number of return operators in the function. 

如前所述,逻辑条件进行了计算。

例如if (len < 8 || len > 20)计为3个条件:

  1. if
  2. len<8
  3. len > 20

这意味着,您的代码的复杂性2 + 8 - 3 = 7 ,其中:

  • 2 - 它总是存在(见式在那里)
  • 8 - 数量的分支
  • 3 - 数返回的


文章来源: Cyclomatic Complexity in piece of code with multiple exit points