通过代码审查调和童子军规则和机会主义重构


55

我坚信童子军规则

始终要比在检出时检查模块中的清洁剂。”不管原始作者是谁,如果我们总是花点力气,不管大小如何,以改进模块。结果是什么?我想所有人都遵循这个简单的规则,我们将会看到软件系统不断恶化的终结,相反,随着系统的发展,我们的系统将逐渐变得越来越好。我们还将看到团队关心整个系统,而不是整个系统。不仅仅是个人照顾自己的一小部分。

我也是机会重构相关思想的坚定信奉者:

尽管在某些地方可以进行一些计划内的重构工作,但我还是鼓励将重构作为一种机会主义活动,它需要在任何时候,任何地方需要清理代码的人(无论谁)进行。这意味着在任何时候,只要有人看到一些不尽如人意的代码,他们都应趁此机会立即将其修复,或者至少在几分钟内

特别注意以下来自重构文章的摘录:

我对任何可能导致机会重构产生冲突的开发实践都保持警惕。我的感觉是,大多数团队都没有进行足够的重构,因此,请注意任何阻碍人们进行重构的事情,这一点很重要。为了避免这种情况的发生,请注意任何时候您都不愿意进行小规模的重构,您肯定只需要一两分钟。任何此类障碍都是应该引起对话的气味。因此,请记下该挫折并与团队联系。至少应该在下一次回顾中讨论它。

在我工作的地方,有一种开发实践会引起严重的摩擦-代码审查(CR)。每当我更改不在“任务”范围内的任何内容时,我的审核员都会对我感到bu异,因为我正在使更改难以审核。当涉及到重构时,尤其如此,因为这使得“逐行”差异比较变得困难。这种方法是这里的标准,这意味着很少进行机会性重构,并且只会进行“计划的”重构(通常太少,太晚)。

我声称这样做的好处是值得的,并且3名审阅者会更加努力(实际上要前后理解代码,而不是仅仅关注变更范围的狭窄范围,因此,审阅本身会更好一些) ),以便接下来的100个阅读和维护代码的开发人员将受益。当我向审阅者提出这个论点时,他们说只要我不在同一CR中,他们的重构就不会有问题。但是我声称这是一个神话:

(1)大多数时候,您只有在从事作业时才意识到要重构的内容和方式。正如马丁·福勒(Martin Fowler)所说:

在添加功能时,您意识到要添加的某些代码与某些现有代码包含某些重复项,因此您需要重构现有代码以清理问题……您可能会工作,但意识到如果更改了与现有类的交互,则更好。在您认为自己已完成之前,抓住这个机会。

(2)没有人会喜欢您发布您不应该做的“重构” CR。CR有一定的开销,您的经理不希望您在重构上“浪费时间”。当它与您应做的更改捆绑在一起时,此问题被最小化。

Resharper加剧了这个问题,因为我添加到更改中的每个新文件(而且我事先无法确切知道哪些文件最终会更改),通常充满错误和建议-其中大多数都是应有的且应有的定影。

最终结果是我看到了可怕的代码,然后就把它留在那里了。具有讽刺意味的是,我觉得修复这样的代码不仅不会提高我的声誉,而且实际上降低了我的声誉,并将我描绘成一个“无专心的”家伙,他浪费时间去修复那些没人关心的事情而不是去干他的工作。我对此感到难过,因为我确实鄙视错误的代码,无法忍受观看,更不用说从我的方法中调用它了!

关于如何纠正这种情况有什么想法?


40
在这样的地方工作会让我感到不安your manager doesn't want you to "waste your time" on refactoring
Daenyth 2014年

19
除了具有多个CR外,关键点在于每次提交都应出于单一目的:一个用于重构,一个用于需求/错误/等等。这样,检查就可以区分重构和请求的代码更改。我还要指出,只有在有单元测试证明您的重构没有破坏任何东西的情况下,才应该进行重构(鲍勃叔叔同意)。

2
@ t0x1n我认为没有什么不同
Daenyth 2014年

2
@ t0x1n是的,我错过了那个。今天早上没有足够的咖啡。以我的经验,有几种重构方法。也许您查看了需要修改的代码,并立即知道它需要清除,所以您首先要这样做。也许您必须重构某些内容才能进行更改,因为新要求与现有代码不兼容。我认为重构本质上是您更改的一部分,不应其视为单独的内容。最后,也许您看到代码在更改过程中失败了,但是您可以完成更改。事实之后重构。

