节点判断计算公式为:

V (G) = P + 1   注:除了节点判断法,还有其他方法,如点边判断法,这里只选一个用于说明。其中 P 为条件节点数,条件节点类型为:

  • 条件语句
    • if 语句
    • while 语句(包含 do…while…语句)
    • for 语句(包含 foreach 语句)
    • switch case 语句
    • try catch 语句
  • 条件表达式(二元或多元)
    • && 表达式
    • || 表达式
    • 三元运算符
//案例1,圈复杂度V(G) =  1(if) + 1(catch) + 1 = 3
public String myMethod1(){
    if(xxx){
        try {
            //xxx;
        } catch (IOException e) {
            //xxx;
        }
    }else{
         xxx;
    }
    return xx;
}
 
//案例2,圈复杂度V(G) =  2(if)  + 1(&&) + 1 = 4  
public String myMethod2() {
    if (xxx) {
        //xxx;
    } else {
        if (xxx && xxx) {
            //xxx;
        } else {
            //xxx;
        }
        xx();
    }
    
    return xx;
}

降低圈复杂度

方法一:抽取复杂方法

public XXresult doSave( NewScriptDTO newScriptDTO) {
    
      //0.构造结果
      XXresult result=new XXresult() ;
      
      try{
            //1.脚本名检查
            scriptNameCheck(newScriptDTO); 
            
             //2.脚本加载
            loadScript(newScriptDTO); 
            
             //3.脚本保存
            saveScript(newScriptDTO); 
            
        }catch(XXException e){
            result.setSuccess(false)
            result.setMessage("XXX");
            return result;
        }catch(Exception e){
            result.setSuccess(false)
            result.setMessage("XXX");
            return result;
        }
        //操作完成
                result.setSuccess(true)
        result.setMessage("XXX");
        return result;
 
}
/**检查脚本名*/
private void scriptNameCheck(NewScriptDTO newScriptDTO){
  xxx
}
/**加载脚本*/
private void loadScript(NewScriptDTO newScriptDTO){
  xxx
}
/**保存脚本*/
private void saveScript(NewScriptDTO newScriptDTO){
  xxx
}

方法二:优化逻辑判断

///////// 案例1,抽取频繁出现的条件a/////////
//修改前
if (条件1)
{
    if (条件a)
    {
        // 执行a逻辑
    }
}
else if(条件2)
{
    if (条件a)
    {
        // 执行b逻辑
    }
}
if (条件a)
{
    // 执行c逻辑
}
//修改后
if (条件a)
{
    if (条件1)
        {
             // 执行a逻辑
    }
    else if(条件2)
    {
             // 执行b逻辑
    }    // 执行c逻辑
}
///////// 案例2,优化逻辑判断顺序/////////
//修改前
if((条件1 && 条件2)|| !条件1){
    return true;
}else{
    return false;
}
//修改后
if(条件1 && !条件2){
    return false;
}
return true;

方法三:流式判断

//修改前
 List list = XXX;
 if (CollectionUtils.isEmpty(list)) {
   for (XX item : list) {
      if (item==null){
        return;
      }else{
        // 逻辑a
      }
  }
   
  //修改后
  List list = XX;
  list = Optional.ofNullable(list).orElse(new ArrayList<>());
  list.stream().filter(Objects::nonNull).forEach(item->{
     //逻辑a
  });
 
}