在工作期间我参与过多个开发项目,也认识了很多的开发人员。我注意到一个普遍现象:不同团队成员的编程技能和代码编写习惯存在显著差异。这种差异性在团队合作中可能导致代码理解上的障碍和效率的降低。此外,不规范或质量不佳的代码可能埋下潜在的错误隐患。因此,我在此分享一些方法,说明如何在团队内部实施代码规范以提升整体的代码品质。接下来,我将从选择代码规范、阿里巴巴代码规范插件的使用,以及 Sonar 工具的应用三个方面进行详细阐述。
代码规范选型
首先,让我们探讨代码规范的选择。正如我之前提到的,制定代码规范的主要目的是提升团队的工作效率和代码的整体质量。编写高质量代码是一个多方面的任务,它涵盖了编码过程中的许多细节,包括代码的可读性、性能等方面。作为团队的技术领导者,如何制定一套全面且优秀的代码规范是一个关键问题。总体而言,我们有两种主要的方法:一种是自主开发,另一种是采用业界已经存在的、现成的规范。
我的建议是选择那些在业界已经成熟并广泛使用的代码规范,因为它们内容全面,且拥有良好的生态系统,能够与其他应用程序无缝集成。
此外,许多成熟的代码规范还提供了扩展点,使我们能够扩展和定制自己的规范。由于这些规范已经为我们定义了基本框架,我们只需进行少量工作即可实现自己的规范。综上所述,我们的策略应该是选择成熟的方案,并根据需要进行扩展。
目前,业界广泛使用且较为成熟的代码规范主要有两个:
-
阿里巴巴代码规范( github.com/alibaba/p3c...
-
Sonar 代码规范( www.sonarqube.org)
阿里巴巴的代码规范是阿里巴巴工程师团队根据 Java 开发的各项需求总结而成的一套规范。这套规范已经被编纂成书,并且可以在 GitHub 上免费获取。此外,这套规范还提供了集成开发环境(IDE)和 Maven 的插件支持。
Sonar 是一个代码质量管理平台。包含一整套工具,比如可视化 Web 界面、丰富的插件、对持续集成工具的支持,另外,Sonar 支持大部分开发语言。
需要说明一下,这两个代码规范不是非此即彼的,可以在项目中同时使用。
那么当我们制定了合理的代码规范,让大家去遵循就行了吗?不是的,这只是一个好的开始,很多团队在落地代码规范的时候遇到了困难,比如大部分开发人员在编码时并不能及时意识到某些代码是不规范的。所以,我们就需要借助一些工具,来发现不规范代码,并进行修复。这个工具最好是和 IDE 深度集成的,我们在编码的同时就能使用,而无需离开当前的编码环境。
而我今天要介绍的两个代码规范,也就是刚才提到的阿里巴巴代码规范和 Sonar 代码规范都提供了丰富的插件。接下来我会给你分别进行说明。
如何使用阿里巴巴代码规范插件
首先,让我们看看阿里巴巴代码规范的插件,它包括了 IDE 插件和 PMD 插件。
IDE 插件
阿里巴巴代码规范为大部分主流 IDE 都提供了插件,今天我就以使用最多的 IDEA 为例,说明一下如何在 IDEA 中安装和使用这个插件。
首先,怎么安装 IDEA 插件呢?
我们打开插件市场(Preference > Plugin > Marketplace),搜索并安装插件"Alibaba Java Coding Guidelines"。
安装插件完成后,它将在 IDEA 中增加一些新的菜单选项。你可以通过在项目、包或文件上打开菜单,选择"编码规约扫描"功能来进行代码规范检查。扫描结果将在 IDEA 的底部面板中展示。
建议团队中的每个成员都安装这个插件,以便在编码过程中能够及时发现并修正不规范的代码。使用阿里巴巴代码规范插件相对简单,通常不需要特殊的配置步骤。但有一点需要特别提醒,该插件建议为每个类添加作者信息。插件将提供智能提示,一旦选择应用,它将自动添加信息。但默认情况下,作者信息会显示为操作系统的当前用户。在大多数情况下,这与我们预期的格式并不一致。你可以打开 Help > Edit custom VM options。,然后添加一个 JVM 参数来设定合适的作者信息,例如使用公司邮箱的前缀或者中文姓名等。
ini
-Duser.name=xiao.ming
PMD 插件
接下来,我将向你介绍如何利用 PMD 插件强制执行代码规范检查,并在 CI/CD 流程中设置质量控制点。PMD 是一个支持多种编程语言的开源静态代码分析工具。你可以在 pom.xml 文件中集成 PMD 插件,这样在 Maven 构建应用程序(使用 mvn install 或 mvn package 命令)时,PMD 插件将自动执行代码规范检查,识别出不合规的代码。你可以参照以下阿里巴巴代码规范 PMD 插件的配置示例进行设置:
xml
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-pmd-plugin</artifactId>
<version>3.10.0</version>
<configuration>
<sourceEncoding>UTF-8</sourceEncoding>
<targetJdk>1.8</targetJdk>
<printFailingErrors>true</printFailingErrors>
<rulesets>
<ruleset>rulesets/java/ali-comment.xml</ruleset>
<ruleset>rulesets/java/ali-concurrent.xml</ruleset>
<ruleset>rulesets/java/ali-constant.xml</ruleset>
<ruleset>rulesets/java/ali-exception.xml</ruleset>
<ruleset>rulesets/java/ali-flowcontrol.xml</ruleset>
<ruleset>rulesets/java/ali-naming.xml</ruleset>
<ruleset>rulesets/java/ali-oop.xml</ruleset>
<ruleset>rulesets/java/ali-orm.xml</ruleset>
<ruleset>rulesets/java/ali-other.xml</ruleset>
<ruleset>rulesets/java/ali-set.xml</ruleset>
</rulesets>
<failurePriority>5</failurePriority>
<maxAllowedViolations>20</maxAllowedViolations>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>com.alibaba.p3c</groupId>
<artifactId>p3c-pmd</artifactId>
<version>2.0.1</version>
</dependency>
</dependencies>
</plugin>
在这里呢,我顺便跟你解释一下 PMD 插件的几个关键概念:
-
rulesets:规则集合。阿里巴巴将代码规范分成了几大类,比如注释、命名、OOP 设计、数据库设计等。你可以根据需要进行配置。
-
failurePriority:是指最低的错误级别。阿里巴巴代码规范将错误按照严重程度分成了 5 个等级。最高是等级 1,最低是等级 5。比如 failurePriority=3 表示所有等级大于等于 3 的错误都会被报告。由于等级 5 是最低等级,所以 failurePriority=5 表示所有错误。
-
maxAllowedViolations:表示允许的最多错误。比如,maxAllowedViolations=20 表示最多允许 20 个错误,如果大于 20 个,构建会失败。
其中的 failurePriority 和 maxAllowedViolations 参数很重要,你可以根据实际情况,进行调整。
在我使用阿里巴巴代码规范的时候,发现了一个需要注意的地方。IDEA 插件和 PMD 插件的检查结果可能会不一样,尤其当问题很多的时候比较明显。这会给开发人员造成一些困扰。开发往往是由 IDEA 插件来检查代码,如果通过了,就提交代码。结果在 CI/CD 流程中,使用 PMD 插件来检查,却提示检查不通过。这时候开发就比较疑惑了,可能会怀疑是不是代码合并出问题了,花了大量时间来排查也没找到原因。其实就是因为插件本身的原因导致的。如果你也在使用这个插件,请一定要留意这个问题。建议在最终提交代码的时候,也在本地使用 mvn package 命令来执行一下 PMD 检查了,通过了再提交代码。
如何使用 Sonar
前面我介绍了阿里巴巴代码规范,是通过插件的形式来使用的,比如 IDEA 插件、Maven 插件等。但 Sonar 是一个工具,一个平台。它包含了 Server 端、Client 端、Web 界面和完善的插件机制。那在今天的分享中,我不会特别详细地介绍如何安装、配置 Sonar,因为这些都是标准的操作步骤,你可以在网上找到详细的教程。Sonar 通常会集成到 CI/CD 流程中,来自动检查质量。目前,Jenkins 是使用最广泛的 CI/CD 工具,所以,今天我就以 Jenkins 为例,简单地说明一下 Sonar 和 Jenkins 的集成步骤,然后跟你聊聊在实际使用过程中,需要注意的一些事项。
Sonar 是一个专注于代码质量管理的平台,包括了一系列工具,如可视化的 Web 界面、多样的插件以及对多种持续集成工具的支持,并且 Sonar 兼容大多数编程语言。Jenkins 中集成 Sonar 相对简单,因为 Sonar 已提供了 Jenkins 集成的插件,只需要在 Jenkins 中安装、配置即可。主要有五个步骤:安装 Sonar 的 Server 端、在 Jenkins 中安装 Sonar 插件、配置 Sonar Server、配置 Sonar Scanner,以及在需要进行 Sonar 扫描的 Job 中,添加 Sonar 扫描步骤。在 Jenkins 中配置好了 Sonar 后,构建时会自动执行 Sonar 扫描,Sonar 会分析代码中的问题,比如 Bug、坏味道、代码重复等。可以在 Sonar 中设置质量阈值,如果问题数超过阈值,会导致当前构建失败。
Jenkins 中安装 Sonar 插件
Jenkins 中集成 Sonar 很简单,因为 Sonar 已提供了 Jenkins 集成的插件,只需要在 Jenkins 中安装、配置即可。主要有五个步骤:
-
第一步:安装 Sonar 的 Server 端。
-
第二步:Jenkins 中安装 Sonar 插件。可以在线安装或手动安装。
-
第三步:Jenkins 中配置 Sonar Server。
-
第四步:Jenkins 中配置 Sonar Scanner。
-
第五步:在需要进行 Sonar 扫描的 Job 中,添加 Sonar 扫描步骤。
设置 Sonar 的质量阈值
在 Jenkins 中配置好了 Sonar 后,构建时会自动执行 Sonar 扫描,Sonar 会分析代码中的问题,比如 Bug、坏味道、代码重复等。可以在 Sonar 中设置质量阈值,如果问题数超过阈值,会导致当前构建失败。
Sonar 误判
在使用 Sonar 扫描时,可能会遇到 Sonar 误判的情况。有时候,我们的代码是符合规范的,而 Sonar 却一直提示代码有问题。一个典型的场景是 NPE 问题。我们思考一个简单的例子:有一段代码要处理手机号码。它先调用 Apache Common 类库的 StringUtils.isNotBlank 方法,确保手机号不为空,不为 Null,然后再处理手机号。理论上这段代码是不会出现 NPE 的,因为 StringUtils.isNotBlank 已经保证了手机号不为空。但是 Sonar 却给了我们一个大大的告警,提示有 NPE 风险,没有进行 Null 判断。这就比较让人迷惑了。
scss
if (StringUtils.isNotBlank(phoneNumber)) {
if (phoneNumber.length == 11 ) {
// do something
}
}
这个时候,你只要简单看一下 StringUtils.isNotBlank 方法的源码就知道,它已经进行了 Null 检查。那为什么 Sonar 会误判呢?这是因为 Sonar 默认情况下只会扫描项目自己的代码,而不会扫描项目的第三方依赖。也就是说它不会扫描 Apache Common 包,也就不知道 StringUtils 的 isNotBlank 方法的细节了,并不知道该方法内部进行了 Null 检查。正是因为 Sonar 无法获得足够多的上下文,于是出现了误判。为了解决这个问题,需要让 Sonar 变得聪明一点,也能够分析项目的依赖。Sonar 提供了一个 sonar.java.libraries 的配置,可以指定一个目录,Sonar 会扫描该目录中的 JAR 文件。
我们可以在 pom 文件中添加 maven-dependency-plugin 插件,将项目依赖的所有类库拷贝到某个目录,默认是 target/dependency 目录。
xml
<!-- 将项目依赖的第三方jar复制到target/dependency目录,用于sonar分析用 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.8</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
</execution>
</executions>
</plugin>
然后在 Jenkins 的 Job 中配置 sonar.java.libraries。将其指定为 maven-dependency-plugin 复制依赖的目录。
bash
-Dsonar.java.libraries=/root/.jenkins/workspace/${project_name}/target/dependency
到此,我们就完美地解决了 Sonar 误判的问题了。
总结
在推广代码规范的初期,如果一开始就设置了严格的检查机制,可能会给团队带来额外的开发成本,甚至产生排斥的情绪。因此,在实施过程中需要把控检查规则的宽松度,并结合公司和团队的实际情况,制定一个合适的方案。例如,可以先培养习惯,再逐渐提升要求,项目赶进度时,适当放宽甚至临时取消代码规范检查。同时,除了使用工具,还需要与团队成员进行有效沟通,帮助他们解决问题,共同进步。