6
项目符号1并不声称不可能分离提交。它仅表示您不知道如何做,否则您的VCS会变得很难。我一直在这样做,甚至是一次提交并在事后将其拆分。
没用的2014年

Answers:


18

好,所以现在这里的事情比适合发表评论的要多。

tl; dr

你对你的直觉应该做(重构,当您去)是正确的。

鉴于必须解决较差的代码审查系统,实现此问题的难度归结为处理源代码和VCS的困难。很多人都说过您可以并且应该将更改(是的,甚至在文件中)也分成多个提交,但是您似乎很难相信这一点。

确实可以做到这一点。这确实是我们的建议。您确实应该学会从编辑,源代码操纵和版本控制工具中获得最大收益。如果您花时间学习如何正确使用它们,则将使生活变得更加轻松。


工作流程/办公室政治问题

我会提出与GlenH7基本上相同的建议,即创建两个提交-一个仅进行重构,(显然或显然)不进行任何功能更改,而另一个进行相关的功能更改。

但是,如果您发现许多错误,则选择一个错误类别以在单个CR中修复可能会很有用。然后,您将提交一个带有注释的提交,例如“重复代码”,“修复X型错误”或类似内容。因为这是一种类型的更改,大概是在多个地方,所以复查应该很简单。这确实意味着您无法修复发现的每个错误,但可以减轻走私带来的痛苦。


VCS问题

将对工作源所做的更改拆分为多个提交不是一个挑战。您尚未说出正在使用什么,但是可能的工作流程是:

  1. 如果您使用的是git,那么您将拥有出色的工具

    • 您可以git add -i从命令行用于交互式登台
    • 您可以使用git gui并选择单个的块和线来上演(这是我实际上更喜欢命令行的少数VCS相关GUI工具之一,另一个是一个不错的三向合并编辑器)
    • 您可以进行许多微小的提交(单独更改,或在多个位置修复同一类错误),然后重新排序,合并或拆分 rebase -i
  2. 如果您不使用git,则您的VCS可能仍具有用于此类操作的工具,但是如果您不知道使用的是什么系统,我将无法为您提供建议

    您提到您正在使用TFS-自TFS2013起,我认为它与git兼容。可以尝试使用该存储库的本地git克隆进行实验。如果此功能被禁用或不适合您,您仍然可以将源导入到本地git存储库中,然后在其中工作并使用它导出您的最终提交。

  3. 你可以手工做任何VCS如果你有机会像基本的工具diffpatch。这更痛苦,但肯定是可能的。基本工作流程为:

    1. 进行所有更改,测试等。
    2. 用于diff制作(上一次提交后的)所有更改的(上下文或统一)补丁文件
    3. 将其划分为两个文件:您最终将得到一个包含重构的补丁文件,而一个包含功能更改的补丁文件
      • 这并非完全无关紧要-emacs diff模式之类的工具可能会有所帮助
    4. 备份一切
    5. 恢复到最后一次提交,用于patch重播一个补丁文件,提交那些更改
      • 注意 如果补丁不能很好地应用,则可能需要手动修复失败的块
    6. 对第二个补丁文件重复5

现在,您有两个提交,更改已适当划分。

请注意,可能有一些工具可以使此补丁程序管理更轻松-我只是不使用它们,因为git为我做了。


我不确定我是否遵循-项目符号3.3是否假定重构和功能更改位于其他文件中?无论如何,他们没有。也许行分隔更有意义,但是我认为我们在CVS(TFS)中没有为此提供工具。无论如何,对于功能更改依赖于重构更改的许多(大多数?)重构来说,它是行不通的。例如,假设我重构方法Foo(需要在我的功能更改中使用它)使用3个参数而不是2个参数。现在Imy功能代码依赖于重构代码,即使按行拆分也无济于事。
t0x1n 2014年

1
在给定的工作流程中,同一文件中的不同行是可以的。鉴于这两次提交是顺序的,第二次(功能性)提交完全依赖于第一次就可以了。哦,据称TFS2013支持git。
没用的2014年

我们还将TFS用于源代码管理。您假设第二个提交将是功能性提交,而通常会相反(请参见我无法事先告知必须进行哪些重构)。我想我可以完成所有的功能+重构工作,然后摆脱任何功能,然后将其添加回单独的提交中。我只是说,要让几个审稿人感到高兴,这是很麻烦的(和时间)。在我看来,更合理的方法是允许机会重构,并以您自己同意CR进行此类更改作为回报(接受增加的难度)。
t0x1n 2014年

