当代码“必须”不好时,我应该作为审核者做什么?


18

我在一个设计不良,设计过度的项目中工作,该项目几个月前已引入强制性代码审查。

我被要求检查大量实现新功能的代码。它具有与我们其他代码库相同的缺陷。我知道在很大程度上,这些缺陷会渗入新代码中,例如。因为必须继承设计不良的类或实现设计不良的接口,同时又要保持兼容性,因此,我无法提供不涉及重写一半代码库的更好的解决方案。但是我觉得从工程的角度来看,这对于已经损坏的代码库不利,因为我们还要对其进行更多破坏。我正在检查的代码肯定是不好的,但是必须要实现该功能。

对于此特定评论,我应该如何表现?我有办法保持诚信并保持建设性吗?

请注意,我在此询问的是代码审查的范围。我确实意识到问题是由其他因素引起的,包括组织和工作文化,但是我想知道的是如何处理审查本身。


1
开发人员是否记录了为什么要这样做,甚至在问题跟踪器上为核心问题写了一个问题?
卢克斯·弗兰肯

很少,没有。
红色

4
您的组织内是否有胃口来解决技术债务问题?
罗伯特·哈维

5
如果考虑到环境代码没有错,我不会攻击代码。大多数情况下,自从您撰写本文以来,您暂时看不到真正的改进。它将创造冲突而没有改善的机会。我要做的是第一步,要教好记录。其次,创建一个程序使他们写清楚的问题。这将导致两件事:关于此问题的文档,以便下一个文档可以更快地工作。除此之外,您还可以获得可能要解决的具体问题列表。我喜欢GitHub提及的内容,因为您可以看到GitHub对其进行标记的次数。
Luc Franken

1
相关(可能是重复的):如何处理项目中过多的实用主义?
t

Answers:


25

简单:

1.记录您的技术债务

您已经确定了一段有效的代码,但是存在一些技术问题。这是技术债务。与其他债务一样,如果不及时处理,债务也会随着时间的推移而恶化。

处理技术债务的第一步是对其进行记录。为此,您可以在问题跟踪器中添加描述债务的项目。这将帮助您更清楚地了解问题的严重性,并有助于制定解决方案。

2.逐步还清债务

修改软件开发过程,以考虑偿还技术债务。这可能涉及偶尔的强化冲刺,或者只是定期解决债务项目(例如,每周2个项目)。确保债务清算的速度比其应计速度更快的重要部分(债务甚至技术债务都有利息)。

一旦达到不再缺乏技术缺陷的地步,您就可以使用更健康的代码库了:)


5

附带说明:寻找新工作。这个不会再好了。

您正在检查的代码的目标是:

  • 运送功能部件,该功能部件应根据要求工作。

  • 减少技术债务的增长。

通过检查单元,集成,系统和功能测试是否在这里,它们是否相关以及它们是否覆盖了所有必须测试的情况,来审查第一个目标。您还必须检查原始作者对编程语言的看法,这可能会导致细微的错误或导致代码伪装做与实际不同的事情。

第二个目标是您所关注的目标。一方面,新法规预计不会增加技术债务。另一方面,审查的范围是代码本身,但在整个代码库的上下文中。在这里,作为审阅者,您可以期待原始作者提供的两种方法:

  • 外部代码不是我的错。我只是实现了该功能,并不关心整个代码库。

    从这个角度来看,代码将复制代码库的缺陷,并因此不可避免地增加了技术负担:越糟糕的代码总是越糟。

    尽管这是一种有效的短期方法,但从长远来看,这将导致延迟增加和生产率降低,并最终导致开发过程如此昂贵和冒险,以至于产品将停止发展。

  • 编写新代码是重构旧代码的机会。

    从这个角度来看,可以限制遗留代码缺陷对新代码的影响。此外,可以减少技术债务,或者至少不与代码增长成比例地增加技术债务。

    尽管这是一种有效的长期方法,但它具有短期风险。主要的问题是,从短期来看,发布特定功能有时会花费更多时间。另一个重要方面是,如果遗留代码未经测试,则对其进行重构会带来引入回归的巨大风险。

根据您要鼓励的观点,您可能倾向于建议受审者更多地重构或不重构。在所有情况下,不要指望在糟糕的代码库中拥有完美的体系结构和设计的完美无瑕的代码段。什么,你不应该鼓励的是行为,其中谁拥有对一个蹩脚的代码库的尝试工作懂行的开发商做他的部分很好。除了使事情变得更简单之外,它只会使它们变得比以前更复杂。现在,您将有一个具有设计模式的部分,而不是统一的错误代码,另一个具有干净,清晰的代码的部分,随着时间的流逝而广泛重构的另一部分,并且没有任何统一性。

