数百万年前,猿猴从树上繁衍出来,进化出对向性拇指(译者注,对向性拇指即拇指与其他四指对合,结果可以拿握东西),最终成为人类。
我们以类似的方式看到强制的代码审查:在软件开发大草原地的翻滚的草原上将人与兽区分开来。
尽管如此,我有时还是听到我们团队成员的评论:
- “对该项目进行代码审查是浪费时间。”
- “我没有时间进行代码审查。”
- “我的发布被推迟了,因为我懦弱的同事还没有完成我的审查。”
- “你能相信我的同事希望我更改我的代码吗?请向他们解释,如果以任何方式更改我原始的优雅代码,宇宙的脆弱平衡将被破坏。”
我们为什么要进行代码审查?
首先,让我们记住为什么我们要进行代码审查。任何专业软件开发人员最重要的目标之一是持续提高他们的工作质量。即使你的团队挤满了有才华的程序员,你也不会把你自己与有能力的自由职业者区分开来,除非你作为一个团队工作。代码审查是实现此目标的最重要方法之一。特别是,它们:
- 提供另一双眼睛以发现缺陷和更好的做事方法。
- 确保至少有其他人熟悉你的代码。
- 通过向新员工展示更有经验的开发者的代码来帮助培训他们。
- 通过向审阅者和受审者展示彼此的好主意和实践来促进知识共享。
- 鼓励开发人员做得更彻底,因为他们知道它将由他们的一位同事进行审查。
做彻底的审查
但是,除非花费适当的时间和精力进行审查,否则无法实现这些目标。仅滚动修改,确保缩进正确并且所有变量均使用小写的驼峰字母,并不构成对代码的彻底审查。考虑结对编程是很有益性的,这是一种非常流行的做法,并且将所有开发时间的开销增加了100%,以此作为代码审查工作的基准。你可以在代码审查上花费大量时间,并且仍然比结对编程花费更少的全部的工程师时间。
我的感觉是,大约25%的原始开发时间应该花在代码审查上。例如,如果开发人员花两天的时间来实施故事,则审阅者应花大约四个小时来审阅它。
当然,只要检查正确完成,你花费多少时间在检查上并不重要。具体来说,你必须理解你要检查的代码。这不仅意味着你知道其编写语言的语法。这还意味着你必须了解代码如何适合其所包含的应用程序,组件或库的情形。如果你没有掌握每一行代码的所有含义,那么你的审查将不会很有价值。这就是为什么不能快速进行良好检查的原因:花时间调查可能触发给定功能的各种代码路径,以确保正确使用了第三方API(包括任何边缘情况)等等。
除了在正在检查的代码中查找缺陷或其他问题之外,你还应确保:
- 包括所有必要的测试。
- 已经编写了适当的设计文档。
尽管是擅长编写测试和文档的开发人员也不总是记得在更改代码时对其进行更新。在适当的时候,代码审阅者轻微地劝说对于确保它们不会随着时间的过去变得陈旧是重要的。
防止代码审查负担过重
如果你的团队执行强制性代码审查,则存在代码审查积压到无法管理的程度的危险。如果你两周未进行任何评论,你能够轻松用几天去审查以追赶进度。这意味着当你最终决定处理它们时,你自己的开发工作将遭受巨大而意想不到的打击。由于适当的代码审阅需要大量而持续的脑力劳动,这也使得进行良好的审查变得困难。很难连续几天维持这种状态到结束。
因此,开发人员应每天努力清空他们的审查任务。一种方法是在早上第一时间处理审查。通过在开始自己的开发工作之前进行所有未完成的审查,可以避免审查情况失控。有些人可能更喜欢在午休之前或之后或一天结束时进行审查。无论你什么时候进行,通过将代码审查作为日常工作的一部分,而不是消遣,你要避免:
- 没有时间处理你的审查任务。
- 由于你的审查尚未完成而推迟发布。
- 发起不再相关的审查,因为代码在此期间发生了很大变化。
- 进行不完善的审查,因为你必须在最后一刻匆匆完成。
编写可审查的代码
审查者并非总是审查任务失控的唯一责任人。如果我的同事花一个星期在一个大型项目中随意添加代码,那么他们发布的修改将很难审查。完成这个会议将有太多难处。理解代码的目的和基础架构将会是困难的。
这是为什么将你的工作分成可管理的单元很重要的许多原因之一。我们使用Scrum方法论,因此适合我们的单元就是故事。通过努力按故事的方式组织我们的工作并提交仅与我们正在研究的特定故事相关的审查,我们编写了易于审查的代码。你的团队可能会使用其他方法,但是原理是相同的。
编写可审阅的代码还有其他先决条件。如果要做出灵活的结构决策,那么事先与审阅者进行讨论是有意义的。这将使审阅者更容易理解你的代码,因为他们将知道你要实现的目标以及你打算如何实现。这也有助于避免在审阅者提出不同的更好的方法之后,你必须重写大量代码的情况。
项目架构应在设计文档中进行详细描述。无论如何,这是重要的,因为它使新项目成员可以加快速度并了解现有代码库。它还有更好的优点,可以帮助审查人去更好地工作。在向审查者阐述组件是如何工作这方面,单元测试也是有用的。
如果你的代码中包含第三方代码,请分别提交。当将9000行jQuery放到中间时,要正确地检查代码是非常困难的。
创建可审查代码的最重要步骤之一是为你的代码审查添加注释。这意味着你在进行自我审查,并在你认为会帮助审查者理解什么在发生的任何地方添加注释。我发现对代码进行审查注释需要相对较少的时间(通常只需几分钟),并且对更快更好地审查代码影响巨大。当然,代码注释具有许多相同的优点,并应该用在适合的地方,但审查注释更有意义。另外,研究表明,开发人员在重读和审查注释代码时会发现自己代码中的许多缺陷。
大型代码重构
有时,以影响许多组件的方式重构代码库是必要的。对于大型应用程序,这可能需要几天(或更多),并且会产生巨大的修改。在这些情况下,标准的代码审查可能不切实际。
最好的解决方案是增量重构代码。在正在工作的代码并中,找出你想去的那个方向的的合理范围内的部分修改。一旦完成更改并发起审查,进行第二次增量更改,依此类推,直到完成整个重构。这并不总是可能的,但是这种想法和计划通常是现实的,当重构时避免大量的修改。开发人员以这种方式重构可能会花费更多时间,但它也可以提高代码质量,并使审查变得更加容易。
如果确实不可能以增量方式重构代码(这可能说明出原始代码的编写和组织的情况),一种解决方案可能是在进行重构时执行结对编程而不是代码审查。
解决纠纷
毫无疑问,你的团队是由聪明的专业人员组成,并且在几乎所有情况下,当对指定编码问题的意见不同时,应该是可能达成一致。作为开发人员,请保持开放的想法,并准备妥协,当你的审查者更倾向于一个不同的方法时。不要对你的代码采取固有态度,也不要亲自查看评论。仅仅因为有人认为你应该将某些重复的代码重构为可重用的函数,这并不意味着你就不再是一个有吸引力,聪明而有魅力的人。
作为审查者,要机智。在提出更改建议之前,请考虑你的建议是否真的更好,或者只是个人看法。如果你选择奋斗并专注于原始代码明显需要改进的区域,那么你将获得更大的成功。诸如说“它可能值得考虑…”或“有人推荐…”之类的内容,而不是“我的宠物仓鼠可以编写比这更有效的排序算法”。
如果你真的找不到中立的立场,那么找两个你尊重的第三方开发人员来看看并提出他们的意见。
原文:http://blog.salsitasoft.com/practical-lessons-in-peer-code-review/