首页 > 编程知识 正文

switch case圈复杂度

时间:2023-05-03 13:03:06 阅读:237064 作者:4578

最近在做ESLint规则配置,重新注意了下complexity规则,之前对该规则不够重视,理解有盲区,于是系统学习,这里犹豫的彩虹下。

概念循环复杂度 Cyclomatic complexity也称为条件复杂度或圈复杂度,是一种软件度量,是由kydgz在1976年提出,用来表示程序的复杂度

圈复杂度计算

公式

M = E − N + 2P

其中

E 为图中边的个数

N 为图中节点的个数

P 为连接组件的个数[程序的个数,对于单一的程序,P恒为1],如下图是1

如图,E = 9, N = 8, P = 1,因此其循环复杂度为 9 - 8 + (2*1) = 3

以上是标准的公式,但是简单的办法实际上是判定节点数量再加一

节点判定

个人喜欢这样直接算,较为简单

判定节点if语句

conditional语句,比如?:

for语句

while语句

try语句

switch/case语句

注意从1开始,一直往下通过程序

遇到以下关键字,或者其它同类的词,就加1:if,while,repeat,for,and,or

if-else-if,switch-case语句中的每一种情况都加1

圈复杂度参考值

这里贴下圈值与风险值对比表格。可以看出20是个已经在维护性边缘,当然10最佳。

01 to 10 – Minimal Risk, Easy to maintain

11 to 20 – Moderate Risk, Harder to maintain

21 to 50 – High Risk,Candidates for refactoring/redesign

Over 50 – Very High Risk

注意eslint中默认值是20,checkstype中默认值是10

圈复杂度小不一定意味着代码好,但是太大,代码一定不好,不具备维护性,这点需要明确

检测手段

开发中为了确保代码风格的统一,我们往往通过eslint,checkStyle等工具检测代码,对于不满足的规范报错提示。当前这些检测工具都支持了圈复杂度

eslint-rules

1

2

3{

'complexity': ['error', { 'max': 20 }]

}

checkStyle

1

2

3

4

5

6

7

8

9

10

11<?xml version="1.0"?>

重构手法

面对圈值过高的函数,我们要做的是重构来解决,具体如何处理呢。

提炼函数,做到函数职责单一,降低单个函数的复杂度,圈值自然降低

switch,if else使用的多时,可以考虑多态,考虑map映射来解决多分支问题

简化逻辑判断,不断的逻辑合并收拢,有时会发现重复。

ESLint中圈复杂度统计源码分析

这里通过ESLint中相关rule了解下实现原理

eslint/lib.rules/complexity.js,地址戳这里

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34/**

* Increase the switch complexity in context

* @param {ASTNode}node node to evaluate

* @returns {void}

* @private

*/

function increaseSwitchComplexity(node){

// Avoiding `default`

if (node.test) {

increaseComplexity();

}

}

return {

FunctionDeclaration: startFunction,

FunctionExpression: startFunction,

ArrowFunctionExpression: startFunction,

"FunctionDeclaration:exit": endFunction,

"FunctionExpression:exit": endFunction,

"ArrowFunctionExpression:exit": endFunction,

CatchClause: increaseComplexity,

ConditionalExpression: increaseComplexity,

LogicalExpression: increaseComplexity,

ForStatement: increaseComplexity,

ForInStatement: increaseComplexity,

ForOfStatement: increaseComplexity,

IfStatement: increaseComplexity,

SwitchCase: increaseSwitchComplexity,

WhileStatement: increaseComplexity,

DoWhileStatement: increaseComplexity

};

计算办法就是,根据AST树,找到这些判定节点,进行对应的复杂度计算即可。如上,switch/case中default不算。

写在最后记得以前看书,印象深的一句话,代码易读性是为了人,面对运行代码的机器,怎么写理论上都行,但问题是人要读和看,那么易读性,可维护性就显得尤为重要。so,重视圈复杂度,这是个很好的指标来督促我们写出易读的代码

圈复杂度的意义是在缺陷成为缺陷之前捕获它们。

参考链接

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。