代码审查与集体编程
在这一部分,我们将回顾另一个令人惊讶地难以自动化的领域:检查代码质量。
正如我们在本书中所看到的,TDD 主要关注代码的设计。当我们构建单元测试时,我们定义了代码的使用方式。测试并不关心代码的实现,但作为软件工程师,我们关心。我们希望实现具有良好的性能,并且易于下一个读者理解。在代码的生命周期中,代码被阅读的次数远远多于被编写的次数。
有一些自动化工具可以帮助检查代码质量。这些工具被称为静态代码分析工具。这个名字来源于它们不运行代码,而是对源代码进行自动审查。Java 中一个流行的工具是 Sonarqube(位于 https://www.sonarqube.org/ ),它运行一组规则来检查代码库。
开箱即用,这类工具会给出以下警告:
-
未遵循变量命名约定
-
未初始化的变量可能导致
NullPointerException
问题 -
安全漏洞
-
编程结构使用不当或存在风险
-
违反社区接受的实践和标准
这些规则可以修改和添加,允许根据本地项目的风格和规则进行定制。
当然,这种自动化评估有其局限性。与手动探索性测试一样,有些事情只有人类才能做到(至少在撰写本文时)。在代码分析方面,这主要涉及为决策带来上下文。一个简单的例子是,与原始类型如 int
相比,更喜欢更长、更具描述性的变量名,而不是更详细的类型如 WordRepository
。静态工具缺乏对不同上下文的理解。
自动化代码分析有其优点和局限性,总结如下:
自动化分析 | 人工审查 |
---|---|
严格的规则(例如变量名长度) |
根据上下文放宽规则 |
应用固定的评估标准 |
应用经验学习 |
报告通过/失败结果 |
提出替代改进建议 |
谷歌有一个非常有趣的系统,叫做 Google Tricorder。这是一套程序分析工具,结合了谷歌工程师在制定良好代码规则方面的创造力和自动化应用这些规则的能力。更多信息请参见 https://research.google/pubs/pub43322/ 。
手动审查代码可以通过多种方式进行,一些常见的方法包括:
-
拉取请求上的代码审查:
拉取请求(也称为合并请求)由开发者在希望将其最新代码更改集成到主代码库时提出。这为另一个开发者提供了审查工作并提出改进建议的机会。他们甚至可能直观地发现缺陷。一旦原始开发者做出商定的更改,请求将被批准,代码将被合并。
-
结对编程:
结对编程是一种工作方式,两个开发者同时处理同一任务。他们持续讨论如何以最佳方式编写代码。这是一个持续的审查过程。一旦任何一个开发者发现问题或有改进建议,就会进行讨论并做出决定。代码在开发过程中不断被纠正和完善。
-
集体(群)编程:
类似于结对编程,但整个团队都参与编写一个任务的代码。这是终极的协作方式,持续将整个团队的专业知识和意见应用于每一段编写的代码。
这里的显著区别在于,代码审查发生在代码编写之后,但结对编程和集体编程发生在代码编写过程中。代码编写后进行的代码审查往往发生得太晚,无法进行有意义的更改。结对编程和集体编程通过持续审查和完善代码避免了这一点。一旦发现问题,立即进行更改。与先编写代码再审查的工作流程相比,这可以更快地交付更高质量的成果。
不同的开发情况会采用不同的实践。在每种情况下,增加一双(或更多)人类的眼睛提供了设计层面改进的机会,而不仅仅是语法层面的改进。
至此,我们已经看到了开发者如何通过将手动探索性测试和代码审查添加到TDD工作中受益。手动技术也使我们的用户受益,我们将在下一部分中讨论这一点。