代码的圈复杂度,圈复杂度什么意思呀,圈复杂度是一种代码复杂度的衡量标准
什么是圈复杂度?
—————————————————————————————————————
圈复杂度是衡量计算机程序复杂程度的一个尺度。它是根据程序从头到尾的线性独立路径数来计算的。
圈复杂度越高,代码就越难复杂难维护。坑就越大。。。
从1开始,一步一步地完成这个程序。但是遇到以下关键词,或者其他类似的词,就加1: if,while,repeat,for,and,or。case语句中的每个case加1。例如,以下函数的圈复杂度为1,这意味着代码只有一条路径。
DEF (A,B):返回A B对于有分支的代码,其圈复杂度为2,比如下面这段递归计算阶乘的代码:
Defial (n):如果n==0:返回1 else:返回n *阶乘(n-1)它的计算方法很简单:
公式1: V (g)=E-N 2p。其中e表示控制流图中的边数,n表示控制流图中的节点数,p图中的连通分量数(图中的分量数是连通节点的最大集合)。因为所有的控制流图都是连通的,所以p是1。
如何测量程序的圈复杂度?
—————————————————————————————————————
在Python中,mccabe包可以用来度量程序的圈复杂度。
Mccabe可以用一个简单的命令行安装。
Pipmccabe运行以下命令来检测test.py的圈复杂度
Python-mmmccabe-min5test.py其中-min5表示允许的最小圈复杂度,输出大于5的圈复杂度,如下所示:
第一个输出的结果是一个91行的roundRobin函数,复杂度为7。5%.
代码质量优化
—————————————————————————————————————
把子程序的一部分提取成另一个子程序,不会降低整个程序的复杂度,只是把决策点移到其他地方
,但是这样做可以降低您必须同时关注的复杂程度。因为重点是减少你需要同时考虑的项目数量,所以降低给定程序的复杂性是有价值的。
1.提炼函数(php为例,下面一样):
函数测试($ NUMBER){ if($ NUMBER self:MIN _ NUMBER){ $ NUMBER=self:MIN _ NUMBER;} for($ I=0;$ i $ number$ I){//某些代码}}可以替换为以下模式:
函数测试($ number){ $ number=getMin($ number);for($ I=0;$ i $ number$ I){//some code } }函数getMin($ NUMBER){ if($ NUMBER self:MIN _ NUMBER){ return self:MIN _ NUMBER;} return $number}
2.替换算法(把复杂算法替换为另一个更清晰的算法):
if($ str== China ){ $ result= China people ;} else if($ str== US ){ $ result= American ;} else if($ str== France ){ $ result= French ;}变成这样:
$people=[China= China , US= American , = French ];$ result=$ people[$ str];
3.反向表达式(改变条件表达式的顺序以简化复杂度):if((条件1,条件2) !1)条件1){返回真;}else{返回false}变成这样:
If(条件1!2){返回false}返回true
4.分解条件(对复杂条件表达式(if、else)进行分解并提取成独立函数):
if(do _ some _ 1($ number) do _ some _ 2($ number)){ $ number=$ number。$someStr1。$someStr2。123456789;}else{ $number=$number。$someStr3。$someStr4。123456789;}变成这样:
if(do _ some _ fun($ number)){ $ number=do _ some _ fun 1($ number);} else { $ number=do _ some _ fun 2($ number);}
5.合并条件(将这些判断合并为一个条件式,并提取成独立函数):
if($x 1)返回0;if($y 10)返回0;如果($z!=0)返回0;变成这样:if(get_result($x,$y,$z))返回0;
6.移除控制标记(可以使用break和return取代控制标记。):
$ bool=falseforeach($arrs as $arr){ if(!$ bool){ if($ arr==1){ some function();$ bool=true} if($ arr==2){ some function();$ bool=true}}}变成这样:
foreach($ arrs as $ arr){ if($ arr==1 $ arr==2){ some function();}破;}
7.以多态取代条件式(将整个条件式的每个分支放进一个子类的重载方法中,然后将原始函数声明为抽象方法。由于php是弱类型语言,这里体现的有点模糊):
switch($ cat){ case fish :eatFish();case moss :eat moss();}函数eatFish(){ echo‘鲸鱼吃鱼’;}函数eat moss(){ echo‘鲸吃苔’;}变成这样:
接口Eat {函数Eat fish();函数eat moss();}类Whale实现Eat {公共函数eatFish(){ echo Whale Eat fish ;}公共函数eat moss(){ echo‘鲸吃苔’;}}
8.参数化方法(建立单一函数,以参数表达那些不同的值):
$result=min(lastUsage(),100)* 0.03;if(last usage()100){ $ result=(min(last usage(),200)-100)* 0.05;}变成这样:
$result=getMin(0,100)* 0.03;$result=getMin(100,200)* 0.03;函数getMin($start,$ end){ if(last usage()$ start){ return(min(last usage(),$ end)-$ start);}返回0;}
9.明确函数取代参数(针对该参数的每一个可能值,建立一个独立函数):
if($ name== width ){ $ width=$ value;} else if($ name== height ){ $ height=$ value;} 变成这样:
函数设置宽度($ value){ $ width=$ value;}函数setHeight($ value){ $ height=$ value;}