3
我认为您真的不了解我。在逻辑上,将源代码编辑和将编辑分组为提交,甚至在同一文件中进行编辑都是如此。如果这似乎很困难,则只需要更好地学习可用的源代码管理工具即可。
无用的

1
是的,您的理解是正确的,您将有两个顺序提交,第二个(功能性)提交取决于第一个(重构)。上述差异/补丁的工作流程也正是这样做是的方式并不需要手动删除更改,然后重新写他们。
没用的2014年

29

我将假设变更请求在您的公司中既庞大又正式。如果没有,只需将更改(如果可能)更改为许多小的提交(如您应该的那样)。

关于如何解决这种情况有任何想法吗?

继续做你在做什么?

我的意思是,您所有的想法和推论都是完全正确的。您应该修复所看到的问题。人们没有进行足够的计划重构。对整个团队的好处比给少数人带来的麻烦更为重要。

可能有所帮助的是减少战斗力。代码审查不应具有战斗性“为什么要这么做?”,而应该协同合作“嗨,伙计们,当我在这里时,我已经整理好所有这些东西!”。(如果可能,与您的主管/经理一起)改变这种文化非常困难,但对于创建一支高功能的开发团队来说至关重要。

您也可以(与领导/经理一起)与同事一起提高这些想法的重要性。让您问“为什么你们不关心质量?” 而不是问他们“为什么总是做这些无用的事情?”。


5
是的,CR大而正式。更改被CRed,注销,然后提交到队列中。应当将小的更改作为迭代添加到正在进行的CR中,而不是单独提交。WRT继续我正在做的事情,这的确可能使小组受益,但恐怕不会使受益。那些给我带来“不便”的人可能是在年度审核中给我评分的人。改变文化的问题在于,大酋长会相信这种文化。也许我只需要在他们的眼中赢得更多的尊重,然后再尝试类似的事情……
t0x1n 2014年

13
@ t0x1n-不要看着我。我已经在面对顽固吸吮的人面前做正确的事。如果我使人们开心,也许利润不如我本来要多,但我睡得很好。
Telastyn 2014年

感谢您的诚实。这确实是值得考虑的事情。
t0x1n 2014年

1
我也经常碰到这个。确保我有一个“清理”补丁,然后工作补丁会很有帮助。通常,我在系统中打架,然后离开工作压力较小的地方。话虽如此,有时您的同事担心还是有正当理由的。例如,如果代码迅速投入生产并且没有足够的测试。我已经将代码审查视为一种避免测试的尝试。这是行不通的。代码审查有助于使代码主体保持统一。它对bug的作用很小。
肖恩·佩里

1
@SeanPerry aggreed -但我说的是哪里的测试存在正常的情况下,错误bashes将被执行,等等
t0x1n

14

对于您的情况我很同情,但没有具体建议。如果没有别的,也许我会让您相信,尽管情况很糟,但情况可能会更糟。它总是会更糟。:-)

首先,我认为您的文化至少有两个问题,而不仅仅是一个问题。一个问题是重构方法,但是代码审查似乎是一个独特的问题。我会尝试分开我的想法。

代码评论

我所在的小组对代码进行了审查。该小组是通过合并来自公司不同部门的两个小组而形成的。我来自从事代码审查已经有好几年的团队了。我们大多数人都认为代码审查可以很好地利用我们的时间。我们合并为一个更大的小组,据我们所知,“另一个”小组甚至从未听说过代码审查。现在我们都在“他们的”代码库上工作。

我们合并时情况不妙。新功能年复一年地推迟了6-12个月。该缺陷积压的数量巨大,不断增长,并且耗尽了生命。代码所有权很强,特别是在最高级的“大师”中。“功能分支”有时会持续数年,并且跨越了几个发行版本。有时没有优势,但只有一个开发人员在到达主分支之前就看到了代码。实际上,“功能分支”具有误导性,因为它表明代码在存储库中的某个位置。通常,它仅在开发人员的个人系统上。

管理层同意,我们需要在质量降低到令人无法接受的低水平之前“做点事情”。:-)他们的答案是代码审查。在每次签到之前,Code Reviews都成为正式的“ Thou Shalt”物品。我们使用的工具是评审委员会。

