您好!
欢迎来到京东云开发者社区
登录
首页
博文
课程
大赛
工具
用户中心
开源
首页
博文
课程
大赛
工具
开源
更多
用户中心
开发者社区
>
博文
>
重构指标之如何监控代码圈复杂度
分享
打开微信扫码分享
点击前往QQ分享
点击前往微博分享
点击复制链接
重构指标之如何监控代码圈复杂度
自猿其说Tech
2022-08-02
IP归属:未知
32360浏览
测试
### 1 引言 软件应用在发展到适当时机,"重构",是开发过程中不可避免需要进行的一项工作。重构代码,以适配当前模块设计之初未考虑到的多样化场景,并增加模块的可维护性、健壮性、可测试性。那么,如何明确重构的方向,以及量化重构的结果呢?代码圈复杂度可以是一个供选择的指标。下文介绍如何获取应用的代码圈复杂度做到线上监控,给到复盘程序复杂程度的数据支撑。 ### 2 背景知识 #### 2.1 圈复杂度 圈复杂度(Cyclomatic complexity,简写CC)也称为条件复杂度,是一种代码复杂度的衡量标准。由托马斯·J·麦凯布(Thomas J. McCabe, Sr.)于1976年提出,用来表示程序的复杂度,其符号为VG或是M。它可以用来衡量一个模块判定结构的复杂程度,数量上表现为独立现行路径条数,也可理解为覆盖所有的可能情况最少使用的测试用例数。圈复杂度大说明程序代码的判断逻辑复杂,可能质量低且难于测试和维护。程序的可能错误和高的圈复杂度有着很大关系。 #### 2.2 圈复杂度计算方式 常用结构圈复杂度计算 - 顺序结构:顺序结构复杂度为1。 - if-else-else、switch-case:每增加一个分支,复杂度增加1,&& 、|| 运算也为一个分支。 - 循环结构:增加一个循环结构,复杂度增加1。 - return:增加一条return语句,复杂度将加1。 #### 2.3 圈复杂度度量标准 ![](//img1.jcloudcs.com/developer.jdcloud.com/ad66cc90-1cdf-4cf8-8af0-a1507c239d6520220728143129.png) 如上列出行业内相对认可的度量数据,实际这个完全是看自己的业务体量和项目情况来决定的。假设你的业务很简单,而且是个单体应用,功能都是很简单的CRUD,那你的圈复杂度即使想上去也没有那么容易。此时你就可以选择把圈复杂度的重构阈值设定为10. 假设你的业务十分复杂,而且涉及到多个其他的微服务系统调用,再加上各种业务中的corner case的判断,圈复杂度上100可能都不在话下。 #### 2.4 降低圈复杂度方法 1)函数提炼与拆分,单一职责 - 拆分成子函数 - 每个函数要有明确的功能实现,不要为了追求行数少而合并功能实现 - 逻辑模块和数据模块要区分开编写 2)优化算法 - 减少不必要条件、循环分支,尽量少用 if …else … ,采用三元表达式替换if else 3)表达式逻辑优化 - 合并条件表达式,比如使用a || b || c 4)减少提前return ### 3 方案概述 #### 3.1 脚本设计 1)开发语言 - python 2)依赖环境 - lizard - APScheduler - smtplib - pymysql 3)脚本架构 ![](//img1.jcloudcs.com/developer.jdcloud.com/f35f850f-21fd-47ff-b873-945555087e6920220728143255.png) #### 3.2 功能介绍 1)支持检索语言范围: 支持15种开发语言,包含常用语言如下 - C/C++ (works with C++14) - Java - C# (C Sharp) - JavaScript (With ES6 and JSX) - Python - Golang 2)扫描参数配置说明: 利用lizard执行扫描,常用命令如下: **配置检查范围:** - 列出要分析的编程语言。如果留空,将搜索支持的所有语言。 ``` -l LANGUAGES, --languages LANGUAGES ``` - 排除与模式匹配的文件。*匹配一切?匹配任何单个字符,“/folder/*”递归地排除文件夹中的所有内容。可以指定多个模式。不要忘了在模式周围加“”号。 ``` -x EXCLUDE, --exclude EXCLUDE ``` - 设置白名单, 默认'./whitelizard.txt' ``` -W WHITELIST, --whitelist WHITELIST ``` **配置阀值警告:** - 圈复杂度数警告的阈值,默认值为15,>15会产生警告。 ``` -C CCN, --CCN CCN ``` - 设置字段的限制数。可以代码行数,圈复杂度,令牌数,参数数或自定义字段。如果函数设置超过了限制数会报警。 ``` -T THRESHOLDS, --Threshold THRESHOLDS ``` **配置报告输出:** - 根据格式输出到文件 ``` -o OUTPUT_FILE, --output_file OUTPUT_FILE ``` 官网地址:http://www.lizard.ws 源码地址:https://github.com/terryyin/lizard 3)定时执行扫描任务: - 通过BackgroundScheduler创建调度任务,自动触发扫描方法,结果写库 ```python def dojob(): scheduler = BackgroundScheduler() scheduler.add_job(func, "cron", hour=21, minute=30) scheduler.start() ``` #### 3.3 结果展示 ##### 3.3.1 报告名词解释 - Cyclomatic complexity,圈复杂度也就是分支复杂度,最好保持在15 以下,目前脚本设置阀值10。 - LOC,包含注释的代码行数,目前设置200阀值。 - Token count ,token的个数,一个程序最多可以有 8192 个令牌, 每个令牌都是一个词,例如关键字,标识符,常量,标点符号,操作符。 对括号和字符串计数作为 1 个令牌。 逗号、句点、LOCAL、分号、END 和注释不计算在内。 - Parameter count,参数统计就是函数的参数个数,目前脚本设置阀值10。 ##### 3.3.2 执行结果展示 - Windows环境运行脚本,输入file_root(文件地址)执行扫描,支持自动弹出浏览器展示本次运行的Html报告 ![](//img1.jcloudcs.com/developer.jdcloud.com/e0deb156-7e8c-4423-8f81-c5010e3eac7c20220728143730.png) - 每周定期执行,按照系统维度扫描,支持触发邮件通知对应系统研发查看超过阀值方法名称 ![](//img1.jcloudcs.com/developer.jdcloud.com/88f8ef61-04cd-4240-8e87-39514cf7315820220728143819.png) ##### 3.3.3 应用数据监控 - 每周定期拉取指定分支最新代码,执行文件分析,存储扫描结果,通过数据图表展示 ![](//img1.jcloudcs.com/developer.jdcloud.com/faedf6ef-da71-4c3a-a2f9-e9fbeb185aa020220728143845.png) ### 4 总结 对于软件代码好坏的衡量,圈复杂度可以作为一个参考指标,研发可以通过提炼拆分函数、优化算法、优化逻辑表达式等方法降低模块(函数)圈复杂度。以上阐述圈复杂度一种线上监控方法,利用好线上化数据,结合现有团队项目情况,才能形成更好的实践机制。 ------------ ###### 自猿其说Tech-JDL京东物流技术与数据智能部 ###### 作者:刘红妍
原创文章,需联系作者,授权转载
上一篇:研发提测前测试到底能做些什么
下一篇:测试角色在项目各阶段的项目管理tips
相关文章
安全测试之探索windows游戏扫雷
Jmeter压测实战:Jmeter二次开发之JSF采样器实现
Laputa自动化测试框架介绍
自猿其说Tech
文章数
426
阅读量
2149964
作者其他文章
01
深入JDK中的Optional
本文将从Optional所解决的问题开始,逐层解剖,由浅入深,文中会出现Optioanl方法之间的对比,实践,误用情况分析,优缺点等。与大家一起,对这项Java8中的新特性,进行理解和深入。
01
Taro小程序跨端开发入门实战
为了让小程序开发更简单,更高效,我们采用 Taro 作为首选框架,我们将使用 Taro 的实践经验整理了出来,主要内容围绕着什么是 Taro,为什么用 Taro,以及 Taro 如何使用(正确使用的姿势),还有 Taro 背后的一些设计思想来进行展开,让大家能够对 Taro 有个完整的认识。
01
Flutter For Web实践
Flutter For Web 已经发布一年多时间,它的发布意味着我们可以真正地使用一套代码、一套资源部署整个大前端系统(包括:iOS、Android、Web)。渠道研发组经过一段时间的探索,使用Flutter For Web技术开发了移动端可视化编程平台—Flutter乐高,在这里希望和大家分享下使用Flutter For Web实践过程和踩坑实践
01
配运基础数据缓存瘦身实践
在基础数据的常规能力当中,数据的存取是最基础也是最重要的能力,为了整体提高数据的读取能力,缓存技术在基础数据的场景中得到了广泛的使用,下面会重点展示一下配运组近期针对数据缓存做的瘦身实践。
自猿其说Tech
文章数
426
阅读量
2149964
作者其他文章
01
深入JDK中的Optional
01
Taro小程序跨端开发入门实战
01
Flutter For Web实践
01
配运基础数据缓存瘦身实践
添加企业微信
获取1V1专业服务
扫码关注
京东云开发者公众号