我们可能见过上面的有关代码质量的图片,究竟如何衡量一段代码好坏?
代码质量是什么?为什么它很重要?
作家通过他的著作来讲述了一个清晰的、令人信服的故事。他们使用章节、标题和段落等工具来清晰地组织他们的思想,并轻松地引导读者。
开发者的工作与作家类似,只是使用不同术语如命名空间、类和方法。如果创作者不能有效地使用他们的工具,那么无论他们的作品是书还是代码,读者都很难读懂。
回到代码质量这个话题,好的代码都应该具备如下一系列理想特征:
- 可靠:能够稳定工作,不会频繁崩溃。
- 一致的代码风格:遵循该语言一致的代码风格和命名惯例。
- 可维护:易于理解,可维护的代码应该易于扩展及添加新功能。
- 完善的测试:具备良好测试的代码往往 bug 更少。
- 高效:不应使用不必要的资源来执行所需的业务。
- 安全:应防止SQL注入等编码漏洞。
- 较低的技术债务:较低的技术债务使团队能够快速前行和开发新功能,而不会被低质量和不可维护的代码拖累。
具备的上述特征越多,代码的质量就越高。根据项目及客户的具体情况,其中一些特性可能不是代码必需的。
当面临交付期限时,编写高质量的代码非常具有挑战,但如果你考虑到代码的长期可维护性,这一点很重要。同时,高质量的代码也会帮助团队长期保持一致的交付速度。
根据我的经验,下面是一些在我的项目中对改进和维护高质量代码非常有效的总结。
使用静态代码分析器提高代码质量
编译器可以捕捉和防止语法问题,但它们无法检测到类似情况:
- 代码结构不一致
- 社区已经成型的经验
- 代码复杂性
静态代码分析是一种在代码运行前对其进行检查的技术。有一些工具可以进行静态分析,它的工作原理是根据多种编码规则分析代码,来发现一些违规行为。这些工具可以集成到构建工具中,如 gradle、maven 等,并让有问题的代码构建失败。
以下是一些可以整合到项目中的工具。
Checkstyle
Checkstyle (1) 是开发中用于检查 Java 源代码是否符合编码规则的静态代码分析工具。Checkstyle 进行的检查限于代码的表现形式,这些检查并不能确认代码的正确性和完整性。
https://checkstyle.sourceforge.io/
使用 Checkstyle 可以确保开发团队遵循一致的编码风格,使其更容易阅读和理解。
下面是一些可以使用 checkstyle 进行的检查。
- 属性和方法的命名惯例
- 函数参数的数量
- 代码每行最大宽度
- 强制性的文件头描述,如版权
- import 和范围修饰符
- 字符之间的空格
- Class 构建函数的约定
- 多重代码复杂度测量
PMD
PMD(Programming Mistake Detector,编程错误检测器)(1) 是一个静态代码分析器,它可以报告在应用程序代码中发现的问题。
https://pmd.github.io/
PMD 可以帮助检测代码中的问题,这些问题可能会在代码交付生产环境时引起问题。
- 可能的 bug: 空的 try/catch/finally/switch 块,吞掉原来异常并抛出一个新的异常。
- 死代码:未使用的局部变量、参数和私有方法。
- 空的 if/while 语句
- 过于复杂的表达式: 不必要的 if 语句,for 循环可以是 while 循环。
- 次优代码:浪费的 String/StringBuffer 的使用
- 高循环复杂度的类
- 错误的 BigDecimal 用法
CPD(复制/粘贴检测器)
CPD (1),顾名思义,是一个基于拷贝的检测器,即使对于大型代码库来说也是非常高效的。它使用 Karp-Rabin (2) 字符串匹配算法编写。
https://pmd.sourceforge.io/pmd-4.2.5/cpd.html
https://xlinux.nist.gov/dads/HTML/karpRabin.html
它可以被配置为检测大于确定数量的标记的重复。复制/粘贴代码是不可取的,因为它使代码难以维护,并可能在对其中一个地方做了一些改变,而忘记在其他地方也存在相同的代码的情况下导致 bug。
衡量代码质量
免责声明:当一项措施成为目标时,它就不再是一项好措施。(1)
https://en.wikipedia.org/wiki/Goodhart%27s_law
代码覆盖率指标
代码覆盖率是一个指标,可以用来获得一些关于代码质量的信心。说了这么多,选择哪些测试来衡量覆盖率时要小心。并不是所有测试金字塔的测试都是一样的,像 JaCoCo 这样的工具可以用来计算代码覆盖率。
在看代码覆盖率的指标时,只应该考虑单元测试,因为单元测试是为了测试代码是否完成了开发者想要做的事情,执行这些测试是最快的验证方法。
衡量集成测试的代码覆盖率可能是有价值的,但它应该被视为单独的结果,而不应该与单元测试报告合并。记住集成测试是为了确保所有的组件一起工作。使用集成测试来提高代码覆盖率,就像使用大锤来敲开一个螺母一样。
毒性图(Toxicity Chart)
毒性图(Toxicity Chart) (1),顾名思义是一种展示代码毒性的方法。这个图代表了代码库中每个类的毒性,毒性分数是根据一系列参数计算出来的,比如文件长度、方法长度、循环复杂度、嵌套语句等等。这个图表可以展示给业务人员、管理人员等非技术人员,帮助他们了解代码的质量。
https://erik.doernenburg.com/2008/11/how-toxic-is-your-code/
示例代码
下面的 Github 仓库包含了一个包含上述所有工具的示例项目。它的结构让你很容易选择一些需要的工具来集成到你自己的项目中。
https://github.com/singhalkul/java-quality-checks
保持代码质量是一个持续的过程,它不能由团队中的某一个人来完成,整个团队都有责任确保编写的代码是高质量的。
虽然上面提到的工具会帮助确保减少代码中一些质量问题,但这不是唯一的方法。团队应该遵循极限编程实践,如配对编程、测试驱动开发、代码审查、持续集成,以确保高质量代码特征存在于代码库中。
英文原文:
https://medium.com/inspiredbrilliance/improving-code-quality-for-java-projects-5d24ad448109
本文转载自微信公众号「高可用架构」,可以通过以下二维码关注。转载本文请联系高可用架构公众号。