代码审查是主观的还是客观的(可量化的)?


55

我正在整理一些代码审查指南。我们还没有一个正式的流程,并且正在尝试使其正式化。而且我们的团队分布在各地。

我们使用TFS进行源代码控制(我们也使用TFS进行任务/错误跟踪/项目管理,但将其迁移到JIRA)与Visual Studio 2008一起进行开发。

您在进行代码审查时会寻找什么?

  • 这些是我想出的东西
    1. 强制执行FxCop规则(我们是Microsoft商店)
    2. 检查性能(是否使用任何工具?)和安全性(考虑使用 OWASP-代码搜寻器)和线程安全性
    3. 遵守命名约定
    4. 该代码应涵盖边缘情况和边界条件
    5. 应该正确处理异常(不要吞下异常)
    6. 检查功能是否在其他地方重复
    7. 方法主体应该很小(20-30行),并且方法只能做一件事情和一件事情(无副作用,避免时间耦合-)
    8. 不要在方法中传递/返回空值
    9. 避免死代码
    10. 记录公共和受保护的方法/属性/变量

我们通常还要注意什么?

我正在尝试看看我们是否可以量化审核过程(当由不同人员审核时,它会产生相同的输出)示例:说“方法主体应不超过20-30行代码”,而不是说“方法”身体应该很小”。

还是代码审查非常主观(一个审查者与另一个审查者会有所不同)?

目的是要有一个标记系统(例如,对于每个违反FxCop的规则,得分为-1分;对于不遵循命名约定的得分为-2分;对于重构,则得分为2分,等等),以便开发人员在检入代码时会更加小心。这样,我们可以识别出始终在编写好/不好代码的开发人员。目标是让审阅者最多花费30分钟左右的时间进行审阅(考虑到变更集/修订版可能包含多个文件/对现有体系结构的巨大更改等事实,我知道这是主观的,但是您得到了总体而言,审阅者不应花几天时间审查某人的代码)。

您遵循什么其他目标/可量化系统来识别开发人员编写的好/坏代码?

参考书:清洁代码:Robert Martin撰写的敏捷软件工艺手册


8
返回空值被认为有害吗?我知道为什么在高级语言(例如C#)中通常最好返回空数组而不是NULL(使代码更加优雅,并且更容易避免错误)。有时您需要返回NULL引用,对吗?

4
如果我们避免返回null,则当客户端/使用应用程序/库调用我们的方法时,可以跳过对null的检查。摘自Robert Martin的Clean Code-第7章(错误处理)pp:110“当我们返回null时,我们本质上是在为自己创建工作并将问题强加给我们的调用者。所要做的只是一个丢失的null检查,以发送应用程序转出控制。”

3
您能为不想买这本书的人解释一下吗:)?似乎对于大多数C#程序而言,避免NULL会使代码变得更加复杂,而这反过来又会导致更多错误……

2
这是一篇博客文章,解释了为什么返回null是一个坏主意。thehackerchickblog.com/2008/10/…。还有另外一个leedumond.com/blog/should-we-return-null-from-our-methods。鲍勃在书中提出的建议是,如果我们很想返回null,则可以抛出Null引用异常,或者返回SPECIAL_CASE对象。想想链接的方法调用this.Foo().FooBar().FooBarBar(); 如果返回的对象从这里符为空,你肯定能避免“对象引用不设置到对象的实例”,呼吁FooBar的时候()

@SoloBold:只是指出,它们只是准则。如果有非常令人信服的理由返回null(在某些情况下可能是),那么返回null比返回SPECIAL_CASE对象有意义

Answers:


25

在评论中给个人评分与我曾经使用过的大多数成功系统相反,也许是全部。但是20多年来我一直试图达到的目标是减少错误并提高每工程师小时的生产率。如果为个人评分是一个目标,我想可以使用评论。我从未见过需要作为工人或领导者的情况。

一些客观的研究(Fagan等)和许多流行的智慧表明,同级关系促进了旨在减少错误和提高生产率的代码审查。工作中的经理可以以工人的身份参加,但不能以经理的身份参加。注意讨论的要点,为了使审阅者满意,进行更改通常是一件好事,但不是必需的。因此,同伴关系。

