圈复杂度 (Cyclomatic Complexity)

圈复杂度,又称条件复杂度,是评估代码复杂性的指标,与测试用例数和程序维护难度有关。计算公式为V(G) = E - N + 2,其中E表示边数,N表示点数。高圈复杂度增加错误风险,建议通过提炼函数、使用break/return、简化条件等方式降低。常用的圈复杂度检查工具有OCLint、GMetrics、PyMetrics、JSComplexity、sourcemonitor和sonarqube。
概念

圈复杂度也称条件复杂度,是一种衡量代码复杂度的标准。它可以用来衡量一个模块判定结构的复杂程度,数量上表现为独立现行路径条数,也可以理解为覆盖所有情况最少使用的测试用例数。圈复杂度大说明程序代码的判断逻辑复杂,可能难以维护。

计算方法

V(G) = E - N + 2;

其中,E表示控制流图中边的数量,N表示控制流图中点的数量。

下面举例说明,如if-else,while,until和正常的顺序:

squence

A;
B;
A
B

if - else

A;
if(some_condition)
	then 
		B;
	else
		C;
end if
D;
A
B
C
D

while

A;
while(some_condition) 
	do 
		B;
	end
C;
A
B
C

until

A;
repeat
	B;
until(some_condition);
C;
A
B
C

举个例子:

void func(){
	a;
	while(A)
	{
		if(B || C)
			b;
		c; 
	}
	if(D && E) {
		d;
		for(F)
		{
			if(G || H || I)
				e;
		}
	}
	if(J && K)
		h;
	i; 
};

那么上面的复杂度为:
A(while)+B(if)+C(if)+D(if)+E(if)+F(for)+G(if)+H(if)+I(if)+J(if)+K(if)+1 = 12

注意||和&&也会被算作一个判定节点

圈复杂度的意义

一般来说,圈复杂度大存在很大的出错风险。另外在测试的时候,一个很好的用例设计经验:创建与圈复杂度值相等的测试用例,以此提高用例对代码的分支覆盖率。

降低圈复杂度的方法
  1. 提炼函数,将复杂的分支隔离,换成call func()调用函数。

  2. 使用break,return代替控制标记。

  3. 使用数据结构,算法。

  4. 多态取代条件式,设计模式替换。

  5. 简化条件判断。
    举个例子:

    string fun(string key) {
    	if(key == "A") {
    		return "a";
    	} else if(key == "B") {
    		return "b"
    	} else if(key == "C") {
    		return "c"
    	};
    	return string;
    }
    

    改成

    string fun(string key) {
    	map<string,string> maps;
    	maps["A"]="a";
    	maps["B"]="b";
    	maps["C"]="c";
    	return maps[key];
    }
    
常用工具
  1. OCLint(C语言),GMetrics(Java),PyMetrics(Python),JSComplexity(js)
  2. Lizard,sourcemonitor(支持多种语言)
  3. sonarqube(平台)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值