节点判断计算公式为:
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
});
}