提升Java代码质量的11个最佳实践和工具
通常情况下,在软件项目开发初期,代码质量并非首要关注点。然而,如何提升代码质量和效率应该是Java开发人员、技术团队负责人、系统架构师乃至项目经理的主要考量之一。那么,究竟该如何提升Java代码质量呢?
代码质量改进需要制定完善的策略,并在整个项目生命周期中坚持执行。如果放任不管,迟早会酿成大祸。因此,最好提前做好管理。
在 Romexsoft,我们通常使用 Java 进行项目开发,并始终致力于提升 Java 代码质量。我们通过遵循软件质量改进技术并使用Java 代码质量工具来实现这一目标,这些工具不仅帮助我们改进代码,还提高了我们的工作效率。
本文将探讨最常用的开发方法和用于编写更高质量代码的顶级工具。目的是分析提升代码质量的常用方法,帮助团队选择合适的开发方法和工具,从而提高开发效率。
什么是软件开发方法论?
软件开发方法论是一套用于构建、规划和控制软件解决方案开发过程的模式和规则。为了高效地管理开发过程,项目经理必须选择最适合项目的开发方法论。
那么,让我们一起来了解一下其中的一些方法,以了解为什么会有不同的方法存在,以及哪些方法最常用。
结对编程
结对编程是一种行之有效的方法,可以减少代码中的错误。它由两位开发者共享一个工作空间(键盘和屏幕)完成,让人想起学生时代——一位开发者编写代码,另一位则阅读代码并思考潜在的问题。开发者们互相指导编码,并且可以在编程过程中互换角色。
结对编程的主要好处在于知识共享和代码质量提升,同时也能改善团队内部沟通。
结对编程不仅限于代码编写,还可以用于操作系统命令行操作、数据库服务器操作、文件管理、云操作以及许多其他场景。
因此,如果您负责更复杂或关键的项目,请随时与同事合作,运用这种方法来预防代码中的错误/问题。考虑到在开发后期或发布后发现错误/问题的成本更高,结对编程可以节省您的时间和金钱。
考虑到“三个臭皮匠,顶个诸葛亮”的常识,关于结对编程的讨论似乎已经平息,人们也确实在实践它。
编码规范
编码规范是由开发团队制定的一套指导原则,其中包含针对公司或特定项目中编写的代码各个方面的编程风格、实践和方法的建议。这些规范通常针对特定的编程语言,涵盖文件组织、缩进、注释、声明、语句、空格、命名规范、编程实践和原则、编程规则、架构最佳实践等。定义标准的主要优势在于,每段代码看起来都清晰易懂,便于阅读,并有助于程序员理解其他程序员编写的代码。
如果在整个开发过程中始终遵循并应用编码标准,那么将来维护和扩展代码、重构代码以及解决集成冲突都会更加容易。标准本身远不如对标准的遵守重要。
代码规范对程序员来说非常重要,原因有很多:
- 软件生命周期成本的 40% - 80% 用于维护。
- 几乎没有软件能由其作者维护到其生命周期结束。
- 代码规范可以提高软件的可读性,使程序员能够更快地理解新代码。
坦白说,我非常支持代码规范。对我来说,花时间讨论和争论代码规范是有意义的,因为这有助于将来节省时间和精力。
首先安排一次会议,讨论编码规范应该包含哪些内容。这次会议必须面对面进行,不能通过电子邮件或聊天系统。讨论你们决定纳入代码规范的规则。团队大多数成员同意的规则应被视为“强制性”规则,其他规则可以视为“可选”规则。
代码规范指南应定期审查。规则可以从“强制性”改为“可选”,反之亦然。如果某些规则未按预期运行,则需要对其进行修改或从指南中移除。
强烈建议程序员在编写代码时遵循这些准则,并且应该将其作为代码审查的一部分,代码审查是我们列表中的下一个内容。

