栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > Web开发 > JavaScript

前端代码质量-圈复杂度

JavaScript 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

前端代码质量-圈复杂度

介绍

圈复杂度 (Cyclomatic complexity) 是一种代码复杂度的衡量标准,也称为条件复杂度或循环复杂度,它可以用来衡量一个模块判定结构的复杂程度,数量上表现为独立现行路径条数,也可理解为覆盖所有的可能情况最少使用的测试用例数。简称 CC 。其符号为 VG 或是 M 。

圈复杂度 在 1976 年由 Thomas J. McCabe, Sr. 提出。

简单的说圈复杂度可以表明你的代码逻辑复杂程度和代码质量,会导致代码难以维护,易出错。

衡量标准
圈复杂度 代码状况 建议
0 - 5 清晰 无需重构
5 - 10 略显复杂 建议重构
> 10 比较复杂 强烈建议重构

以下更合理:(看项目代码性质决定)

  • V(G) ∈ [ 0 , 10 ]:代码质量不错;
  • V(G) ∈ [ 11 , 15]:可能存在需要拆分的代码,应当尽可能想措施重构;
  • V(G) ∈ [ 16 , ∞ ):必须进行重构;
计算方法 1. 点边计算法
M = E − N + 2P
  • E: 表示控制流程图中边的数量
  • N:表示控制流程图中节点的数量
  • P:独立组件的数目

流程控制图
控制流程图,是一个过程或程序的抽象表现,是用在编译器中的一个抽象数据结构,由编译器在内部维护,代表了一个程序执行过程中会遍历到的所有路径。它用图的形式表示一个过程内所有基本块执行的可能流向, 也能反映一个过程的实时执行过程。

2.节点判定法

有一个简单的计算方法,就是通过计算所有的判定节点的数量再加上1。判定节点有if else, switch case, for循环,|| 和 &&, 三元运算等等。

例如:

function foo (i) {
    let r = null
    if (i == 'a'’) {
 r = 1
    } else if (i == 'b') {
 r = 2
    } else {
 r = 3
    }
    switch (r) {
 case 1:
     return 'do something with a'
 case 2:
     return 'do something with b'
 case 3:
     return 'do something with c'
 default:
     return r ? 'do nothing' : 'do something you like'
    }
    
}

上面的代码有2个if, 一个switch case判断,包括了3个case,这里要注意下,整个switch case的绩点按照case数量来算,还有一个三元运算,所以圈复杂度是2+3+1+1=7.

如何优化代码

理论来说最简单的点就是在独立组建中(前端可以理解在一个function)少一点if else, switch case, for循环,&& 和 ||以及三元运算符等等。

那么优化代码可以分为两大类:

1.fucntion优化
  • 提炼函数-单一指责

    单一职责原则:每个类都应该有一个单一的功能,一个类应该只有一个发生变化的原因。
    上面代码可以优化如下:

    function foo (i) {
        let r = null
        if (i == 'a'’) {
     r = 1
        } else if (i == 'b') {
     r = 2
        } else {
     r = 3
        }
        doThings(r)
    }
    
    function doThings (r) {
        switch (r) {
     case 1:
         return 'do something with a'
     case 2:
         return 'do something with b'
     case 3:
         return 'do something with c'
     default:
         return r ? 'do nothing' : 'do something you like'
        }
    }
    
2.判断节点优化

简单点就是利用一切方法消灭判断节点,可以利用对象,数组等其他任何合理方式。

  • 抽象成对象配置

    对于一些判断执行类的业务可以抽象成对象的形势,合理利用对象键值对避免使用冗余的判断节点。
    对于上面的代码可以如下优化:

    function foo (i) {
        
        let r = null
        
        if (i == 'a'’) {
     r = 1
        } else if (i == 'b') {
     r = 2
        } else {
     r = 3
        }
        
        const obj = {
     0: r ? 'do nothing' : 'do something you like',
     1: 'do something with a',
     2: 'do something with b',
     3: 'do something with c'
        }
        
        return obj[r]
        
    }
    

    看上面的例子将判断缩减3,圈复杂度就等于2+1+1=4,其实我们的代码还有很多带优化的地方,需要大家自己去研究,这里就不一一举例了。

如何查看代码的圈复杂的 1.eslint规则

eslint提供了检测代码圈复杂度的rules:
我们开启eslint的rules的complexity规则,max表示允许最大圈复杂度,eslint就会报警代码的圈复杂度

rules: {
    complexity: [
 'warn', { max:0 }
    ]
}

但是这样只能一个一个文件的看,看不到项目代码整体的数据,刚好eslint有个CLIEngine(文档),它类似提供一个cli功能,下面我们介绍下如何使用:

const eslint = require('eslint')

const { CLIEngine } = eslint;

const cli = new CLIEngine({
    parserOptions: {
 ecmaVersion: 2018,
 sourceType: "module", // 允许script引入的js
 ecamFeatures: {
     jsx: true // 允许扫描jsx文件
 }
    },
    
    rules: {
 complexity: [
     'error',
     { max: 1 }
 ]
    },
    useEslintrc: true // 使用 eslintrc的配置
});

注: 对于vue文件我们需要配置vue-eslint-parser先解析vue文件
配置.eslintrc.js

module.exports = {
    extends: "eslint:recommended",
    parser: "vue-eslint-parser",
}

配置完成后,使用executeOnFiles对指定文件扫描,获得结果并过滤返回,

const reports = cli.executeonFiles(['.']).results;

for (let i = 0; i < reports.length; i++) {
    const { messages } = reports[i];
    for (let j = 0; j < messages.length; j++) {
 const { message, ruleId } = messages[j];
 if (ruleId === 'complexity') {
      console.log(message);
 }
    }
}

这样我们就能拿到所有我想要的文件的圈复杂度数据了,结果展示,
results:

results: [
 {
     filePath: "./myfile.js", // 提取
     messages: [
  {
      ruleId: 'complexity', // 只条件
      severity: 2,
      message:
'Function 'fmtNumber' has a complexity of 2. Maximum allowed is 1.', // 提取
      line: 8, // 提取
      column: 1, // 提取
      nodeType: 'FunctionDeclaration',
      messageId: 'complex',
      endLine: 15,
      endColumn: 2 
  }
     ],
     errorCount: 1,
     warningCount: 0
 }
    ],

这样对有用的数据提取并汇总,就能统计项目的整体复杂度了

结果展示


小结

希望看完本文能最你有以下帮助:

  • 理解圈复杂的计算和意义
  • 提升项目代码质量,注重圈复杂度使用

下面是圈复杂度统计的统计工具

cli工具——concc

代码圈复杂度检测(check-cycle-complexity)源码:github

欢迎使用。

详细使用移步github

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/244049.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号