在我描述的文化中它是如何工作的?总比没有好,但是这很痛苦,并且花费了一年多的时间才能达到最低的合规水平。我们观察到的一些事情:

  1. 您使用的工具倾向于以某些方式集中代码审查。这可能是个问题。审查委员会为您提供了精美,色彩丰富的逐行差异,并允许您将注释附加到一行。这使得大多数开发人员忽略了所有未更改的行。对于小的,孤立的更改而言,这很好。对于较大的更改,大量的新代码或包含500个重命名函数实例和10行新功能的代码,它不是很好。
  2. 即使我们处在一个古老的,病态的代码库中,而该代码库以前从来没有被审查过,但是对于审查员来说,对不是变更线的任何内容进行评论,甚至指出一个明显的错误,都变得“无礼”。“不要打扰我,这是一个重要的检查过程,我没有时间修复错误。”
  3. 购买“简单”的评论者。有些人将查看10个文件的评论,其中包含2000条更改的行,持续3分钟,然后单击“立即发送!”。每个人都迅速了解到这些人是谁。如果您真的不想一开始就审查您的代码,请将其发送给“简单”的审查者。您的入住时间不会减慢。您可以通过成为其代码的“轻松”审阅者来回馈青睐。
  4. 如果您讨厌代码审查,请忽略从审查委员会收到的电子邮件。忽略团队成员的后续行动。数周。直到您的队列中有3打公开评论,并且您的名字出现在小组会议中几次。然后成为“轻松”的评论者,并在午餐时间之前清除所有评论。
  5. 避免将您的代码发送给“严格的”审阅者。(这类开发人员会问或回答类似这样的问题。)每个人都会很快学会“硬”审稿人,就像他们学习简单的审稿人一样。如果代码检查是浪费时间(™),那么阅读有关您自己的代码的详细反馈既是浪费时间(™)又是侮辱。
  6. 当代码审查很痛苦时,人们会推迟审查并继续编写更多代码。您得到的代码审查较少,但每个审查都是大的。您需要更多,更小的代码审查,这意味着团队需要找出如何使它们尽可能轻松的方式。

我以为我要写一些有关代码审查的段落,但事实证明,我主要是在撰写关于文化的文章。我想可以归结为这一点:代码审查对一个项目可能是有益的,但是团队只能获得应有的收益。

重构

我的团队是否鄙视重构甚至超过了讨厌的代码审查?当然!由于已经提到的所有显而易见的原因。您浪费我的时间进行棘手的代码审查,甚至没有添加功能或修复错误!

但是代码仍然迫切需要重构。如何进行?

  1. 切勿将重构更改与功能更改混在一起。许多人提到了这一点。如果代码审查是一个摩擦点,请不要增加摩擦。这是更多的工作,但是您应该计划进行单独的审核和单独的签入。
  2. 从小开始。很小。甚至比那还要小。使用很小的重构就可以逐渐告诉人们重构和代码审查并不是纯粹的邪恶。如果您每周可以进行一次很小的重构而不会感到太多痛苦,那么在几个月内,您也许可以每周摆脱两次。它们可以更大一些。有总比没有好。
  3. 我们基本上没有单元测试。所以禁止重构,对吗?不必要。对于某些更改,编译器是您的单元测试。专注于可以测试的重构。如果无法测试,请避免更改。也许花时间写单元测试。
  4. 一些开发人员害怕重构,因为他们害怕所有代码更改。我花了很长时间才认识到这种类型。编写一段代码,在它“起作用”之前不断摆弄,然后再也不想更改它了。他们不一定了解为什么会这样做。改变是有风险的。他们不相信自己会做出任何改变,他们当然也不信任您。重构应该是关于不会改变行为的小的,安全的更改。对于某些开发人员来说,“改变不会改变行为”的想法是不可想象的。在这些情况下,我不知道建议什么。我认为您必须尝试在他们不关心的领域工作。当我得知这种类型可以持续很长时间时,我感到很惊讶,

1
这是一个超思想的答案,谢谢!我特别同意CR工具如何影响评论的重点……逐行是一种简便的方法,它并不涉及实际了解以前发生的事情和现在发生的事情。当然,没有改变的代码是完美的,不需要去研究……
t0x1n 2014年

