软件架构的可维护性指标——代码圈复杂度

news2024/11/19 13:20:26

代码圈复杂度

    • 1、目的
    • 2、前言
    • 3、简介
    • 4、案例
    • 5、降低
    • 6、插件
    • 7、总结

1、目的

区别于常规的高内聚、低耦合、抽象、封装这种定性的指标,我想通过对软件架构可维护性的可量化的指标的分享,帮助大家在日常的开发工作中,有一个更为广阔的视角去审视我们编写的代码。即编写代码时,如果相关量化指标数据升高且超过一定的阈值,那么反问自己一下,当前的编码逻辑方便阅读吗?


2、前言

软件架构是软件开发和维护过程中的一个重要制品,是软件需求和设计、实现之间的桥梁。软件架构的开发和维护是基于架构软件软件生命周期中的重要环节,与之相关的步骤包括导出架构需求、架构开发、架构文档化、架构分析、架构实现和架构维护。软件架构的维护与演化密不可分,维护需要对软件架构的演化过程进行追踪和控制,以保障软件架构的演化过程能够满足需求(亦有说法将架构维护作为架构演化的一个部分)

那么如何衡量软件架构的可维护性呢?官方给出了六个指标

其中圈复杂度 (CCN) 度量整个架构的独立执行路径的条数,该结果值即为待评估架构的最终度量结果;而对于扇入扇出度 (FFC) 、模块间耦合度 (CBO) 、模块的响应 (RFC) 、紧内聚度 (TCC) 、松内聚度 (LCC) 个度量指标,它们针对每个组件进行度量,则待评估架构的最终度量结果为所有组件结果的平均值。


3、简介

由于在组件图中组件是独立的,每个组件代表一个系统或子系统中的封装单位,封装了完整的事务处理行为,组件图能够通过组件之间的控制依赖关系来体现整个系统的组成结构。对架构的组件图进行圈复杂度的度量,可以对整个系统的复杂程度做出初步评估,在设计早期发现问题和做出调整,并预测待评估系统的测试复杂度,及早规避风险,提高软件质量。圈复杂度高的程序往往是最容易出现错误的程序,实践表明程序规模以 CCN小于等于10 为宜。

圈复杂度 = 程序控制流图中分支节点数 + 1,其它计算方法不做过多说明。


4、案例

以项目中的代码片段为例

圈复杂度为37的方法

圈复杂度为10的方法

圈复杂度为5的方法

我们不难发现,圈复杂度越高的代码,往往方法也越长,在阅读代码逻辑时,过长的方法(一屏装不下)和流程细节很影响阅读体验。


5、降低

于其说是降低代码圈复杂度的方法,不如说是常见的代码优化手段:

  • 将条件判定提炼出独立函数
  • 将大函数拆成小函数
  • 以明确函数取代参数
  • 多态方式替代条件式
  • 移除控制标记

更多优化方法可以参考《重构》、《代码整洁之道》等书籍

优化的本质是,该抽象抽象,该封装封装,在面向对象语言(Java)的大背景下,代码首先应该考虑如何自下而上面向对象的设计,而不是考虑如何自上而下的流程编码。


6、插件

metricsreloaded