无需进一步分析或判断就可以接受的任何自动化工具都很好-C,C ++,Java中的lint。定期编译。编译器确实善于发现编译器错误。记录自动检查中的偏差听起来像是对自动检查的微妙指示。恕我直言,允许偏差的代码指令(如Java一样)非常危险。非常适合调试,可让您快速掌握问题的真相。在记录不好的,50,000条非注释行代码块中找不到您要负责的代码,这并不是一件好事。

有些规则很愚蠢,但易于执行。例如,即使每个switch语句不可达,它们也会默认设置。然后,这只是一个复选框,您不必花费时间和金钱来测试不匹配任何值的值。如果你有规则,你就会愚蠢,它们密不可分。任何规则的好处都应该值得它付出的愚蠢之举,并且应该定期检查这种关系。

另一方面,“它运行”不是审查之前的美德,也不是审查中的辩护。如果开发遵循瀑布模型,则您希望在发现并解决复杂错误之前完成编码的85%时进行复查,因为复查是一种更便宜的查找方法。由于现实生活不是瀑布模型,何时进行回顾在某种程度上是一门艺术,并且构成了一种社会规范。真正会阅读您的代码并在其中发现问题的人是坚决的。持续支持这一点的管理层是一颗高于价格的明珠。评论应该像签到一样,而且要经常进行

我发现这些东西是有益的:

1)没有风格大战。打开花括号的位置只应在给定文件中进行一致性检查。全部都一样。那很好 同上压痕深度**和tab宽度。大多数组织发现他们需要一个通用的标签标准,该标准被用作较大的空间。