1
可能会更糟。可能会下雨。 ”当我阅读您的最后一段(第二点#4)时,我在想:他们需要更多的审查,编码人员的审查。以及一些重构,例如:“ yourSalary = 0”

绝对在很多方面都找到了答案。我完全可以看出您来自哪里:我本人处在完全相同的情况下,这简直令人沮丧。您一直在为质量和良好实践而奋斗,不仅管理层,而且团队中其他开发人员的支持几乎为零。
julealgon

13

为什么不同时执行两个操作,却又分别提交呢?

您的同龄人有一点。代码审查应评估别人更改的代码。 不应碰触正在为其他人审阅的代码,因为这会使您作为审阅者的角色偏颇。

但是,如果您看到许多明显的问题,则可以采取两种选择。

  1. 如果代码检查还不错,则允许提交您检查的部分,然后在第二次检入时重构代码。

  2. 如果代码审查中有需要纠正的问题,请要求开发人员根据Resharper的建议进行重构。


我从您的回答中得知您相信“强大的代码所有权”。我鼓励您阅读Fowler关于它为什么是个坏主意的想法:martinfowler.com/bliki/CodeOwnership.html。为了专门解决你的观点:(1)是一个神话的重构发生,而你正在你的变化-而不是之前或在一个单独的,干净的,不相关的时尚之后作为单独的CR需要。(2)对于大多数开发人员来说,这永远不会发生。从不。大多数开发人员并不关心这些事情,更不用说来自不是其经理的其他人了。他们有自己想做的事情。
t0x1n 2014年

8
@ t0x1n:如果您的经理不关心重构,而您的开发人员也不关心重构……那么该公司正在慢慢陷入困境。逃跑!:)
logc

8
@ t0x1n只是因为您一起进行了更改,并不意味着您必须将它们一起提交。此外,它往往是有用的检查您的重构没有意外的副作用分别从检查你的功能改变了预期的效果。显然,这可能并不适用于所有重构,但是一般来说这并不是一个坏建议。
没用的2014年

2
@ t0x1n-我不记得说过任何有关强大代码所有权的事情。我的答案是保持您作为审稿人的角色纯粹。如果审阅者引入了更改,那么它们将不再仅仅是审阅者。

3
@ GlenH7也许这里有些误解-我不是审稿人。我只是在编写我需要的代码,然后运行我可以在此过程中改进的代码。然后,当我这样做时,我的审阅者就会抱怨。
t0x1n 2014年

7

我个人讨厌提交后代码审查的想法。进行代码更改时,应进行代码审查。我在这里谈论的当然是结对编程。配对时,您可以免费获得评论,并且可以获得更好的代码评论。现在,我在这里表达自己的观点,我知道其他人也有这样的看法,可能有一些研究证明了这一点。

如果您可以让您的代码审阅者与您配对,那么代码审阅的好斗元素就会消失。当您开始进行无法理解的更改时,可以在更改时提出问题,进行讨论并探索替代方法,这可能会导致更好的重构。您将获得更高质量的代码审查,因为这对将能够理解更广泛的更改范围,而不必过多地关注逐行更改,这是您通过并排代码比较获得的。

当然,这并不是对重构超出正在进行的更改范围之外的问题的直接答案,但是我希望您的同事在您进行更改时可以在其中理解更改背后的原因。

顺便说一句,假设您正在执行TDD或某种形式的红绿色重构,确保与同伴互动的一种方法是使用乒乓配对技术。在RGR循环的每个步骤中旋转驱动程序时,简单地解释一下,即对1编写失败的测试,对2修复它,对1重构,对2编写失败的测试……等等。


优点。不幸的是,我真诚地怀疑我能否更改“系统”。有时,审阅者也来自不同的时区和地理位置,因此在这种情况下,审阅者将不会飞行。
t0x1n 2014年

6

这个问题可能反映了组织文化中更大的问题。人们似乎更喜欢“正确地工作”而不是使产品变得更好,这可能是因为该公司具有“责备”文化而不是具有协作精神的文化,并且人们似乎更倾向于掩盖自己而不是拥有整个产品/公司愿景。

我认为您完全正确,审查您的代码的人如果有抱怨,那是完全错误的,因为您“触摸”“您的任务”之外的东西,试图说服这些人,但永远不要违反您的原则,对我来说,这就是真正专业的最重要素质。

