圈复杂度

摘要:
b.圈复杂度高的害处:圈复杂度大说明代码的判断逻辑复杂,可能质量低;需要的更多的测试用例,难于测试和维护;程序的可能错误和高的圈复杂度有着很大关系。

Cyclomatic Complexity

1. 概念

a. 圈复杂度是一种衡量代码复杂程度的标准。

b. 圈复杂度高的害处:

圈复杂度大说明代码的判断逻辑复杂,可能质量低;

需要的更多的测试用例,难于测试和维护;

程序的可能错误和高的圈复杂度有着很大关系。

c. 圈复杂度的表现:

代码中分支循环语句多(if/else, switch/case, for, while),圈复杂度与分支循环语句个数正相关;

表达式复杂(含有三元运算符 )。

2. 圈复杂度的计算方法

圈复杂度第1张

(1)圈复杂度可以通过程序控制流图计算,公式为:V(G) = e + 2 - n

e :控制流图中边的数量

n :控制流图中节点的数量(包括起点和终点;所有终点只计算一次,多个return和throw算作一个节点)

(2)圈复杂度对应程序控制流图中从起点到所有终点的路径的条数,所以页可以通过数路径的方式获得圈复杂度。

3. 圈复杂度计算实例

private int CalculateScore(int culture, String nation, booleanextend) {
        int result = 0;
        if (culture < 0) {
            throw new RuntimeException("分数不能小于0");
        } else if (culture < 200) {
            returnculture;
        } else{
            switch(nation){
            case "汉":
                result = 0;
                break;
            case "蒙":
            case "回":
            case "维":
            case "藏":
                result = 10;
                break;
            default:
                result = 20;
            }
        }
        
        if(extend) {
            result += 10; 
        }
        return result +culture;
        
    }

程序控制流图:

圈复杂度第2张

(1) V(G) = 21 + 2 - 13 = 8;

(2) 数路径:8条

4. 减小圈复杂度的方法

a. 提取函数 - 将独立业务或模块代码独立出来,封装为函数,通过函数名诠释代码作用,做到见名知意。

b. 替换算法 - 复杂算法会导致bug可能性的增加及可理解性/可维护性的降低,如果函数对性能要求不高,提倡使用简单明了的算法。

c. 分解条件式 - 复杂的条件表达式,使用函数进行封装

d. 合并条件式 - 将一系列得到相同结果的条件表达式合并,可以的话封装为函数

e. 合并重复的条件片段 - 不同条件的分支,有相同的处理,可以提炼出分支以外,或者封装为函数

f. 移除控制标记 - 使用控制标签作为条件的,使用break 和 return取代

g. 将查询函数和修改函数分离 - 单一职责原则,强调函数的复用性而不是多用性

h. 函数携带参数 - 使用带参函数,强调函数的复用性

i. 以明确函数取代参数 - 强调函数的功能的明确性

免责声明:文章转载自《圈复杂度》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇C#实现PDF转SWF的操作未在本地计算机上注册"MSDAORA.1"提供程序下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

CentOS设置密码复杂度及过期时间等

我们在使用linux系统设置密码的时候,经常遇到这样的问题,系统提示:您的密码太简单,或者您的密码是字典的一部分。那么系统是如何实现对用户的密码的复杂度的检查的呢?  系统对密码的控制是有两部分(我知道的)组成:  1 cracklib  2 login.defs  声明:login.defs主要是控制密码的有效期。对密码进行时间管理。此处不细谈。  lo...

Go -- LFU类(缓存淘汰算法)(转)

1.LFU类 1.1.LFU 1.1.1.原理 LFU(LeastFrequentlyUsed)算法根据数据的历史访问频率来淘汰数据,其核心思想是“如果数据过去被访问多次,那么将来被访问的频率也更高”。 1.1.2.实现 LFU的每个数据块都有一个引用计数,所有数据块按照引用计数排序,具有相同引用计数的数据块则按照时间排序。 具体实现如下: 1.新加...

多串匹配

meteor多串匹配 Description Input 第一行为一个整数n,表示文本的长度 第二行为一个长度为n的文本 第三行为一个整数m,表示模式串个数 下接m行,每行一个模式串  Output 共m行,若第i个模式串在文本中出现过则第i行输出YES,否则输出NO 数据范围 对于30%的数据,n<=10^3,m<=10^3; 对于80%的数...

kubernetes的网络代理模式

  在k8s中,如果想ping svc以及ip,发现无法ping通,使用测试环境为k8s 1.6,后来k8s升级到1.12版本,发现ping svc以及ip可以ping通,这里分析一下原因。   后来发现是由于1.8的代理模式不是ipvs(1.6版本没有引入ipvs),1.12可以配置iptables和ipvs,而1.12版本配置使用的是ipvs。   这里...

什么是数据驱动编程

转自:https://blog.csdn.net/chgaowei/article/details/6658260 前言: 最近在学习《Unix编程艺术》。以前粗略的翻过,以为是介绍unix工具的。现在认真的看了下,原来是介绍设计原则的。它的核心就是第一章介绍的unix的哲学以及17个设计原则,而后面的内容就是围绕它来展开的。以前说过,要学习适合自己的资料...

OO第一单元总结(多项式求导)

一.综述 第一单元的主题为多项式求导,给定多项式函数,输出其导函数。其中第一次作业仅限幂函数,第二次作业添加了三角函数,第三次作业添加了函数之间的嵌套,相比人人皆知的求导规则,又臭又长,每次都不尽相同的格式要求或许才是真正磨人的地方。 二.作业与BUG分析 第一次作业 1.代码思路 第一次作业总体思路是先用正则拆项,然后根据拆得字符串提取系数与指数构造每一...