代码审查
仅次于结对编程的就是代码审查。如果您不采用结对编程,那么至少应该考虑进行代码审查。代码审查是一个轻量级的过程,应该在代码编写完成后尽快实施。
下面列出的其他一些主题可能不太明显,但值得考虑。我们继续。
单元测试
接下来我们要讨论的方法是单元测试。根据您的经验,您可能听说过单元测试、测试驱动开发或其他类型的测试方法。通常,这些方法应用于大型软件系统,有时也应用于简单的网站。
在计算机编程中,单元测试是一种软件开发过程,它将源代码中最小的可测试部分(称为单元)单独且独立地进行测试,以检查其是否按预期运行。这有助于在代码发布之前识别算法和/或逻辑中的缺陷。
创建单元测试的好处之一是,它能激励团队成员编写可测试的代码。由于单元测试需要代码具备合理的结构,这意味着代码必须被拆分成更小、更专注的函数。每个函数负责对一组数据执行单一操作,而不是像大型函数那样执行多个不同的操作。
编写经过充分测试的代码的第二个好处是,当对现有代码进行微小改动导致功能失效时,可以防止未来出现故障。一旦发生故障,您就能及时发现问题所在。
乍一看,在开发过程中花时间编写单元测试似乎是额外的开销。然而,它能节省你可能花费在调试上的时间。这应该是一个循序渐进的过程。
当然,你不可能为项目的每个部分都编写单元测试,但你需要确保核心组件的行为符合预期。随着项目规模的扩大,你可以简单地运行已开发的测试,以确保在引入新功能时现有功能不会受到影响。
测试驱动开发
测试驱动开发(TDD),也称为测试驱动设计,是一种软件开发方法,它结合了单元测试、编程和源代码重构。通常,开发人员倾向于忽略软件开发的架构方面,直接进入编码阶段。他们试图先实现一个粗略的版本,只有在有了可运行的原型之后才会考虑编写测试。虽然这种方法有时也能成功,但要让它正常运行却需要付出大量的努力。
测试驱动开发 (TDD) 是提升代码质量、减少 bug 的实践方法之一。它最初是作为 Scrum 和极限编程 (XP) 等更广泛的软件设计范式的一部分而引入的,而 Scrum 和 XP 又是敏捷软件开发方法论的两种类型。TDD 有助于在更短的时间内交付高质量的应用程序。正确实施 TDD 要求开发人员和测试人员准确预测应用程序及其功能在实际应用中的使用方式。
当它作为持续集成周期的一部分,配合频繁的自动化构建和测试时,这种实践就相当于强化版的单元测试。为了应用这种方法,开发人员需要接受专门的培训和指导。
在我理解的测试驱动开发(TDD)中,编写代码之前,你至少需要知道起点。首先,你需要思考如何构建对象以及它们的行为来解决给定的问题。在进行TDD时,你会从一个测试用例开始,并设想测试用例应该是什么样子。
持续集成
持续集成(CI)是一种开发实践,它要求开发人员每天多次将代码提交到共享代码库(例如 SVN、Subversion 或 Git)。每次提交都会经过自动化测试的验证。虽然自动化测试并非 CI 的严格组成部分,但通常会预先进行。这种方法使开发人员能够更早地发现问题,从而更快地解决问题。
这本身就是一项非常有价值的实践。你应该尽早着手搭建一个简单的持续集成流程。有很多工具可以帮助你搭建这个流程,其中最知名的包括Jenkins、Bamboo和TeamCity。它们可以帮你实现软件部署自动化,让你专注于产品开发。
演示环节
演示评审会议通常在冲刺周期接近尾声时举行。此次会议的目的是向其他团队成员、客户和利益相关者展示团队在冲刺周期内取得的成果。
或许你不会立即意识到这样做为何能写出更好的代码,但它的确有效。通过定期展示源代码,开发者需要确保代码始终接近发布版本。定期召开演示会议,可以建立一套完善的反馈机制。这将帮助你更好地了解哪些方面做得好,以及哪些方面出了问题。
现在,让我们继续探讨一些推荐的代码质量工具,以优化代码质量流程。
提高 Java 代码质量的工具
没有哪个开发者从不犯错。
通常情况下,编译器会捕获语法和运算错误,并列出堆栈跟踪信息。但仍然可能存在一些编译器无法捕获的问题。这些问题可能包括不恰当的需求实现、错误的算法、糟糕的代码结构,或者一些社区根据经验已知的潜在问题。
要发现这类错误,唯一的办法就是请一位资深开发人员审查你的代码。这种方法并非万全之策,而且效果也有限。团队中每增加一位新开发人员,就应该安排一位额外的人员来审阅他/她的代码。幸运的是,现在有很多工具可以帮助你控制代码质量,例如 Checkstyle、PMD、FindBugs 和 SonarQube等。这些工具通常用于分析代码质量并生成一些有用的报告。这些报告通常会由持续集成服务器(例如 Jenkins)发布。
以下是我们在 RomexSoft 的大多数项目中使用的 Java 静态代码分析工具清单。让我们逐一了解一下。
格子图案
代码审查对代码质量至关重要,但通常团队中没有人愿意审查数万行代码。然而,像Checkstyle这样的源代码分析工具可以自动化手动代码审查所带来的种种挑战。
Checkstyle 是一款免费开源的静态代码分析工具,用于软件开发中检查 Java 代码是否符合您制定的编码规范。它可以自动执行检查 Java 代码这项至关重要但又枯燥乏味的任务。它是最流行的代码审查自动化工具之一。
Checkstyle 内置了一些预定义规则,有助于维护代码规范。这些规则是一个很好的起点,但它们无法满足项目特定的需求。要想成功实现自动化代码审查,关键在于将内置规则与自定义规则相结合,因为网上有很多教程提供了相关的操作指南。
Checkstyle 可以用作Eclipse 插件,也可以用作Ant、Maven或Gradle等构建系统的一部分,以验证代码并生成编码标准违规报告。
PMD
PMD是一款静态代码分析工具,能够自动检测各种潜在的错误以及不安全或未优化的代码。它会检查Java源代码,查找潜在问题,例如可能存在的错误、无用代码、次优代码、过于复杂的表达式和重复代码。
其他工具(例如 Checkstyle)可以验证代码规范和标准是否得到遵守,而 PMD 则更侧重于预防性缺陷检测。它提供了一套丰富且高度可配置的规则,您可以轻松配置并选择特定项目应使用的规则。
与 Checkstyle 一样,PMD 可以与 Eclipse、IntelliJ IDEA、Maven、Gradle或Jenkins一起使用。
以下是PMD处理的一些不良行为案例:
- 空的 try/catch/finally/switch 代码块。
- 空的 if/while 语句。
- 死代码。
- 直接实现而非接口的情况。
- 方法过于复杂。
- 具有高圈复杂度测量值的类。
- 不必要的“if”语句,本可以用“while”循环代替。
- 未使用的局部变量、参数和私有方法。
- 重写 hashcode() 方法,但不使用 equals() 方法。
- 浪费的字符串/字符串缓冲区使用。
- 重复代码——复制/粘贴代码可能意味着复制/粘贴错误,从而降低可维护性。
FindBugs
FindBugs是一款开源的 Java 代码质量工具,在某些方面与 Checkstyle 和 PMD 类似,但侧重点却截然不同。FindBugs 并不关注格式或编码标准,对最佳实践也只是略有涉及。
事实上,FindBugs 专注于检测潜在的 bug 和性能问题,并且在检测各种常见的、难以发现的编码错误方面表现出色,包括线程同步问题、空指针解引用、无限递归循环、API 方法误用等等。FindBugs 处理的是 Java 字节码,而不是源代码。因此,与 PMD 或 Checkstyle 相比,它能够以相对较高的精度检测到截然不同的问题。正因如此,它可以成为您静态分析工具箱的得力助手。
FindBugs 主要用于识别大型应用程序中数百个严重缺陷,这些缺陷被分为四个等级:
- 最恐怖
- 可怕的
- 令人不安的
- 令人担忧
让我们仔细看看一些漏洞案例。
无限递归循环
public String resultValue() { return this.resultValue(); }
这里,结果值()方法在其内部被递归调用。
空指针异常
FindBug 会检查代码,找出肯定会导致 NullPointerException 的语句。
Object obj = null; obj.doSomeThing(); //代码执行将导致空指针异常
以下代码存在一个相对简单的错误。如果变量 'obj' 包含 null 值,而变量 'str' 包含实例,则肯定会导致 NullPointerException 异常。
如果 str 为空且 obj 为空,或者 str 等于 obj,则 执行某些操作 。
一个其返回值不应被忽略的方法
该字符串是一个不可变对象。因此,忽略方法的返回值将被视为一个错误。
String str = "Java"; str.toUpper(); if (str.equals("JAVA"))
可疑的 equal() 比较
该方法对没有共同子类的不同类类型的引用调用 equals(Object)。
Integer value = new Integer(10); String str = new String(“10”); if (str != null && !str.equals(value)) { //执行某些操作; }
不同类的对象应该始终被视为不相等,因此 !str.equals(value) 比较将始终返回 false。
哈希值等于不匹配
该类重写了 equals(Object) 方法,但没有重写 hashCode() 方法,而是使用了 java.lang.Object 中固有的 hashCode() 实现。该对象很可能违反了相等对象必须具有相等哈希码的不变式。
类不会重写超类中的 equals 方法。
举个例子:继承自父类(父类定义了 equals 方法)的子类添加了新的字段,但自身并未重写 equals 方法。因此,子类实例的相等性判断将使用继承的 equals 方法,从而忽略子类的身份以及新添加的字段。
总而言之,FindBug 以独立图形用户界面应用程序的形式分发,但也提供适用于 Eclipse、NetBeans、IntelliJ IDEA、Gradle、Maven 和 Jenkins 的插件。用户可以在 FindBugs 中添加额外的规则集,以增加执行的检查项目。
SonarQube
SonarQube 是一个开源平台,最初于 2007 年发布,供开发人员用于管理源代码质量。Sonar 的设计初衷是支持公司内部代码质量的全球持续改进策略,因此可以用作共享的中央质量管理系统。它使团队中的任何开发人员都能进行代码质量管理。因此,近年来,它已成为代码质量管理系统持续检查领域的全球领导者。
Sonar 目前支持多种语言,包括 Java、C/C++、C#、PHP、Flex、Groovy、JavaScript、Python 和 PL/SQL(部分语言需要通过插件支持)。Sonar 非常实用,因为它提供全自动分析工具,并且能够与 Maven、Ant、Gradle 和持续集成工具完美集成。
Sonar 使用 FindBugs、Checkstyle 和 PMD 来收集和分析源代码,查找错误、不良代码以及可能违反代码风格规范的地方。它会检查和评估源代码的各个方面,从细微的样式细节、潜在的错误和代码缺陷,到关键的设计错误、测试覆盖率不足和代码过于复杂。最终,Sonar 会生成指标值和统计信息,揭示源代码中需要检查或改进的问题区域。
以下是 SonarQube 的一些功能列表:
- 它不仅会指出问题所在,还会提供质量管理工具来帮助你纠正问题。
- SonarQube 不仅可以解决 bug,还可以解决编码规则、测试覆盖率、代码重复、复杂性和架构问题,并在仪表板中提供所有详细信息。
- 它可以让你了解某个特定时刻的代码质量快照,以及滞后和领先质量指标的趋势。
- 它提供代码质量指标,帮助您做出正确的决策。
- 有一些代码质量指标可以显示你的进度,以及你是在进步还是退步。
SonarQube 是一个 Web 应用程序,可以独立安装,也可以安装在现有系统中。Java Web应用程序。可以通过在项目上运行 `mvn sonar:sonar` 命令来获取代码质量指标。
您的 pom.xml 文件需要引用此插件,因为它不是 Maven 的默认插件。
<build> … <plugins> <plugin> <groupId>org.sonarsource.scanner.maven</groupId> <artifactId>sonar-maven-plugin</artifactId> <version>3.3.0.603</version> </plugin> </plugins> … </build>
此外,Sonar 还提供增强型报告功能,通过多种视图显示所有项目的特定指标(您可以配置要查看的指标)。更重要的是,它不仅提供有关代码的指标和统计信息,还能将这些抽象的数值转化为实际的业务价值,例如风险和技术债务。
是时候得出结论了
多年来,我们在参与各种软件开发项目的过程中积累了丰富的经验,能够帮助优秀的代码变得更好。以下是我们建议在整个开发过程中采取的一些措施,以提高代码质量:
- 请遵循编程语言风格指南。
- 设计时要遵循SOLID原则。
- 给方法和变量起描述性的名称。
- 不要过度设计。
- 使用设计模式。
- 不要重复造轮子,请使用第三方框架。
- 使用高效的数据结构和算法。
- 创建单元测试。
- 记录项目的各个方面。
- 将项目的所有元素都纳入版本控制系统。
通过做到以上几点,并在日常编程实践中结合开发方法论使用代码质量分析工具,最终您将创建出更易读、测试更全面、运行更稳定、更易于修改的代码。此外,您还能为自己、团队和客户节省大量时间和金钱,避免诸多麻烦。
如果您希望在整个开发过程中体验到这种高效便捷的服务,请随时联系 Romexsoft。我们深谙如何交付高质量代码,并为客户带来最佳体验。
本文由Romexsoft于 2017 年 9 月 13 日撰写
,最初发表于 Romexsoft 博客,标题为《提升 Java 代码质量的 11 个最佳实践和工具》。
作者:尤拉·邦达连科
文章来源:https://dev.to/serhiykozlov/11-best-practices-and-tools-to-improve-the-java-code-quality-l0j