如果正确的事情以某种愚蠢的公司方式给您带来不好的数字来评估您的工作,那又是什么问题呢?谁想在一个疯狂的公司中“赢得”这个评估游戏呢?尝试改变它!您很累,找到另一个地方,但是永远,永远不要违反您的原则,这是您拥有的最好的。


1
您一开始意识到要赢取薪水,奖金和股票期权奖励您,就开始想要赢得评估游戏:)
t0x1n 2014年

2
不,您是在用钱交易原则@ t0x1n。就那么简单。您有三个选择:修复系统,接受系统,离开系统。选项1和3对灵魂有益。
肖恩·佩里

2
一家专注于本地最大化原则的公司不仅对灵魂有害,而且通常不如关注全球最大化原则的公司最佳。不仅如此,不仅要花钱,而且每天要花很多时间在工作上,要安心于工作,感觉自己在做正确的事情,可能每月多花一美元会更好。
AlfredoCasado 2014年

1
嗯,灵魂被高估了;)
t0x1n 2014年

2
@SeanPerry我确实尝试过修复该系统,但这非常困难。(1)在这方面,我几乎是一个人,很难与大酋长抗衡(我只是一个普通的开发人员,甚至都不是高级人员)。(2)这些事情需要我根本没有的时间。工作量很大,整个环境非常耗时(电子邮件,中断,CR,需要修复的测试周期失败,会议等)。我会尽力进行筛选并提高工作效率,但通常我几乎无法及时完成“规定的”工作(高标准无济于事),更不用说更改系统了……
t0x1n 2014年

5

有时候,重构是一件坏事。 但是,并非出于您的代码审阅者给予的原因;听起来他们并不真正在乎代码的质量,而您确实在乎,这很棒。但是有两个原因使您无法进行重构1.您无法测试使用自动化测试(单元测试或其他测试)所做的更改,或者2.您正在对某些您不太了解的代码进行更改好; 即,您没有特定领域的知识来知道应该进行哪些更改。

1.当您无法测试使用自动测试所做的更改时,请不要重构。

进行代码检查的人员需要确保您所做的更改不会破坏任何曾经起作用的内容。这是不使用有效代码的最大原因。是的,将1000行长的函数(确实是可恶的)重构为一堆函数肯定会更好,但是如果您无法自动化测试,那么很难说服他人您做了所有事情对。我以前肯定犯过这个错误。

重构之前,请确保有单元测试。如果没有单元测试,请写一些!然后重构,您的代码审阅者将没有任何(正当的)借口感到不高兴。

不要重构不需要您没有特定领域知识的代码。

我工作的地方有很多化学工程繁重的代码。代码库使用化学工程师通用的习惯用语。切勿进行字段惯用的更改。这似乎是一个伟大的想法,重命名一个变量叫xmolarConcentration,但你猜怎么着?在所有化学课本中,摩尔浓度均以表示x。重命名它会使该领域人员更难知道代码中实际发生了什么。

无需重命名惯用变量,只需在注释中说明它们是什么。 如果不是惯用语言,请重命名它们。不要离开ijkxy,等漂浮时获得更好的名字会工作。

缩写词的经验法则:如果人们在讲话时使用缩写词,则可以在代码中使用该缩写词。工作中的代码示例:

我们谈论以下概念时总是将其缩写:“关注区域”变为“ AOC”,“蒸气云爆炸”变为VCE,诸如此类。在我们的代码库中,有人将所有称为aoc的实例重构为AreaOfConcern,将VCE重构为vaporCloudExplosion,将nPlanes重构为confiningPlanesCount ...,这使得具有特定领域知识的人实际上很难阅读代码。我也因为做这样的事情而感到内gui。


这实际上可能根本不适用于您的情况,但是我对此有一些想法。


谢谢科迪。关于“您的代码审阅者不会有(正当)借口的烦恼”-他们的借口已经是非法的,因为他们对变更的难度越来越大,而不是正确性,可读性或类似的东西。
t0x1n 2014年

2

现在,这个问题有两个不同的问题-易于检查代码检查中的更改以及重构所花费的时间。

在我工作的地方,有一种开发实践会引起严重的摩擦-代码审查(CR)。每当我更改不在“任务”范围内的任何内容时,我的审核员都会对我感到bu异,因为我正在使更改难以审核。

正如其他答案所言-您能否将重构签入与代码更改签入分开(不一定要作为单独的评论)?根据您用来进行代码审查的工具的不同,您应该只能查看特定修订版之间的差异(Atlassian的Crucible确实可以做到这一点)。