Method metrics:

  1. ev(G)(Essential Complexity (ev(G)):基本复杂度是用来衡量程序非结构化程度的,非结构成分降低了程序的质量,增加了代码的维护难度,使程序难于理解。因此,基本复杂度高意味着非结构化程度高,难以模块化和维护。实际上,消除了一个错误有时会引起其他的错误。
  2. Iv(G)(Module Design Complexity (iv(G))):模块设计复杂度是用来衡量模块判定结构,即模块和其他模块的调用关系。软件模块设计复杂度高意味模块耦合度高,这将导致模块难于隔离、维护和复用。模块设计复杂度是从模块流程图中移去那些不包含调用子模块的判定和循环结构后得出的圈复杂度,因此模块设计复杂度不能大于圈复杂度,通常是远小于圈复杂度。
  3. v(G)(Cyclomatic Complexity (v(G))):衡量圈复杂度,数量上表现为独立路径的条数,即合理的预防错误所需测试的最少路径条数,圈复杂度大说明程序代码可能质量低且难于测试和维护,经验表明,程序的可能错误和高的圈复杂度有着很大关系。

Class metrics:

  1. OCavg:代表类的方法的平均循环复杂度
  2. WMC:总循环复杂度

Package metrics:包复杂度

  1. v(G)avg:圈复杂度
  2. v(G)tot:总复杂度

Module metrics:模块复杂度

  • 同上

Project metrics:项目复杂度

  • 同上

7、总结

再次说明我们的目的不是去追求降圈复杂度的代码,因为过低的圈代码复杂度也不是最佳实践。而是要以有利架构维护的前提下,尽可能的提高代码的可读性。在开头的分享目的中提到,圈复杂度这一量化指标的提出,是帮助我们去审视编写的代码是否具有可读性。那么如何审视呢?

  1. 编写新业务流程时,当我们意识到方法过长或者圈复杂度过高时,应该考虑到需要对执行的流程进行抽象,至于抽象的方法是否需要满足xx设计、是否需要考虑未来的扩展,如果开发时间不允许,完全可以定义为private方法,而这个方法大概率也只有你自己会用。换个思路,将流程式的代码片段放在主逻辑中,也没有想要给给别人用。
  2. 维护业务时,当我们意识到新增的业务流程会影响原流程的圈复杂度,并且圈复杂度超过了可接受的值,那么维护相关的代码则需要考虑是否需要抽象,抽象程度同理

屎山代码往往不是一个人造成的,而我们能做的也只有做好自己



测试驱动的开发较低圈复杂度值 之间存在着紧密联系。

因为在编写测试用例时,开发人员会首先考虑代码的可测试性,从而倾向编写简单的代码(因为复杂的代码难以测试)。

一个好的测试用例设计经验是:创建数量与被测代码圈复杂度值相等的测试用例,以此提升测试用例对代码的分支覆盖率。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1199846.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

No181.精选前端面试题,享受每天的挑战和学习

🤍 前端开发工程师(主业)、技术博主(副业)、已过CET6 🍨 阿珊和她的猫_CSDN个人主页 🕠 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 🍚 蓝桥云课签约作者、已在蓝桥云课上架的前后端实战课程《Vue.js 和 Egg.js 开发企业级健康管理项目》、《带你从入…

共享内存原理和实现

实现原理 实现函数 1,ftok--shmget--shmat--shmdt shmget用于分配映射物理内存的虚拟内存。 怎么保证不同进程访问同一块物理内存呢 key_t ftok(const char *pathname, int proj_id); ftok的第一个参数是一个文件,只要使用同一个文件进行映射&#x…

STM32F4之看门狗

1、 看门狗作用 单片机复位的方式:硬件复位 -- reset按键 上电复位 -- 电容 看门狗复位 看门狗的复位功能主要是用于一些平常难以操作的场合去帮助我们进行复位操作。当你单片机突然死机或者程序跑飞了,看门狗就可以检测得到并且及时帮你复位。看门狗也可…

74hc595模块参考

74hc595模块参考 8位串行并行输出(SIPO)移位寄存器 使用74HC595移位寄存器扩展微控制器上的输出引脚数量。如果你需要扩充输入引脚的数量那么你需要74HC165移位寄存器。 SER(串行输入)引脚用于一次一位地将数据发送到移位寄存器…

(离散数学)逻辑连接词

异或可以理解为不同为1相同为0 P->Q的前件和后件满足0->1的其中一个就为真 <—>可以看做 &#xff0c;相同为1不同为0 异或与等价相反

Torch Hub 系列#2:VGG 和 ResNet

一、说明 在上一篇教程中,我们了解了 Torch Hub 背后的本质及其概念。然后,我们使用 Torch Hub 的复杂性发布了我们的模型,并通过相同的方式访问它。但是,当我们的工作要求我们利用 Torch Hub 上提供的众多全能模型之一时,会发生什么? 在本教程中,我们将学习如何利用称为…

MySQL:日志系统

目录 概述错误日志&#xff08;error log&#xff09;慢查询日志&#xff08;slow query log&#xff09;一般查询日志( general log )中继日志&#xff08;relay log&#xff09;Buffer Pool 缓存回滚日志&#xff08;undo log)概述undo log 作用undo log 的存储机制Undo log …

WorkPlus Meet:局域网内部使用的高效视频会议系统

随着全球化和远程办公的趋势&#xff0c;视频会议已成为现代企业和机构不可或缺的沟通工具。而现在&#xff0c;大多数政企单位或者涉密强的企业&#xff0c;都会使用局域网部署的音视频会议系统&#xff0c;提供更高的安全性和隐私保护。因为音视频会议中可能涉及到公司机密和…

Angular 使用教程——基本语法和双向数据绑定

Angular 是一个应用设计框架与开发平台&#xff0c;旨在创建高效而精致的单页面应用 Angular 是一个基于 TypeScript 构建的开发平台。它包括&#xff1a;一个基于组件的框架&#xff0c;用于构建可伸缩的 Web 应用&#xff0c;一组完美集成的库&#xff0c;涵盖各种功能&…

基于SSM的考研图书电子商务平台的设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;Vue 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#xff1a;是 目录…

HDMI之编码篇

概述 HDMI 2.0b(含)以下版本,采用3个Channel方式输出。传输又分为3三种周期,视频数据,数据岛以及控制周期。视频传输采用8/10编码。数据岛采用4/10编码(TERC4)。控制周期采用2/10。编码都拓展成了10bits。 上图中,Pixel component(e.g.B)->D[7:0]表示视频数据周期…

linux之IPC

linux之IPC 什么是IPC共享内存(shm)ftokshmgetshmatshmdtshmctl 消息队列msggetmsgrcvmsgsndmsgctl 旗语(信号量)semgetsemctlsemopsem三级标题三级标题 ipc命令守护进程查看守护进程 什么是IPC IPC: Inter(内核) Process(进程) Communicton&#xff08;通信&#xff09; 共享内…

【Delphi】 各个平台使用 ntfy 效果说明

目录 一、Delphi 中使用 ntfy 库下载地址 二、各个平台使用效果说明 1. android 平台 2. ios 平台 3. windows 平台 三、总结 一、Delphi 中使用 ntfy 库下载地址 官方的文档地址&#xff1a;ntfyDelphi 接口库地址&#xff1a;GitHub - hazzelnuts/ntfy-for-delphi at …

冯·诺依曼结构

一、约翰冯诺依曼---计算机之父 约翰冯诺依曼&#xff08;John von Neumann&#xff0c;1903年12月28日—1957年2月8日&#xff09;&#xff0c;出生于匈牙利布达佩斯&#xff0c;匈牙利裔美籍数学家、计算机科学家、物理学家和化学家&#xff0c;美国国家科学院院士&#xff…

OpenCV:图像旋转与缩放

人工智能的学习之路非常漫长&#xff0c;不少人因为学习路线不对或者学习内容不够专业而举步难行。不过别担心&#xff0c;我为大家整理了一份600多G的学习资源&#xff0c;基本上涵盖了人工智能学习的所有内容。点击下方链接,0元进群领取学习资源,让你的学习之路更加顺畅!记得…

Java Web——TomcatWeb服务器

目录 1. 服务器概述 1.1. 服务器硬件 1.2. 服务器软件 2. Web服务器 2.1. Tomcat服务器 2.2. 简单的Web服务器使用 1. 服务器概述 服务器指的是网络环境下为客户机提供某种服务的专用计算机&#xff0c;服务器安装有网络操作系统和各种服务器的应用系统服务器的具有高速…

linux入门---自旋锁和读写锁

自旋锁 首先通过一个例子来带着大家理解自旋锁&#xff0c;在生活中大家肯定都等过人比如你们一家人准备出去玩可是出发的时候妻子发现自己还没有化妆于是连忙赶回了家这个时候其他人就得在楼下等着&#xff0c;但是这个等又分为两种情况第一种是真的在楼下等其他的什么事都没…

Nginx:不同域名访问同一台机器的不同项目

Nginx很简单就可以解决同一台机器同时跑两个或者多个项目&#xff0c;而且都通过域名从80端口走。 以Windows环境下nginx服务为例&#xff0c;配置文件nginx.conf中&#xff0c;http中加上 include /setup/nginx-1.20.1/conf/conf.d/*.conf;删除server部分&#xff0c;完整如…

RT-Thread Studio开发 新手入门

文章目录 前言一、RT-Thread Studio 与 STM32CubeMX 下载安装二、新建工程三、点亮LED灯四、按键中断五、串口通信六、OLED显示 前言 软件开发环境&#xff1a;RT-Thread Studio、STM32CubeMX 硬件&#xff1a;STM32F407ZGT6 一、RT-Thread Studio 与 STM32CubeMX 下载安装 …

【图像处理:OpenCV-Python基础操作】

【图像处理&#xff1a;OpenCV-Python基础操作】 1 读取图像2 显示图像3 保存图像4 图像二值化、灰度图、彩色图&#xff0c;像素替换5 通道处理&#xff08;通道拆分、合并&#xff09;6 调整尺寸大小7 提取感兴趣区域、掩膜8 乘法、逻辑运算9 HSV色彩空间&#xff0c;获取特定…