代码圈复杂度治理小结

文章介绍了代码圈复杂度的概念、计算方法及其对代码可读性和维护性的影响。通过实例展示了如何通过拆分方法、优化逻辑判断和利用编程技巧降低圈复杂度,以提升代码质量。
摘要由CSDN通过智能技术生成

网上有个段子,说建筑工程师不会轻易答应会给摩天大楼增加一个地下室,但代码开发工程师却经常在干这样的事,并且总有人会对你说“这个需求很简单”。到土里埋个雷,这确实不复杂,但我们往往面临的真实场景其实是“在一片雷区的土里埋一个雷”。而雷区里哪里有雷,任何人都不知道。

回到我们日常的写代码的场景,我们一直在说系统很复杂,那到底什么是系统复杂度呢?最近几个月,蚂蚁代码力平台(注:是蚂蚁的代码评价平台)进入大家视野,很多同学开始关注起自己代码力的得分情况。作为团队的稳定性底盘负责人,也经常和大家探讨为什么会因为圈复杂度高而被扣分。那么,怎么才能写的一手可读,可扩展,可维护[注1]的好代码?本文作者尝试结合在团队内部的实践,分享下过程中心得,希望对大家的代码圈复杂度治理提供微弱的帮助。

什么是圈复杂度

先看看圈复杂度的通用的定义,圈复杂度(Cyclomatic complexity,简写CC)[注2]也称为条件复杂度/循环复杂度,是一种代码复杂度的衡量标准。由托马斯·J·麦凯布(Thomas J. McCabe, Sr.)于1976年提出,用来表示程序的复杂度,其符号为VG。它可以用来衡量一个模块判定结构的复杂程度,数量上表现为独立现行路径条数,也可理解为覆盖所有的可能情况最少使用的测试用例数。说人话,圈复杂度关系到质量同学最少需要设计多少用例才能覆盖你的代码分支。

怎么计算圈复杂度

蚂蚁广目平台给出了比较详细的说明,这里直接引用,网上也可以查到类似内容。

节点判断计算公式为:V (G) = P + 1 注:除了节点判断法,还有其他方法,如点边判断法,这里只选一个用于说明。

其中P为条件节点数,条件节点类型为:

a.条件语句

  • if语句
  • while语句(包含do...while...语句)
  • for语句(包含foreach语句)
  • switch case语句
  • try catch语句

b.条件表达式(二元或多元)

  • && 表达式
  • || 表达式
  • 三元运算符


举例如下(部分代码省略后用xxx代替):

//案例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( XXDTO newScriptDTO) {
    
    String type = Enums.ScriptType.CUSTOM;
    Boolean containsTryCatch = StringUtil.contains(content, "try")
        && StringUtil.contains(content, "catch");
    if (StringUtil.isBlank(scriptName)) {
        baseOperationResult.setMessage("XXX");
        return baseOperationResult;
    }
    
    if (!scriptName.matches("^[(\\d)|_|a-z|A-Z]+$")) {
        baseOperationResult.setMessage("XXX");
        return baseOperationResult;
    }
    
    NewScript tempScript = null;
    try {
        tempScript = newScriptManager.findByName(StringUtil.trim(scriptName));
    } catch (Exception e) {
        baseOperationResult.setMessage("XXX");
        return baseOperationResult;
    }
    
    if (StringUtil.isBlank(id)) {
        if (tempScript != null) {
            baseOperationResult.setMessage("XXX");
            return baseOperationResult;
        }
    } else {
        Integer editScriptId = Integer.parseInt(id);
        if (null != tempScript) {
            if (!editScriptId.equals(tempScript.getId())) {
                baseOperationResult.setMessage("XXX");
                return baseOperationResult;
            }
        }
    }
    
    if (!Enums.NewScriptTypeEnum.XX.contains(sc
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值