(2)没有人会青睐您发布您不应该做的“重构” CR。CR有一定的开销,您的经理不希望您在重构时“浪费时间”。当它与您应做的更改捆绑在一起时,此问题被最小化。

如果重构很简单,并且使代码更易于理解(如果只是重构,这就是您应该做的所有事情),那么代码复审应该不会花很长时间才能完成,并且应该将开销降至最低,当有人必须在将来再次查看代码。如果您的老板不满意,那么您可能需要轻轻地将他们推向一些资源,以讨论为什么《童子军规则》会导致与您的代码建立更有效的关系。如果您可以说服他们,现在“浪费您的时间”将在您/其他人回来对该代码进行更多工作后节省两倍,五倍或十倍的时间,那么您的问题就可以解决。

Resharper加剧了这个问题,因为我添加到更改中的每个新文件(而且我事先无法确切知道哪些文件最终会更改),通常充满错误和建议-其中大多数都是应有的且应有的定影。

您是否尝试过将这些问题引起同事的注意,并讨论为什么值得解决?并且可以自动修复其中的任何一个(假设您具有足够的测试覆盖率,以确认您没有通过自动重构破坏东西)吗?有时候,如果确实是挑剔的话,那么进行重构是“不值得的”。您的整个团队都使用ReSharper吗?如果这样做,您是否对执行哪些警告/规则有共同的政策?如果它们不支持,那么也许您应该再一次说明该工具在哪里帮助您确定代码区域,这些区域可能是造成未来痛苦的原因。


关于CR分离,我在我的帖子中以及其他一些评论中指出了为什么我认为不可能。
t0x1n 2014年

我不是在谈论挑剔的东西,我是在谈论实际的性能和正确性问题,以及冗余代码,重复的代码等。而这仅仅是R#的东西,还有一些我可以轻松修复的真正不好的代码。不幸的是,并非我的团队中的所有人都使用过剃刀,甚至那些没有认真对待过剃刀的人也是如此。需要进行大量的教育工作,也许我会尝试领导类似的事情。但是这很困难,因为我几乎没有足够的时间去做我需要做的工作,更不用说辅助教育项目了。也许我只需要等待停机时间即可利用。
t0x1n 2014年

我只是插话说那绝对不是不可能的,因为我一直都这么认为。进行无需重构的更改,将其检入,然后进行重构以清理并检入。这不是火箭科学。噢,并准备辩护为什么您认为值得花时间进行重构和检查重构的代码。
埃里克·金

@EricKing我想我可以做到。但是:(1)我必须处理丑陋的代码,并记下要改进的内容,直到完成对功能的更改,这既使功能变差,又减慢了我的功能进展(2)一旦提交了功能更改,然后重新访问我的重构笔记,这只是第一次迭代,完成重构可能会花费更多时间,正如您所建议的那样,鉴于我的工作已经“完成”,我很难向经理解释。
t0x1n 2014年

2
“我正在谈论实际的性能和正确性问题”-那么这可能会扩展重构的定义;如果代码实际上不正确,则将构成错误修复。至于性能问题,这不是您应该在功能更改中解决的问题,它可能需要度量,彻底的测试和单独的代码审查。
克里斯·库珀

2

我记得25年前左右,我碰巧正在为其他目的工作的“清理”代码,主要是通过重新格式化注释块和制表符/列对齐来使代码整洁,因此更易于理解(没有实际的功能更改) 。我碰巧喜欢井井有条的代码。好吧,高级开发人员很生气。事实证明,与个人副本相比,他们使用某种文件比较(diff)来查看发生了什么变化,现在,它给出了各种各样的误报。我应该提到,我们的代码库位于大型机上,没有版本控制-您基本上重写了那里的内容,仅此而已。

这个故事的主旨?我不知道。我猜是有时候你不能取悦除了你自己以外的任何人。我没有浪费时间(在我眼里) -在清理代码更容易阅读和理解。只是其他人使用的原始变更控制工具使他们付出了一些额外的一次性工作。这些工具太原始了,无法忽略空格/制表符和重排注释。


是的,我也为间距留了很多软管,还有一些琐碎的东西,例如多余的铸件等。我的更改没有完全规定“噪声”。
t0x1n 2014年

2