2)`衣衫agged

   looking

文字不

   line up is hard to read 

为内容。

顺便说一句,K&R缩进了五个(五个)空格,因此向权威求助是毫无价值的。保持一致。

3)在审阅之前,应指出要进行审阅的行号不变且可公开获得的文件副本,为期72小时或更长时间。

4)没有即时设计。如果有问题,请记下其位置并继续前进。

5)贯穿开发环境中所有路径的测试是一个非常非常非常好的主意。需要大量外部数据,硬件资源,对客户站点的使用等的测试需要花费巨资,而且不会彻底。

6)如果存在或在开发初期就创建,显示,编辑等工具,则可以接受非ASCII文件格式。这是我的个人偏见,但是在一个当今的主流操作系统中,如果内存不足1 GB,就无法摆脱困境,我不明白为什么文件少于10 MB应该是什么? ASCII或其他一些商业支持的格式以外的格式。有图形,声音,电影,可执行文件以及与之配套的工具的标准。包含某些对象的二进制表示形式的文件没有任何借口。

为了维护,重构或开发已发布的代码,我曾与一群同事坐在一个显示器上,看一看新旧差异,作为同事进入分支机构的门户。我喜欢它,它便宜,快速,相对容易做到。对于未事先阅读代码的人员进行演练对所有人都具有教育意义,但很少改进开发人员的代码。

如果您地理位置分散,与其他人在同一屏幕上交谈时查看屏幕上的差异会相对容易。这涵盖了两个人在研究变化。对于一大群阅读了相关代码的人来说,多个站点并不比一个房间中的所有站点难得多。恕我直言,多个房间通过共享的计算机屏幕和壁橱链接在一起,效果很好。站点越多,会议管理就越需要。经理作为主持人可以在这里赚钱。切记继续轮询您不在的站点。

在同一时间,同一组织具有自动化的单元测试,该测试用作回归测试。真的很好 当然,我们随后改变了平台,自动测试落伍了。正如《敏捷宣言》所指出的那样,审查更好,关系比流程或工具更重要。但是,一旦获得审查,自动化的单元测试/回归测试将是创建优秀软件的下一个最重要的帮助。

如果您可以根据需求进行测试,那么就像女士在《当哈利遇见莎莉》中所说的那样,我将拥有她的一切!

所有评论都需要有一个停车场,以捕获编码以上级别的要求和设计问题。一旦发现某物属于停车场,讨论应在审查中停止。

有时我认为代码审查应该像硬件设计中的原理图审查一样-完全公开,透彻,教程,过程的结束,构建和测试之后的网关。但是原理图审查很重,因为更改物理对象很昂贵。软件的体系结构,界面和文档审查可能应该是重量级的。代码更加流畅。代码审查应减轻重量。

在很多方面,我认为技术与文化和期望一样,与特定工具同样重要。想一想所有“ 瑞士家庭鲁滨逊 ” / 摩登原始人 / 麦吉佛尔的即兴创作,它们会愉悦人心并挑战思想。我们希望我们的东西起作用。唯一的途径是,“智能”可以通过1960年代的AI程序以某种方式抽象和自动化。


这是一个很好的答案,尤其是在对人员进行分级方面-这不应该是代码审查的重点。
Paddy

25

您描述的大多数要点仅是代码格式或“表面”内容的问题:

  • 遵守命名约定
  • 避免死代码
  • 文献
  • ...

所有这些都可以使用一些自动化工具进行检查:不需要有经验的开发人员花时间浏览代码来进行观察。

我对.NET一点也不了解,但是对于PHP,我们有工具可以检查这种东西。考虑到.NET通常被认为比PHP更“工业化”,我很惊讶地听到没有任何工具可以检查这种东西。


自动化工具可以:

  • 集成在某些自动构建过程中,该过程每天晚上运行
  • 发送电子邮件报告
    • 警告(例如,方法超过20行)
    • 错误(例如,方法超过50行)

可以将邮件发送给所有团队,也可以发送给提交未通过测试的代码的人-或者您可以使用某些报告Web界面 (有关.NET和PHP的相同说明)


我还要补充一点,在将代码用于生产之前,自动测试可以很大程度地检测出一定数量的错误。我想,自动化测试还可以帮助一些指标。


由经验丰富的开发人员进行的 代码审查还具有另一个您没有谈到的巨大优势:

  • 经验丰富的开发人员通常只需查看源代码就可以检测到各种错误(我经常在进行代码审查时发现错误)
  • 由经验丰富的开发人员进行的代码审查将使他能够向团队提出意见和建议
    • 他将尝试了解代码中使用的算法,并可能提出更好的解决方案。
    • 只需阅读代码,通常您会看到自动工具无法检测到的内容。

但是,对于不仅代码格式化更深入的代码审查,您将需要超过半小时的时间 ...


用于.Net的工具(目前仅适用于C#)是StyleCop。code.msdn.microsoft.com/sourceanalysis-
布莱恩·安德森

15

我在代码审查方面的经验是,应该综合努力来改进代码,而不是确定谁胜任或不胜任的“措施”。如果在代码检查过程中获得大量评论无关紧要,则检查者将变得更加严格,从而提出了改进代码的建议。

为了提高签入代码的质量,请强制处理审阅注释(让审阅者批准处理后的注释),并使用静态代码检查工具为初始提交强制设置质量级别。


2
+1表示您的意见,就是不要让这成为谁的工作比较出色的比较。这对士气不利!

2
@KarstenF:是的。另外,DeveloperA可能正在处理更复杂的任务(更多的代码行),而DeveloperB可能正在处理简单的任务并且得分可能更低(按分数计)。这是不公平的说,德瓦做了一个糟糕的工作时,有没有办法既规范自己的工作/任务

2
另外,一些开发人员可能会抹黑他们的同事。

这一点是正确的。琐碎的概念(例如分级)会导致琐碎。
Dan Rosenstark 2010年

在这个非常重要的点上+1。一旦您的过程开始产生一个数字,人们就会玩他们的代码来增加他们的数字。例如,他们编写了许多行简单的代码,因此其惩罚/方法评级非常低。或者,他们将所有时间都花在寻找完美的变量名上。然后这成为政治上的事情,因为没有人会想指出他们朋友代码中的小错误,因为那样会降低他们的得分,使他们看起来很糟!哦,不!简而言之,您的心在正确的地方,但不好的主意。程序员不看狗。
leoger 2010年

5

我认为您的评分系统不是一个好主意。有什么意义?识别程序员的好坏?该代码审阅中的每个人都可以根据代码审阅中提供的代码对特定程序员进行评估,而不是将值任意地分配给某种任意特征集。如果您要确定好的和坏的程序员,请向程序员询问。我保证人类可以比您的愚蠢的启发式方法更好地进行评估。

我的建议是尝试和改进代码审查,以便人们在非审判和非敌对的环境中公开分享想法和意见。如果可以做到,那么您将比基于愚蠢的清单对程序员做出判断要好100倍,这些清单旨在很好地评估程序员。我认为,如果许多程序员在代码审查方面做得不好,他们已经感到很自豪和努力。我怀疑对表现不佳的进一步“惩罚”是否通常会有所帮助。


4

我唯一的建议是避免使您的代码审查过程过于严格 -最重要的是,代码审查实际上是在进行并认真对待

对于审阅者而言,该过程越费劲,代码审阅就越不可能发生,并且它们将被认真对待而不是被视为烦人。此外,代码审查的真正价值在于审查者使用自己判断的能力,自动化工具可用于检查FXCop规则是否通过。


+100!我的意思是+1,但实际上并不是全部内容:对于代码审查和单元测试(及其他内容),少即是多。这是正确的,因为只有更多,直到它变为零为止:)
Dan Rosenstark 2010年

4

根据经验,避免花任何时间在代码审查中做机器可以完成的事情。例如,您的第一项内容是“强制执行FxCop规则”,但是大概可以通过FxCop做到这一点,而无需人工操作。


3

如果可以衡量它,如果它是客观的,可量化的,则尝试使用一种工具来实现。您需要经验丰富的审阅者的地方是模糊的主观知识。


制作该工具需要100个小时,使用它可以节省1000个小时。
Dan Rosenstark 2010年

3

关于样式的问题,已经有很多好的评论,这很重要。在团队项目中,所有代码看起来像是由单个作者编写的,这非常有价值。这样,团队中的其他成员就可以更轻松地介入并解决问题。您选择哪种量化措施来确保这一更广泛的目标并不重要。

另外一项要确保代码与系统其余部分已同意的总体体系结构相匹配。相似的问题都应以相同的方式解决。如果将应用程序逻辑划分为多个层,则所检查的代码是否会像系统其余部分那样破坏其功能?或者,正在检查的代码是否教授了一些应该在系统其余部分中撤回的新内容?就像样式检查确保代码看起来都一样一样,体系结构审查也应确保代码都以相同的方式工作。这里的重点还是可维护性。团队中的任何人都应该能够使用此代码并立即了解正在发生的事情。

分级的想法似乎是一个灾难,但是您最了解您的团队。这样的系统可能会激发他们的动力,但我认为人们更有可能开始担心自己的成绩而不是解决问题。代码审查的真正有价值的副作用之一是它们提供的指导机会。审阅者应将编写代码的人员视为他们的指导者。发现的每个问题都不是问题,而是一个机会,可以创建一个知识渊博,经验丰富的团队成员,并在整体上建立更紧密的团队。


2

坦率地说,我实际上更关心“主观”东西。我想从一个好的代码审查中得到的是有人检查我的逻辑,而不是我的打字。这就是我进行代码审查时关注的重点。

我喜欢的一般格式是:

  1. 我们要解决什么?
  2. 是什么原因造成的?(看代码)
  3. 我们如何解决?
  4. 告诉我新代码
  5. 给我看代码的工作原理

否则,仅查看差异往往会在小问题或风格方面提供意见。我更关心逻辑是否正确,整体使用的方法是否正确以及解决方案是否可维护。

作为示例,我最近查看了一位同事的一些代码。最初的问题是FxCop违规。但是正在做的是尝试通过检查版本号来确定Windows功能的存在与否。我的主要意见是这样做是一种脆弱的方法,最好还是直接查询该服务,因为功能存在与Windows sku之间的映射将来可能会更改,并且根本无法面向未来。


从您的答案中还不清楚:FxCop是否捕捉到了这种脆弱性,还是您?
Dan Rosenstark 2010年

2

循环复杂度(CC)是评估“还不错”的代码的一种方法。

在具有较高CC的实际代码中,我具有较高的“这里发生了什么,我不记得了”的因素。较低的CC代码更容易找出。

显然,通常的警告适用于度量标准。


1
@AfermeraInfo:是吗?
Paul Nathan

1

代码审查既是主观的又是客观的。诸如“方法主体必须为20-30行”之类的规则是主观的(有些人可能认为100行是可以的),但是如果您的公司确定20-30行是极限,那很好,您可以进行测量。我认为您想出的分数系统是个好主意。当您发现某些规则在计分中需要或多或少地需要权重时,您将需要定期对其进行重新评估,但是只要每个人都知道这些规则,它看起来就是一个很好的系统。

我会寻找的其他东西:

  • 代码清晰-有时一段代码可以一行或几行编写。一般的程序员不必花几分钟来弄清楚一行代码的作用。如果他这样做了,也许应该以更简单的方式重写代码。这是主观的,但关键是您公司中的大多数程序员应该立即可以理解该代码。
  • 检查功能输入参数-应该有一些代码来检查输入参数是否在可接受的范围内。这也应该与功能文档相匹配。
  • 描述性的变量名-除少数特殊情况(循环索引等)外,变量名应具有描述性。您可能想看看命名约定等资源之一是“代码完成”

1

看来您太详细了太快了。您应该将其分解。您应该遵守代码的代码质量和功能合规性。你们应该都分开了,这还不是故事的结局...所以这是我的建议:

代码质量:

  • 自动检查:
    • 样式的一致性:命名约定是否正确,所有代码是否正确缩进,等等。
    • 效率标准:检查内存泄漏,复杂性检查,冗余变量等。
  • 实际同行评审:
    • 设计的简单演练
    • 自动检查的偏差说明
    • 易于维护,谈论如何维护它以及所有
    • 可测试性:测试此代码有多容易?有计划吗?

功能符合性:

  1. 审查功能需求以及自需求和/或设计审查以来的任何更改
  2. 演示与需求相关的功能并逐一检查
  3. 讨论在实施过程中遇到的软件其他方面的任何其他要求(例如部署计划,基础架构等)
  4. 如有任何偏离需求的说明。

如果您能涵盖代码审查的这两个方面,那么您就是无所不能。



1

这取决于。

评论的某些部分易于量化(无FxCop问题,无StyleCop错误,无CAT.NET错误等)

但是,样式可以是主观的-但正如您所说,一旦开始变得更加具体(没有方法> 20行),您就可以对其进行度量,而NDepend之类的工具可以自动做到这一点。但是,有些事情永远不会自动进行-检查边缘案例处理将需要进行测试,这会增加代码覆盖率,并且在很多情况下100%是无法实现的理想选择。重复检查很难自动进行。空检查,不确定我是否同意您的意见,但是您可能可以编写NDepend规则或FxCop规则。

越多的工具越好,并且如果这些工具允许开发人员在提交更改之前检查其工作,并允许将其作为CI流程的一部分进行检查,那么您将最大程度地减少对审核的需求。


0

标记系统听起来很难正确,但值得作为测量工具使用:您无法改善无法测量的内容。但是您可能应该接受,有些事情很难/不可能准确量化。棘手的事情是确定每种质量应该得分多少分:例如,如果遵守命名约定得分2分,那么保持方法小分多少分?

也许像简单的清单这样的东西会更好,以便可以将代码标记为符合,部分符合或不符合特定质量。以后,一旦您看到最经常出现或引起最多问题的质量问题,便可以将评分添加到清单中。

审查过程还应该足够灵活,以使代码无法通过部分审查,前提是可以对此进行辩护并形成文件。盲目地遵守某些会使组件变得不必要的复杂/难以管理的代码质量标准是一个坏主意!


完美的事情正在发生。

0

如果您希望人们的代码更加标准化,而又不让他们“浪费时间进行格式化”,那么某些开发人员就会抱怨。投资ReSharper之类的工具,因为它使固定格式设置和其他重构任务几乎是自动化的过程。


0
  • 如果一台机器可以检查它,人们就不应该检查。
  • 仅一项检查清单项目:是否每个地方都正确处理了所有错误案例?
  • 使用代码审查来提高质量并转移知识。
  • 不要使用代码审查来识别“不良”开发人员。
  • 自我比明确点更有效。
  • 保持简短-90分钟和500行非常庞大。
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.