例如,想象一下,您正在发现一个中型网站的遗留代码库。您会惊讶于缺少任何常用的结构,并且记录完成后实际上是通过手动将内容附加到文本文件中而不是使用记录框架来完成的。您决定要使用MVC和日志记录框架的新功能。

您的同事正在实现另一项功能,而对于缺少ORM可以使尺寸完美的ORM感到非常惊讶。因此,他开始使用ORM。

您和您的同事都无法浏览成千上万行代码来在任何地方使用MVC,日志记录框架或ORM。实际上,这将需要数月的工作:设想引入MVC;需要多长时间?或在没人能理解的情况下,通过串联(偶尔有用于SQL注入的位置)内的SQL查询是混乱生成的情况下的ORM,该怎么办?

您认为您做得很好,但是现在,加入该项目的新开发人员必须面对比以前更多的复杂性:

  • 处理请求的旧方法

  • MVC方式

  • 旧的日志记录机制

  • 记录框架

  • 通过即时构建的SQL查询直接访问数据库,

  • ORM。

在我正在工作的一个项目中,有四个(!)日志记录框架并排使用(加上手动日志记录)。原因是,每当有人想记录内容时,都没有通用的方法可以这样做,因此与其学习一个新的框架(在所有情况下仅使用5%的代码库),不如简单地添加一个新框架。已经知道了。想象一下混乱。

更好的方法是一次重构代码库。再次以日志记录为例,重构将包括以下几个小步骤:

  • 查找完成旧式日志记录的所有位置(即,直接访问日志文件时),并确保它们都调用相同的方法。

  • 将此代码移至专用库(如果适用)。我不想在购物车类中记录存储逻辑。

  • 如果需要,修改日志记录方法的接口。例如,我们可以添加一个级别来指示消息是非正式消息,还是警告或错误消息。

  • 在新功能中使用新重构的方法。

  • 迁移到日志记录框架:唯一受影响的代码是专用库中的代码。


1
好的答案,直到最后一段。无论您是否打算,都意味着不应将良好实践用于新代码。-1
RubberDuck

2
@RubberDuck:这与良好实践无关,它与编写与其余代码库完全不同的代码有关。我曾经是那个开发人员,并且看到了我所做的事情的后果:在糟糕的代码中拥有明显更好的代码只会使事情变得更糟;使它变得更好的是通过少量重构步骤来改进代码库。我将在几分钟后在答案中添加一个示例。
Arseni Mourzenko '16

如果可以的话,我会再次DV。编辑使情况变得更糟。有四种不同的方法来做新的事情是不好的,但这是添加第二个日志记录框架的人的错。在沙子上画一条线,在烂代码旁边放上干净的代码,这本身并不坏。
RubberDuck

@RubberDuck:不是要添加第二个日志记录框架,而是要添加第一个。添加第二个日志记录框架的人之所以这样做,只是因为第一个框架仅用于一个小功能。如果按照我的建议重构了代码库,则不会发生这种情况。
Arseni Mourzenko '16

我认为您和我都同意,但是您的答案读起来会妨碍改善。我只是无法接受。
RubberDuck

3

如果您在开发过程中正在执行代码审查,那么您必须设置规则来“判断”正在检查的代码。

这应该放在您的“完成定义”中,并且可以作为样式指南,代码库或静态分析的体系结构文档,检查法律要求,无论公司决定其对“代码质量”的要求是什么

一旦到位,代码审核就成为必然的事情了,是否遵循了样式指南,我们是否具有所需的测试覆盖率百分比等?

如果您不具备此功能,那么代码审查就可能成为谁拥有最大的编码意愿的战斗,或者,根据您的情况,对判断的质疑要求重构与截止日期之前完成的功能。这只是浪费每个人的时间。


3

您的主要问题是,对重要的新功能进行代码审查是进行此讨论的错误时间。到那时,除了微小的改变,现在什么都为时已晚。正确的位置是在计划阶段,或者最晚在初步设计审查中。如果您的公司至少没有非正式地进行这些早期审核,则应首先改变这种文化。

下一步是邀请自己参加这些会议,并在这些会议上产生富有成果的想法。通常,这意味着不要试图在一夜之间改变一切,而是寻找可以隔离和解决的小块。这些块将随着时间的推移而显着增加。

换句话说,关键是在项目开始时定期建议较小的更改,而不是在项目结束时建议较大更改。


2

在我一直在进行代码审查的地方,如果它承诺(至少)进行一些重构,那么我将接受并确定代码提交。是作为提交的错误,作为故事还是作为承诺,在完成(某些)重构后再发送其他评论。

在这些情况下,如果我是编写代码进行审查的人员,那么我通常会准备两项更改,一项更改具有我的新功能或错误修复,另一项更改并进行了一些清理。这样一来,清理更改不会影响新功能或错误修复,但可以轻松地将其表示为令牌“是的,我知道这不能解决这些问题,但是在那儿”纯粹的清理“做”。

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.