如果您可以将请求的更改和未请求的重构拆分为(很多)单独的提交(如@ Useless,@ Telastyn和其他人所指出的那样),那么这就是您能做到的。您仍将在单个CR上工作,而无需创建“重构” CR的管理开销。只是保持您的承诺小而集中。

我没有给您一些建议,而是建议您从专家那里得到更大的解释(实际上是一本书)。这样,您将能够学到更多。阅读“有效使用旧版代码工作”(作者Michael Feathers)。本书可以教您如何进行重构,并与功能更改交织在一起。

涵盖的主题包括:

  • 了解软件变更的机制:添加功能,修复错误,改进设计,优化性能
  • 将遗留代码纳入测试工具
  • 编写测试以防止引入新问题
  • 可以与任何语言或平台一起使用的技术,例如Java,C ++,C和C#中的示例
  • 准确识别需要更改代码的位置
  • 应对非面向对象的遗留系统
  • 处理似乎没有任何结构的应用程序

本书还包括24种依赖打破技术的目录,这些技术可以帮助您隔离处理程序元素并进行更安全的更改。


2

我也是Boyscout规则和机会重构的忠实拥护者。问题通常出在管理层的支持上。重构伴随着风险和成本。管理层经常忽略的是技术债务也是如此。

这是人的本性。我们习惯于处理实际问题,而不是试图防止它们。我们是被动的,不是主动的。

软件是无形的,因此很难理解,就像汽车一样,它需要维修。没有理智的人会买车,永远不会维修。我们接受这样的疏忽会降低其使用寿命,从长远来看,代价会更高。

尽管许多经理都了解这一点,但他们仍对生产代码的更改负责。政治使得人们更容易离开孤独。通常,需要说服力的人实际上是在您的经理之上,而他只是不想为了将您的“伟大创意”投入生产而奋斗。

老实说,您的经理并不总是相信您的补救措施实际上是您认为的那么好。(蛇油?)有推销技巧。帮助他看到收益是您的工作。

管理层不同意您的优先事项。戴上管理帽,以管理的眼光来看。您更有可能找到合适的角度。坚持不懈。通过不允许第一个负面回应阻止您,您将带来更多变化。


1

如果您可以将请求的更改和未请求的重构拆分为两个单独的更改请求(如@ GlenH7所示),那么这就是您可以做到的。那么,您不是“浪费时间的人”,而是“努力工作的人”。

如果您经常遇到无法分割它们的情况,因为请求的工作现在需要非请求的重构来编译,我建议您坚持使用此处概述的参数来使用工具来自动检查编码标准(Resharper单独发出警告可能是个不错的选择,我对此并不熟悉)。这些参数都是有效的,但是您可以利用其中的一个附加好处:有了这些测试,现在就有责任在每次提交时通过测试。

如果您的公司不想“浪费时间进行重构”(这对他们而言是一个不好的信号),那么他们应该向您提供一个“警告抑制”文件(每个工具都有其自己的机制),以免您再被烦恼这样的警告。我说这是为了为您提供针对不同情况(甚至是最坏情况)的选项。最好在您和您的公司之间有明确声明的协议,也要有预期的代码质量,而不要双方都隐含假设。


对于新项目,这将是一个很好的建议。但是,我们当前的代码库很大,Resharper会针对大多数文件发出许多错误。强制实施为时已晚,抑制现有错误会使情况更糟-您将在新代码中错过它们。还有很多错误,问题和代码气味,静态分析器无法捕获,我只是以Resharper警告为例。再说一次,我可能对“浪费部分”的措辞太苛刻了,我应该说些“专门的时间而不是优先考虑的事情”。
t0x1n 2014年

@ t0x1n:童子军规则主要涉及您正在触摸的模块。这可以帮助您绘制第一条分界线。我知道,警告的警告不是一个好主意,但是从公司的角度来看,在新代码中禁止警告是正确的,并且遵循其惯例-好吧,也许我被我自己的论点
吓倒了

1
那是令人沮丧的部分!我只触摸我本来会碰到的文件,但是我收到的投诉也一样!我说的警告不是样式警告,而是实际的性能和正确性问题,以及冗余代码,重复代码等
。– t0x1n 2014年

@ t0x1n:听起来确实很令人沮丧。请注意,我不仅指“静态代码分析”,还指其他建议,等同于Nexus。当然,没有工具能够抓住100%的语义。这只是补救策略。
logc 2014年
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.