代码质量管理
代码质量管理是指在软件开发过程中,通过采取一系列的管理措施,使得软件代码的质量达到一定标准的过程。
它旨在提高代码的可读性、可维护性、可测试性以及减少潜在的缺陷和Bug。
代码质量管理是一个持续的过程,它涵盖了从项目初期的编码阶段到软件交付和维护的整个生命周期。
代码质量管理包含以下几个关键方面:
- 编码规范和标准:制定并强制执行统一的编码规范和标准,确保团队成员按照相同的规则,书写代 码,提高代码的一致性和可读性
- 单元测试:建立自动化测试框架,编写单元测试、集成测试和端到端测试等,以便在代码变更后快速检测和验证代码是否符合预期行为,确保代码的正确性和稳定性
- 静态代码分析:使用静态代码分析工具扫描代码,发现代码潜在的缺陷、漏洞和代码异味等等。
- 文档与注释:编写清晰的文档和注释,以便于他人理解代码的设计和实现。
代码质量管理是软件开发过程中至关重要的一环,它对于个人开发者、开发团队和整个项目的成功都具有重要影响。良好的代码质量管理具有以下几个作用。
- 提高代码可维护性和可读性:高质量的代码易于理解和维护。通过编写清晰、可读性好且符合规范的代码,开发者可以更轻松地理解其功能和逻辑,降低团队成员之间的一个沟通成本。当需要进行修改、扩展或修复时,开发者更容易找到问题所在并进行相应的操作。
- 提高代码可靠性和稳定性:低质量的代码容易导致软件的漏洞、错误和异常。
- 提高开发效率:良好的代码质量管理可以提高开发效率。通过使用自动化的工具和流程来进行代码质量检查和分析,开发者可以及时发现问题并进行修复,避免问题逐渐累积和扩大。这样可以减少后期修复问题和重构代码的工作量,提高开发速度和工作效率。
一个好的代码质量管理如此重要,那么如何做到呢,今天主要围绕静态代码分析的入手。
静态代码扫描工具
当前市面上有许多静态代码扫描工具,这里主要介绍以下几种常见的工具。
工具名称 |
支持语言 |
主要特点 |
可扩展性 |
可视化报告 |
SonarQube |
多种语言 |
综合代码质量管理平台,强大的静态分析 |
支持插件扩展 |
丰富的Web界面 |
FindBugs |
Java |
检测常见的Java代码缺陷 |
较轻量级 |
无 |
Checkstyle |
Java |
强制执行一致的编码风格和规范 |
无 |
无 |
PMD |
多种语言 |
多语言支持,可检测重复代码和低效代码 |
支持自定义规则 |
无 |
ESLint |
JavaScript/TypeScript |
静态分析工具,发现错误和不符合规范的代码 |
支持自定义规则 |
无 |
sonarQube相比其他的工具的优势体现
- 扫描语言的种类有Java,C#,JavaScript,python,C/C++,go等等多种语言。
- 可扩展性更强,支持插件扩展。可以在插件管理中添加PMD,FindBugs等分析工具。
- 可视化展示,提供了一个Web界面将分析结果直观的展示给用户。
静态代码分析:在不执行代码的情况下对代码进行分析,通过检查代码的静态结构、语法和规则来发现潜在的问题。
动态代码分析:在代码执行过程中对代码进行分析。它通过模拟和运行代码来收集运行时的数据和信息,用于检测代码中的问题。
SonarQube简介
SonarQube的整体架构如图所示,包含了一个SonarScanner命令行工具客户端,该客户端提供一些配置参数到sonarQube服务端,具体的扫描计算的逻辑是在服务端进行,最终分析得到的数据将会存储在所配置连接的数据库中。
# 指定项目的唯一标识符
sonar.projectKey=my-project
# 指定项目的名称
sonar.projectName=My Project
# 指定项目的版本
sonar.projectVersion=1.0
# 指定项目的源代码路径
sonar.sources=src
# 指定要排除的文件或文件夹
sonar.exclusions=**/vendor/**, **/node_modules/**
# 配置SonarQube服务器的位置以及链接token,可在CICD工具中配置
sonar.host.url=//localhost:9000
# 配置其他静态代码分析参数
sonar.language=java
sonar.java.binaries=target/classes
SonarQube服务端提供了一套全面的规则,用于检测代码中的潜在缺陷、漏洞、代码重复以及编码规范的合规性。
其主要功能包括:
- 静态代码分析与代码质量度量:SonarQube利用静态代码分析技术对代码进行全面检查,发现并报告代码中的潜在问题和不良实践。这包括代码错误、安全漏洞、代码异味、代码重复率、测试覆盖率等。
- 规范和合规性:SonarQube支持自定义规则和规范,也内置了许多常见的规则集。这些规则用于检查代码是否符合编码规范和最佳实践,以确保代码的一致性和可读性。
- 持续集成和交付:SonarQube可以与持续集成工具(如Jenkins、GitLab等)集成,使得代码质量分析成为开发过程中的一部分。这样可以早期发现和解决问题,避免质量问题逐渐积累并影响整个项目。
- 扫描报告的查看:扫描完成之后,sonarQube可以提供扫描报告的结果,并给出修改建议。
SonarQube的主要功能
1、静态代码分析与代码质量度量
SonarQube利用静态分析技术扫描代码,识别出潜在的问题和缺陷,包括以下几个方面。
Bugs(缺陷/错误):
Bugs是指代码中的错误或潜在的错误,可能导致应用程序在运行时出现异常或不正确的行为。
- 空指针引用
- 除零错误
- 未捕获的异常:没有相关的异常处理机制来捕获和处理异常
- 数组越界
- 类型转换错误:不匹配的类型转换或者精度丢失
- 资源泄露:未正确释放或者关闭使用的资源,例如文件,数据库连接,网络连接等等
- 并发问题:多线程中存在竞态条件、死锁或者数据竞争问题。
Vulnerabilities(安全漏洞):
Vulnerabilities是指代码中存在的安全漏洞或弱点,可能被攻击者利用来执行恶意操作或访问敏感数据来入侵系统。
- 跨站脚本攻击(Cross-Site Scripting):代码中可能存在未正确过滤或转义用户输入数据的地方,导致恶意脚本被注入到网页中,攻击者可利用它们窃取用户信息或进行其他恶意操作。
- SQL注入:直接拼接用户输入到SQL查询语句中的情况。
- 假设一个登录页面要求用户输入用户名和密码进行身份验证,并使用这些输入构建SQL查询语句来检查用户的凭据是否匹配。而这个页面没有对用户输入进行正确的验证和转义处理.
SELECT * FROM users WHERE username = '输入的用户名' AND password = '输入的密码';
输入的用户名:admin' OR '1'='1 输入的密码:' OR '1'='1
SELECT * FROM users WHERE username = 'admin' OR '1'='1' AND password = '' OR '1'='1';
1=1总是为真,就会绕过正常的身份验证逻辑,导致系统返回所有的用户的记录。
mybias:使用#{}替代${},一个是构建参数化查询,一个是占位符。
- 非安全的文件处理:可能存在未正确验证用户上传的文件或者文件路径的地方,导致恶意文件的执行、覆盖或者下载
- 不安全的密码处理:例如硬编码的密钥、密码存储不安全等
- 安全配置问题:检测代码中是否存在安全配置不当的问题,比如弱密码策略、未禁用调试模式。
Code Smells(代码异味):
Code smells是指代码中的不良编码实践或结构模式,虽然不一定是错误或安全漏洞,但可能导致代码难以理解、维护困难或性能下降。
- 重复代码块
- 过长的方法或者函数:难以理解和维护
- 过长的类和模块:包含了过多的责任,不符合单一职责原则,难以修改扩展
- 复杂的条件逻辑:过多的if-else,嵌套的条件语句或者负复杂的布尔表达式等等
- 过多的参数:参数列表过长
- 过多的全局变量:增加了代码的耦合性
Coverage(覆盖率):
它衡量了在代码中有多少行、语句、分支或函数被自动化测试覆盖到。
Duplications(重复代码):
重复代码是指在代码库中出现重复的代码片段或代码模式。这可能是因为复制粘贴、复制错误、不正确的重构等原因导致的。
Technical Debt Ratio(技术债务率):
衡量的是修复所有可维护性问题所需的工作量,单位为分钟。当该值以天为单位展示时默认为8小时/天。
技术债务比率=项目的技术债务的成本/从零开始重写代码所需的成本(代码规模)
较高的技术债务比例意味着较多的代码质量问题和维护成本。
可以看到这个图的每个指标的右上角都有一个等级 A B C D,根据每种类别问题的严重程度划分的。

sonarQube在划分了不同问题类别之下,还对问题的一个严重程度进行了区分。从重要程度依次划分为以下五个类别。
Blocker(阻断级别):表示临界的缺陷,会导致系统崩溃、无法正常运行或存在严重的安全漏洞,通常需要立即解决该级别的缺陷。
Critical(严重级别):表示关键的缺陷,可能导致重要的功能异常或存在安全漏洞,需要及时解决,确保系统的稳定性和安全性。
Major(重要级别):可能导致功能错误,性能问题或者存在潜在的安全隐患。
Minor(次要级别):表示较小的缺陷,通常是一些代码规范或约定问题。
Info(信息级别):通常涉及与代码质量无关的信息性问题。
通常需要关注的前三个程度级别的问题并对其进行修复,这类问题较大可能影响项目的功能运行。

通常出现了C评级及其以下,需要引起用户的注意。
对于Bugs
A:表示代码无bug,最高级别
B:代码有一个次要bug,等级评估为B
C:代码有一个重要bug,等级评估为C
D:代码有一个严重bug,等级评估为D
E:代码有一个阻断bug,等级评估为E,最低级别。
对于Vulnerabilities(漏洞):
A:表示代码无漏洞,最高级别
B:代码有一个次要漏洞,等级评估为B
C:代码有一个重要漏洞,等级评估为C
D:代码有一个严重漏洞,等级评估为D
E:代码有一个阻断漏洞,等级评估为E,最低级别。
对于技术债务:评级A到E,分别的默认值为0.05,0.1,0.2,0.5,超过0.5就是评级为E。
2、规则与自定义规则集Quality Profile
这些指标最终都是根据相关的规则集生成的。
规则
sonarQube支持的语言包括Java,C#,JavaScript,python,C/C++,go等等多种语言,针对每种语言,都存在默认的一个规则集对代码进行检测。

比如说,选择java,选择类别为bug,会展示出110条规则,如果不符合这些规则,将会被认为是bug。

由于规则较多,我们选择一个进行查看规则的具体定义
比如这条,代码中不应该出现死循环,同时这里还给出了一些合规和不合规的案例。如果出现了话,将会扫描出一条严重级别为Blocker的Bug数据。
规则集
由一条条规则组成的集合便是规则集,针对每一种语言,sonar都有一套自己的默认规则集,也就是页面上的Quality Profiles选项,具体如图所示。
同样,以java语言为例,默认的规则集都叫做Sonar Way,它包含了一系列通用的,广泛适用的规则,用于检测代码中的常见问题,例如空指针引用,代码重复,未使用的变量等等。
java的默认Sonar Way规则集中包含了315条规则,其中96条bug规则,28条漏洞规则,以及191条代码异味规则。
自定义规则集
同时也可以自定义规则集,在当前的Quality profile中创建一个profile,然后向其中添加不同的规则。构建自定义的规则集。

创建完成之后,点击activate more,可以向里面添加不同的规则。

最后将profile进行激活,就可以使用自定义的规则集。

除此之外,可以使用外部扫描工具带的规则,之前提到,sonarQube支持插件的扩展。
以PMD分析插件举例,当安装PMD外部分析工具插件之后,可以在rules下的repository中找到PMD的规则集进行配置。
3、 质量门Quality Gate
对分析得到的指标可以从整个web页面上看到,如果要对整个项目分析做一个定性的结论,也就是扫描结果是否为通过呢,需要质量门进行一个阈值划分。
当代码提交到sonarqube进行分析时,首先会按照响应的规则进行分析,对于分析得到的结果,例如当前分析出项目中存在多少个bug,多少个code smells,或者当前项目的代码覆盖率等等这些指标。通过定义这些指标的阈值,来确定代码质量的期望水平。这个阈值的指标集合就是Quality Gate,相当于对按照规则生成的分析结果划定一个阈值。
例如,当前通过规则分析得到当前的项目的安全漏洞的数量为15,如果设置质量门其中一个指标为安全漏洞数应该小于10,则当前项目的分析结果将不是Pass,而是Failed。
Quality Gate通常包含了多个条件,每个条件可以定义为一个指标。sonarqube同样给出了一个默认的质量门。与默认规则集不同,针对所有的语言,sonarqube只需要提供一套默认的Sonar Way质量门。

默认的规则包含了五条:
- 新代码的单元测试覆盖率:Coverage
- 新代码上的重复行数:Duplications
- 新代码的可靠性评级:Bugs
- 新代码的可维护性评级:Technical Debt
- 新代码的安全性级:Vunlerbilities
除开默认的之外,sonarqube 还提供了许多其他指标。
同时也可以使用自定义的质量门。

4、 报告查看,修改建议
对分析得到的结果,最终的目的是要解决这个问题

获取到扫描报告之后,点进扫描结果,可以看到具体在哪一行代码出现了什么类别的问题,这里是出现了major级别的bug。
这是由于Thread.interrupt()方法在中断阻塞线程的时候,该线程会抛出InterruptedException同时将线程的中断状态清除为false。因此通常需要在捕获异常的时候再次进行否则,容易进入死循环。