该方法的Cyclomatic Complexity大于授权

时间:2016-05-05 09:21:21

标签: java cyclomatic-complexity

我使用以下方法检查null或空字段:

public boolean isVoNotNull(){
        return null != this.cardNo &&  StringUtils.isNotBlank(this.cardNo) 
                && null != this.otp && StringUtils.isNotBlank(this.otp) 
                && null != this.password && StringUtils.isNotBlank(this.password)
                && null != this.userid && StringUtils.isNotBlank(this.userid) 
                && null != this.type && StringUtils.isNotBlank(this.type) 
                && null != this.walletMobileNo && StringUtils.isNotBlank(this.walletMobileNo);
    }

但是当此代码使用SonarLint进行验证时,请低于异常

  

异常:这种方法的循环复杂性" isVoNotNull"是   12,大于10授权。

如何解决此异常或如何从代码中删除复杂性?

4 个答案:

答案 0 :(得分:12)

您需要分析重复的代码并将其重构为可重用的方法。

鉴于您的原始代码段,

public boolean isVoNotNull() {
    return null != this.cardNo &&  StringUtils.isNotBlank(this.cardNo) 
        && null != this.otp && StringUtils.isNotBlank(this.otp) 
        && null != this.password && StringUtils.isNotBlank(this.password)
        && null != this.userid && StringUtils.isNotBlank(this.userid) 
        && null != this.type && StringUtils.isNotBlank(this.type) 
        && null != this.walletMobileNo && StringUtils.isNotBlank(this.walletMobileNo);
}

我们可以识别以下重复部分:

null != this.xxx && StringUtils.isNotBlank(this.xxx)

鉴于StringUtils#isNotBlank() already检查了null,我们可以进一步简化它。

StringUtils.isNotBlank(this.xxx)

鉴于你需要多次调用它,最好是将它重构为一个variable number of arguments的方法,它在一个循环中检查它们。

public static boolean isNoneBlank(String... strings) {
    for (String string : strings) {
        if (!StringUtils.isNotBlank(string)) {
            return false;
        }
    }
    return true;
}

或者,如果您已经使用Streams and Lambda支持使用Java 8,那么

public static boolean isNoneBlank(String... strings) {
    return Arrays.stream(strings).allMatch(StringUtils::isNotBlank);
}

现在您可以按照以下方式使用它:

public boolean isVoNotNull() {
    return isNoneBlank(this.cardNo, this.otp, this.password, this.userid, this.type, this.walletMobileNo);
}

您可以通过删除不必要的this来进一步减少样板。

public boolean isVoNotNull() {
    return isNoneBlank(cardNo, otp, password, userid, type, walletMobileNo);
}

这一切都是Don't Repeat Yourself (DRY)软件工程原理的应用。

那就是说,正如msandiford指出的那样,事实证明Apache Commons Lang StringUtils已经完成了3.2 already版本的这种方法。因此,如果您还没有,请考虑将Apache Commons Lang升级到至少3.2。

public boolean isVoNotNull() {
    return StringUtils.isNoneBlank(cardNo, otp, password, userid, type, walletMobileNo);
}

答案 1 :(得分:4)

正如其他人指出的那样null检查是多余的,因为isNotBlank也检查了这一点。

因此,如果您使用的是Apache StringUtils 3.2或更高版本,则可以使用StringUtils.isNoneBlank(...)

public boolean isVoNotNull() {
    return StringUtils.isNoneBlank(cardNo, otp, password, userid, type, walletMobileNo);
}

如果您使用的是早期版本,则可以轻松编写一个:

public static boolean isNoneBlank(CharSequence... seqs) {
  for (CharSequence seq : seqs) {
    if (StringUtils.isBlank(seq))
      return false;
  }
  return true;
}

或者在Java 8中:

public static boolean isNoneBlank(CharSequence... seqs) {
  return Stream.of(seqs).allMatch(StringUtils::isNotBlank);
}

答案 2 :(得分:1)

将字符串添加到数组中并使用循环检查是否为null而不是空白。当然最糟糕的表现,但应该打破那个没有感觉到的限制。

示例代码:

public boolean isVoNotNull(){
    string [] stringsToCheck = new string[]{
    this.cardNo,
    this.otp,
    // ...
    }

    //return CheckStringArrayNotNull(stringsToCheck);        
    return StringUtils.isNoneBlank(stringsToCheck);
}

// high chance this method already exists inside StringUtils
// INFACT FOUND! :)
private boolean CheckStringArrayNotNull( string [] stringsToCheck){
     for(int i=0; i<stringsToCheck.length(); i++)
        if( StringUtils.isNotBlank( stringsToCheck[i]) == false)
            return false;

    return true; 
}

甚至更好,(编辑:似乎@msandiford按时击败了我的解决方案)

public boolean isVoNotNull(){      
    return StringUtils.isNoneBlank(cardNo, otp, ...);
}

当然,您可以使用更多方法来减少圈复杂度,但这会使课程更难以阅读和理解。代码度量应仅用于调查问题,而不是用作开发咒语,例如,我可以使用100个方法的非常愚蠢的类,每个方法的Cyclomatic复杂度为100,并重构它以使其具有完美的代码度量但无法理解。永远不要看代码指标,在不使用编码指标的情况下考虑好的解决方案。

答案 3 :(得分:0)

StringUtils.isNotBlank

https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/StringUtils.html#isNotBlank%28java.lang.CharSequence%29

“检查CharSequence是否为空(”“),不为空且不仅仅为空格。”

该函数已经检查对象是否为null,那么你可以简化

public boolean isVoNotNull() { 
  return StringUtils.isNotBlank(this.cardNo) 
      && StringUtils.isNotBlank(this.otp) 
      && StringUtils.isNotBlank(this.password)
      && StringUtils.isNotBlank(this.userid) 
      && StringUtils.isNotBlank(this.type) 
      && StringUtils.isNotBlank(this.walletMobileNo);
}

要减少条件运算符的数量,可以执行以下操作:

public boolean isVoNotNull(){
  Boolean[] condition = new Boolean[] {
      StringUtils.isNotBlank(this.cardNo), 
      StringUtils.isNotBlank(this.otp),
      StringUtils.isNotBlank(this.password),
      StringUtils.isNotBlank(this.userid), 
      StringUtils.isNotBlank(this.type),
      StringUtils.isNotBlank(this.walletMobileNo)
  };
  return BooleanUtils.and(condition);
}

可能有点棘手,但它有效