【外评】代码审查确实能发现漏洞

2015 年,微软公司发表了一篇题为《代码审查找不到漏洞》(Code Reviews Do Not Find Bugs) 的研究报告,这篇文章的名字似乎很奇怪,因为审查人员确实发现了漏洞。

作者是这么说的:

与通常所说的代码审查的主要目标相反,代码审查往往找不到应该阻止代码提交的功能缺陷。在评审人员提供的意见中,只有约 15% 指出了可能存在的缺陷,更不用说阻塞性缺陷了。

这是一个具有误导性的统计数字,因为它对缺陷发现率一无所知。只有约 15% 的吸烟者会得肺癌,但这并不意味着我们可以忽略吸烟这个原因–80% 以上的肺癌病例都是由吸烟引起的。事实上,15% 的代码审查意见是关于缺陷的,这并不说明缺乏被检测到的缺陷,而是说明审查员也写了很多关于其他事情的意见,我们稍后会看到更多关于这一点的内容。

这恰恰不支持审稿人没有发现缺陷的观点。例如,如果他们数据中的评论平均每条有四条评论,那么超过一半的评论确实得到了关于缺陷的评论!

但我们不需要猜测他们的数据中有多少评论,因为之前已经有这方面的研究。我们早就知道,代码评审(以及结对编程)只需增加 15% 的时间投入,就能多发现 60% 的缺陷。

在这一点上,我们还有关于代码审查有效性的更详细数据。在一天中前 60 分钟的代码审查中,只要每十分钟审查的代码少于 50 行,审查员大约每十分钟就能发现一个缺陷。

你能想象还有什么活动能让一个开发人员每 10 分钟就发现一个缺陷吗?当然不是通过手动测试,甚至所有形式的自动测试都无法超越这一速度,因为一个组件的自动测试总成本很快就会超过 10 分钟的时间投入。代码审查有效得令人发指。在我们可能采取的所有质量措施中,代码审查是我最不愿意放弃的措施。

微软的作者还报告了代码审查对学习代码库的显著效果。

由代码更改作者判断的代码审查意见的有用性与审查者的经验呈正相关。如果事先没有接触过被审查的代码库部分,审查员的评论中平均只有 33% 被变更的作者认为是有用的。不过,审核员的学习速度通常很快。当第三次审核代码库的同一部分时,他们的意见中有用的比例会增加到约 67%。到第四次时,其有用性就相当于项目的长期平均值了。

当然,他们并没有详细说明 “项目的长期平均水平 “是处于相对较低还是较高的熟悉程度,但在我看来,只需四次代码审查就足以让人们相对熟悉代码库的全新部分。假设一个合理大小的变更(50-100 行代码?)和一个合理的初学者审查速度(每 10 分钟审查 10-50 行代码?

这是一个作弊码。探索和利用总是相互冲突的;对于软件工程来说,这意味着知识共享和速度是相互冲突的。如果我们让一个对某个组件有经验的人去完成一项任务,他们会很快完成,但我们却无法传播有关该组件的知识。如果我们让一个没有经验的人去完成任务,那么任务可能会花费更长的时间,但我们却能获得知识共享。或者!我们让没有经验的人审查有经验的人的代码。这几乎不花时间(开发时间增加 15%),而且他们还能因此熟悉组件。我们既能共享知识,又能提高速度。

微软论文的主要论点似乎是,代码审查不值得花费时间。我们已经看到,如果审查工作量管理得当,代码审查在发现缺陷和学习代码库方面都非常有效。

微软的论文还提到了其他一些似乎与他们的论点相矛盾的地方,比如

  • 关于代码长期可维护性的反馈意见占代码评审意见的 50%。当然,这难道不是一件好事吗?根据我的经验,在不进行同行评审的组织中,代码的长期可维护性是一个大问题。
  • 评审是作者和评审者证明自己的机会。这似乎是一个潜在的激励因素,而不是一个问题。
  • 代码评审的有用性与变更大小呈负相关。这是一个特点,而不是一个错误。它鼓励保持小规模和原子化的变更。
  • 开发人员每周要花六个小时进行代码审查。这有点太多了(还记得之前的 “每天第一小时 “规则),但这应该只会导致工作效率的微弱下降–代码审查应该仍然是一个明显的赢家。

我认为,根据作者的经验,代码审查的真正问题在于他们提出的最后一点:

  • 审查周转时间的中位数为 24 小时。有关代码审查的研究大多是在实验室环境中完成的,而不是在综合的工作环境中,因此并不强调周转时间。但根据我的经验,有一半的审核时间超过了 24 小时,这似乎太多了。我在之前的工作中计算过,周转时间的中位数是 6 个小时,这让我感到非常痛苦(这也是我计算这些数字的初衷)。

最后,我同意作者的观点,即我们不应该盲目照搬最佳实践(即货物崇拜实践),但这次报告的经验似乎并没有遵循最佳实践,因此在评判最佳实践之前,我们应该首先确保我们遵循了最佳实践。

如果这些做法在大型组织中不切实际,这将是一个值得公布的重要观察结果,而不是声称这些做法在遵循时不起作用。

本文文字及图片出自 Code Reviews Do Find Bugs

你也许感兴趣的:

共有 628 条讨论

  1. 同意。在我的职业生涯中,我主要负责管理和审查代码。我发现了很多 bug,偶尔也会发现一些可能会导致中断或给用户带来显著问题的 bug。

    但我发现更多的是没有经过深思熟虑的代码。技术债务和代码气味是真实存在的,它们会影响团队的绩效。要将这些问题消灭在萌芽状态,就需要高质量的公关审查,并花时间与提交者就发现的问题进行沟通。

    在我现在工作的公司,我和我的团队已经将高质量的公关审查变成了常态。我强烈推荐!

    其中一个关键点是 “善意而非讨好”。在公共关系中留下评论时要乐于助人,但不要为了避免冲突而表现得和蔼可亲。

    此外,如果你觉得代码审查是浪费时间,我可以向你推荐我经常做的一件事–给予警告。对于类似的 PR,我会批准并就我希望在将来修正的地方给出评论。我不会因为一些小事而耽误合并,但同时我也不会让小事一直拖延下去。

    1. “技术债务和代码气味是真实存在的

      我认为最让我头疼的是,很多时候,”尽快发布 “是一个合理的商业理由,但缺少的是对附加条件的问责。比如,好吧,如果我们现在不想修复这个问题,因为它需要在下一个版本中出现,那么我们可以按原样合并它,但你不能把它记录在外部文档中,它不能成为 API 的一部分,而且在 X、Y 和 Z 被重写为与 ABC 一致之前,不能在这个方向上进行任何进一步的开发。

      我发现这类讨论很难得到认同。每个人都乐于微笑点头,相应的票据也会被归档并附上截止日期,但下一个版本发布后,新的业务影响因素就会成为重点,清理票据就会被悄悄移到积压票据中,截止日期也会被取消。

      多年来,这种情况一直在重复,让我对这个过程产生了一种愤世嫉俗的情绪,感觉代码审查至少在一定程度上是一种挫败感的表现;我没有足够的支持来坚持在前期做好代码审查工作,所以我实际上只是在预览一两年后会发生什么。

      1. 关于这个问题有几点看法。

        1.很多问题都是由于人少事多造成的。如果只有一两个开发人员,而积压的工作越来越多,那么问题并不在于你没有时间解决问题,而是你的人手不足。如果你有足够的人手,那么从业务的角度来看,就不会出现有人在完善之前的工作,而另一个人却在做下一件事的情况。

        2.如果你的人手不是不够,那么清理新代码的最佳时机就是在编写过程中或编写完成后。我喜欢用的一句话是 “趁记忆犹新”。这样既节省了时间,又不会增加新的错误,因为你不必再次记住所有内容,将所有上下文重新载入你的大脑。

        1. > 如果你不是人手不足

          值得注意的是,有一些脂肪是好事。当你是一家初创公司,你正试图自力更生时,我可以理解,但在某些时候,你需要一些脂肪。脂肪太多不好,但没有脂肪也不好。初创企业必须精益求精,但如果大企业过于精益求精,那就叫厌食症。

          1. 的确,如果你读过《目标》或《凤凰计划》,就会发现他们把这叫做 “懈怠”。关于 “松弛 “为什么重要,有一整套理论。

          2. 另一种观点认为,脂肪在人体内是有作用的。诚然,如果你要优化一个非常狭窄的结果,非常低(但不是无)脂肪的身体看起来很理想,但首先,这实际上是一个非常不健康的身体;其次,世界上最好的举重运动员实际上都有相当可观的脂肪储备来支持和维持他们的肌肉。

            没有脂肪有助于提高速度和效率,但会妨碍你变得强壮。

      2. 不过预览还是很有价值的,当你已经知道某样东西是怎么坏的时候,你就会显得像个魔法师。

        1. 但是,当你不断提醒人们注意同样的问题,却在几个月甚至几年后不断遇到这些问题时,你就会觉得自己像卡桑德拉。

          你只能把 “惊讶的皮卡丘 “这个备忘录发这么多次,它就会失去光泽。

        2. 或者是无能。如果你早知道会出问题,为什么还要批准?你唯一的辩解就是 “当时有很大的压力要发布 xyz”。这样的辩解并不值得同情。认为被破坏的功能是有史以来最重要的事情的动物精神早已不复存在,而对之前最重要的功能所造成的新的中断的挫败感已经占据了上风。

          1. 不要批准!这其实是你可以做的一件事。

        3. 很多时候,这比 “这显然会在某个时候以某种方式影响生产 “更微妙。问题更像是觉得逻辑太复杂,以后很难维护,或者觉得应该或不应该使用某个库,或者觉得用线程做的事情应该是异步的。

          所以是的,并不像 “我说过会发生,但它确实发生了 “那样简单明了,而更像是 “我有一种感觉,这将会是一种痛苦,而我确实在审查代表这种痛苦的代码”。

      3. “没有以后。”这是我的新口头禅。

        1. 这让我想起了代码库中遍布的 “Todos”……我喜欢用 “尤达 “来形容……做或不做,都没有 Todo。

          1. TODO 本身并不坏,但我认为意图很重要–有多大可能有人纯粹是为了解决这条评论而回到这里?如果不太可能,那么 TODO 将在未来重构的背景下被使用,在这种情况下,它就是给最终考虑这项工作的人的一份礼物,帮助他们理解代码或背景的某些内容,而你在项目中意识到这些内容时已经太晚了,无法对其采取行动。

        2. 我最喜欢与此相关的咒语:

          没有什么比暂时更永恒。

          … 和 …

          我们没有时间做对,但我们有时间做两遍。

    2. 我是一名新经理,正在努力让我的团队理解代码审查的价值。我已经经历了太多的重写和重写面条代码,现在我对代码审查更加挑剔,我正试图在我的团队中推广这种文化。您有什么建议吗?

      – 同样的人在别人的合并请求上留下了详细的评论,但当别人没有为他们的合并请求付出同样的努力时,他们就会感到气馁。

      – 人们盲目地接受建议,没有任何抵触情绪,也不进行任何讨论,只为完成审核。

      – 人们把 MR 发到侧频道或其他团队,让自己的修改在没有阻力或来回讨论的情况下被合并。(我曾不得不恢复过几次这样的修改)。

      1. 良好的公关文化肯定是要从头开始建立的,并且要得到自上而下的支持。在 Shopify,我认为他们拥有非常好的公关文化,我们有一些我认为有帮助的东西(除了良好的 CICD 和静态分析工具之外):

        1.公关应该等待 2 次验收,1 次验收即可发货,0 次验收即可紧急发货。我们的团队中应该有 2 名审核人员。

        2.根据代码项目的不同,我们必须填写 PR 的模板,其中包含哪些内容,有哪些改动,测试代码时需要注意什么,等等。

        3.某些领域的代码所有者可能需要特定团队的额外审核。

        4.我们应该在审查分支时对其进行检查和测试。因此,除少数情况外,我们真的不鼓励快速阅读和 LGTM。

        我见过很多地方盲目地接受公关,这很困难,因为如果不真正执行和鼓励这种文化,就很难改变。

        1. 此外,代码审查对于需要被审查的代码也同样有效。

          最糟糕的同行评审发生在成千上万行的 PR 上,因为没有人愿意读那么多,而且会有遗漏。我所见过的成功的代码评审是,人们将代码拆分成可评审的部分,而这些单个的评审是如此之快,以至于最终完成的速度比一份巨型公关还要快。

          1. 在不把任何东西分解成一堆更小的改动的情况下,把一个自成一体的改动合理地分解成最小的改动需要多少额外的时间?

            1. 大约 10-15 分钟 ….

                  git co master
                  git co my-branch -- .
                  git add -up . # select changes relevant to first pr
                  git commit
                  git reset HEAD --hard
                  # and again...
              1. 这个问题是专门针对这种方法行不通的情况提出的,例如,您的团队不想批准只包含死代码的 PR,或者因为变更的任何子集无法编译,或者没有其他部分就无法保留正确的行为。

                1. 拥有合适的工具有助于发布 “不完整 “的工作,例如功能标志,这样您就可以发布某个功能的非常轻量级且尚未准备好供最终用户使用的版本,并继续在较小的 PR 中对其进行迭代。

                  例如,第一次发布时添加了一个新的屏幕,但只转储了输出结果

                  第二个版本添加输入字段和控件

                  下一遍添加验证

                  然后添加动画

                  等等

                  1. 理论上听起来很不错,但实际上呢?

                    1.经常需要修改或重构旧代码。仅有功能标志是不够的。

                    2.即使是功能标志本身也可能是有风险的,可能会影响现有客户的使用。

                    大多数情况下,确实需要对旧代码进行修改,至少在我的经验中,确实没有那些完美的孤立的新功能。

                    1. 如果说重构应该被放在特性标志后面,*因为*它们是如此具有破坏性。

                  2. 在我看来,这是一种糟糕的方法,也是我讨厌如今使用特性标志的原因。

                    例如,如果没有输入验证(前端或后台),我是不会批准任何东西的。我不知道你是否真的会在删除 fflag 之前添加验证功能。”相信我兄弟 “对我不起作用。

                    1. 我的意思是,你可以在功能标志后面对已编写的功能进行验证,而暂缓验证尚未存在的功能。

                      功能标志并不意味着把孩子和洗澡水一起扔掉。

            2. 实践中的忒修斯之船。

              有点像。

              原子提交很难。

          2. 您认为这可以在 PR 的提交级别上实现吗?

            1. 如果每个提交都可以单独审查,那就可以了。

              主要问题在于人、

              1.不愿意阅读冗长的内容,从而导致审批速度减慢,因为没有人愿意去碰它

              2.无法有效审查长篇大论,更有可能漏掉一些内容。

        2. 我们也有这些问题,但通常人们把这些当作官僚主义障碍,并不真正执行这些步骤。例如,模板被忽视,审稿人不检查,只是 LGTM 就可以了。很少有人真正认真去看。

      2. 代码审查文化不会凭空产生。除非您有 CI/CD、测试、任务估算、回顾、事件后记等流程,否则您永远无法让人们相信这些流程是有用的。所以,就从这些开始吧。

        增加更多的流程总是会遭到反对,但如果团队成员都认为保持工作正常是首要任务,那么这些流程就会慢慢/自然而然地出现,因为团队会意识到,积极主动地投资这些流程将为他们节省时间。

      3. 这需要时间。

        对于不习惯代码审查的团队来说,一开始可能会觉得麻烦多于值得。很可能在最初的几个月里,麻烦会大于价值。坚持做下去,最终聪明的开发人员会发现 “如果我们无论如何都要做这件事,我们不妨找点有用的东西来说说”:)

        有几件事情可以做得更顺利:

        – 管理期望值。最初可能只是 “我们只是想在每次修改时多一双眼睛 “或 “了解其他团队成员在做什么”–即沟通第一,改进代码第二。

        – 设置工具,使流程顺畅。如果有人想一劳永逸地完成工作,那么对他们来说,使用你的官方审核流程应该比使用一些旁门左道更容易。一个恶毒的替代方案就是让使用旁门左道变得更难;)

        – 利用自动化。在 PR 上运行测试、分类器、静态检查器等,这样即使没有人留下有趣的评论,开发人员也能得到有用的东西。

        – 如果团队中的某些成员已经有了代码审查的经验,那就调整他们的工作量,让他们能做更多的审查工作。他们可以以身作则,有效地培训其他人。

        – 确保审核中的代码变更大小合理。鼓励尽早并经常提交变更以供审核。说 “这是我花了 3 个月开发的功能,周五就要提交,请审核 “不会让任何人高兴。

        – 让审查不再可怕。代码审查不仅仅是为了发现错误和缺陷,也要鼓励审查者说正面的话。

        1. 这是很好的建议,我觉得 “无论如何我们都必须这样做 “这句话更像是…… “所以我们不妨让自己轻松一点”……例如,写出能正常工作的代码,并通过测试和手动(如果需要)进行自我测试,这样审阅者就不必在实际运行代码时陷入困境(开始时可以添加屏幕截图,但到后来就不需要了)。尽可能减少公关,也就是一个功能卡的多个公关接踵而至,尽快提交有价值的公关,不要因为吹毛求疵而阻拦,而是在共同的期望中开始就更好的事情达成一致,并在下一次修改中实现。

          一般的口号是 “如果它能运行,就不应该被阻止”,开发人员可以选择当场改进可维护性,也可以自行决定推迟到下一次或以后的 PR。毕竟你们彼此信任。

        2. > 设置工具,使流程顺畅。

          > 利用自动化。运行 […]流水线、静态检查器 […]。

          除非你将它们设置为只给出警告而不是阻止构建/合并,否则它们并不能使流程顺畅。无论如何,它们都可能被忽略。

          我认为,在得到团队认可之前,应避免使用内衬程序等。

          1. 这要看情况。如果你的代码库中已经没有林特警告,那么添加阻塞检查以防止出现新的林特警告就没什么大不了的。但如果阻塞检查意味着每个人都必须放弃一切,花一周的时间来修复代码,这当然就不顺利了。

            PS.另外,无论您设置了什么自动阻塞,手动覆盖都是个好主意。大多数流水线都已具备这一功能。

        3. > 一个恶毒的替代方法是增加使用侧信道的难度

          如果人们在寻求旁门左道,这就是一个信号。忽视这一点,忽视人们正在想方设法有效地完成自己的工作,我认为似乎没有抓住重点。

          > 如果一些团队成员已经有了代码评审的经验,那么调整他们的工作量,让他们可以做更多的评审。他们正在以身作则,有效地培训其他人。

          这可能会适得其反。突然之间,只有少数(可能只有一两个)团队成员在做所有的代码评审。他们感受到了压力,不想成为出货的阻塞部分,因此他们的审查工作就草草了事。他们会在其他前辈的意见上盖上 LGTM 的橡皮图章,并可能在第二天才审查其他审查意见。他们很难完成自己的工作,每天 2 个小时的代码审核工作影响巨大(如果审核其他 2 名开发人员的工作,而他们在一天内 6、8、10 个小时都在编写代码,那么第二天就需要 2 个小时来审核他们的工作)。

          > – 确保审核中的代码变更大小合理。鼓励尽早并经常提交修改以供审核。说 “这是我花了 3 个月编写的功能,周五就要提交,请审核 “不会让任何人高兴。

          反过来说,”嘿,请尽快审核,这样我就能在接下来的两个小时内再给你一系列 4 个修改,最后再发送更新来完成这件事”。

      4. 我写了一些我在团队中成功应用的规则。https://max.engineer/mindful-code-reviews

      5. 文化是创造出来的,不是偶然的。

        我会在小组会议上提出所有这些问题,甚至更多。尽量让大家了解审核给提交者和审核者带来的各种好处–让他们说出自己想要或可能得到的好处。讨论各种类型的意见(明确的错误、性能、风格、健壮性、因素和组织等),以及从不须采取行动到小毛病再到阻碍的各种优先级。讨论审核本身的优先级。减少审核的延迟会产生巨大的积极影响。

        1. 人都是聪明的–听听他们的担忧如何?在用一系列 “最佳实践 “和 “预期结果 “来打击他们之前,先听听他们的意见吧。

          我开始认为,在代码审查中,挑毛病完全会适得其反。

          自从我了解了 “Ship/Show/Ask “之后,我对代码审查的看法发生了翻天覆地的变化:https://martinfowler.com/articles/ship-show-ask.html;我不再相信审查每一个改动都是健康的,看到其他模式的不同之处,我就知道它现在是有害的。在我看来,另一种好方法是允许合并后审查,”ship/show/ask “更好,但为什么一定要在合并前进行代码审查呢?

      6. 社会氛围如何?

        我这么问是因为我有一份工作,在 COVID 之前,技术团队只有几个呆头呆脑的程序员在一间办公室里,而在 COVID 之后,技术团队只有一群我不在其中的朋友。

        我的意思是,在 COVID 之前,创始人经常会带我们出去吃午饭或打网球,就像正式的团队建设时间一样。我很喜欢这样做,因为我很挑食,很难交到朋友,所以如果公司有正式的活动,我就更容易融入其中。

        在 COVID 之后,官方活动的力度减弱了。团队太大,无法带所有人出去玩,我也没有加入那些自然而然找到社交方式的朋友圈。

        在新的环境中,我不再觉得自己是团队中平等的一员,我觉得自己就像一个局外人,拥有纸面上的权力,却没有完成工作和度过工作日所需的任何友情。

        尽管每个人都一再表示,我作为最资深的程序员受到了尊重和重视,但我发现在新的环境中,我不可能成为一个好队友,我觉得自己整天都在刻薄,没有人把我当人看。这就是我辞职的部分原因。

        在那样的环境中,我的代码审查很糟糕。

        现在,我在一家远程公司工作,在那里,我再次感觉到每个人都同样不合群。如果他们有了办公室,我可能会套现,然后去度假一年。

        编辑:差点忘了,原来那个 “书呆子程序员 “团队中的另一位女成员,也在我辞职的同时倦怠了。她在新环境中也没交到什么朋友,似乎更乐于追求自己的兴趣爱好,在工作间隙过得轻松自在。

        1. 大三学生能和大四学生做朋友吗?我觉得这是一种 “教授-学生”/”私人-中尉 “的关系。

          我在代码评审中也整天刻薄,而且和团队中的大多数人相比,我还是个相对低年级的学生!>:]他们不把我当人看,因为我不是人。我没有他们的人类情感和关切。我只关心代码。不过,感觉上他们还是喜欢和尊重我的!

          1. 我想我不喜欢成为唯一的中尉吧?

            感觉我的权力只停留在纸面上,却没有落到实处。一切都井井有条,没有人把任何事情写下来……

      7. > 同样的人在别人的合并请求上留下了详细的评论,但当别人没有为他们的合并请求付出同样的努力时,他们就会感到气馁。

        这种情况总是岌岌可危。因为一旦这些人变得颓废,你创造良好公关文化的能力也会随之消失。他们厌倦的原因有很多。如果这些人没有得到明示或暗示的重视,他们就会知道。如果做错事的人先得到晋升(甚至以同样的速度晋升!)、同样的加薪/奖金,而且在所有方面都一视同仁,那么员工几乎总是会得出这样的结论:”如果这对我没有任何好处,我为什么要付出这些额外的努力呢?我不认为提前晋升或类似的承诺会有好的效果,因为有很多员工都得到过这样的承诺,但却没有兑现[0]。因此,在短期内需要有一些奖励,哪怕是微不足道的奖励。

        此外,不要低估明确说 “干得好 “的价值。在沟通中,往往存在着一种巨大的偏见,即只有在出错的时候才会说 “做得好”,而在做得好的时候却不说。你不必事事都说 “干得好”,但我想你会惊讶于有多少人从未从管理层那里听到过这句话。

        [0] 我想和大家分享一个我遇到的故事。我是一名绿色(机械)工程师,在一家初创公司工作。我拥有物理学学位,而不是机械工程学位,但我一直都是动手能力很强的人。但正因为如此,我的薪水较低,也不被重视。我问我的经理,我需要做些什么才能得到晋升,与其他人平起平坐。我把它写成了书面材料,这样我就可以参考了。在下一次绩效考核时,我被说得一无是处。抱怨我没有做到这一点或那一点(有时是不可能做到的事情,有时则很奇怪,比如 “你的代码可能快了 20%,但 X 无法理解它,所以我们不能使用它”–X 是一位只用 C++ 写了不到一年的经理,而我__大量__记录了我对函数的使用)。我询问了我所做的事情和承诺。他们承认我做了所有这些事,甚至更多。其中之一就是拿到了一份合同(我想他们把合同写在这里并不是指望我能拿到),我是唯一一个拿到合同的非经理人,为公司带来了 20% 的收入,同时我也是那个项目上的唯一一个人。你可以想象,我从那次会议上走出来时,我的简历已经被擦得锃亮,从那时起,我就成了朝九晚五的上班族,做着最基本的工作。但我的下一任经理对我赞赏有加,会批评而不是抱怨。他理解我的工作存在未知数,当我加班时,他会让我回家。我一生中从未如此努力地工作过,这也是我最快乐的时光。一个经理可以成就一个员工,也可以毁掉一个员工。这其中的一部分原因是,也许有办法让那些崩溃的员工重新振作起来,但你可能需要先弄清楚他们为什么会崩溃。以及这是否是你能解决的问题。我相信环境对员工的态度有很大的影响,进而影响效率/生产力。如果激情能抵得上 10 点智商,那么快乐至少是让员工高效工作的一个重要因素。每个人都能赢,因为这不是一个零和游戏。

      8. 与人交谈,好奇他们为什么不重视代码审查。

      9. 请继续努力提交 PR!垃圾代码属于垃圾。

        1. 大量垃圾代码正在为所有大型科技公司赚取数十亿美元。亚马逊、Facebook 等公司的大部分代码都是垃圾代码。更不用说那些 “自负盈亏 “的小公司了,它们的代码都是创始人级别的,而且还处于不断 “修复和扩展 “的阶段。

          更重要的是,当一个人致力于某件事情,然后它被称为垃圾时,会形成一种什么样的文化?另一方面,如果有人审视了自己的进展速度,并做出了一个战术性决定:也许某件事情还不错,虽然不是很好,但已经很不错了–他们会把节省下来的时间花在完成项目上;然后,当评审者认为公关是 “垃圾 “时,又会发生什么呢?

          我还认识到,我需要更加有意识地让各种火苗燃烧起来。不可能事事顺心,有时简单低质才是最好的。

      10. 多年前,我有一个老板,他在一瞬间朝我扔了一把椅子。(这可没听起来那么夸张)。

        如果能再为他工作一次,我一定会心甘情愿。因为他虽然会对我大吼大叫或训斥我,但他也愿意给我好的建议,提升我,教导我。

        办公室不是一个安全的空间。你似乎知道哪里出了问题,我肯定你已经很客气地问过了。我相信你提供了胡萝卜,但你的团队知道你有大棒吗?

        > 同样的人在别人的合并请求上留下了详细的评论

        当众表扬这些人做得好。告诉大家,他们设定了标准,而其他人没有达到。

        > 人们盲目接受建议

        辅导,大量的一对一辅导,让他们找到并发出自己的声音。大量的 “团队建设”,让强势与弱势的声音平分秋色。找出那些沉默寡言的人的长处,并围绕这些长处开展有趣的活动。让他们找到…

        > 人们将他们的 MR 发送到侧频道或其他团队

        坚持。措辞严厉的电子邮件。当众贬低。明确告诉团队 “这是不可接受的行为”。

        至于那个扔椅子的人…他总是很公平,总是把团队放在第一位,在他手下工作,我作为一个人、一个经理和一个工程师都得到了成长。在我拿到工资支票的同时,这不是成长的快乐幸运的好时光,而是成长的痛苦,将这种(痛苦)传播开来是你工作的一部分。

        1. 至于躲避投射物:是的,办公室应该是一个安全的空间,如果有人朝我扔椅子,我们中的一个第二天就不会在那里工作了。(加上 “也许他们扔椅子是为了让你躲避从你身后爬过来的忍者 “的正常说明)。

          1. 这把 “椅子 “上有 3 个衣架和 2 个飞盘……我不知道它是怎么把人举起来的。

            那 “扔 “更像是推了一下,那东西就朝我飞过来了。

            那把椅子唯一会伤害的就是我的感情。

            这可比我坐在装运弹药的办公室里可怕多了。

            1. 我很震惊,很震惊,你居然只是为了表达自己的观点而对自己的经历撒谎。有一次,我和一个谎称曾向人扔椅子的人共事,结果发现他是个被通缉的连环杀手,公司差点破产。当然,这一切都不是真的,但如果是真的,那也是我拒绝与这样的人共事的有力佐证!

            2. 你真有勇气,做了一份可怕的工作,不是为了保护其他人过上艰苦的生活,而是为了能在公告板上对他们挑刺。也许我也该这么做

        2. > 办公室不是安全空间。

          它他妈的应该是一个安全的空间,在那里我不会被我的老板向我投掷大型射弹。

        3. 有些工作文化太不利于冲突了。我认为这当然与个人性格有关,但我想归纳为西海岸人不利于冲突。在这些例子中,你可以在 Linked-In 上找到所有的拉拉队,一切都棒极了,发货速度超快,松鼠

          在这些情况下,我发现冲突被掩盖了,而不是以冷静和理解的方式解决。如果没有后者作为范例,大家就会为了和睦相处而互相攻击,同时也就没有了解决分歧的机制。突然之间,在评审中,你就成了拖延时间的 “那个人”,而评审者和被评审者都没有一个健康的文化来讨论问题。

          很抱歉我说了这么多,我认为降权是对一些团队可以有健康的冲突并通过冲突解决问题的震惊的反应–有时它可能看起来像吼叫(通常吼叫就是吼叫,但当一个团队与另一个团队是真正的朋友时,他们会有自己独特的方式来解决冲突)。

    3. 从未意识到这是一个有争议的话题。是否有聪明人认为不需要代码审查?反对代码审查的最佳理由是什么?

      1. 我曾与一位首席技术官交谈过,他反对代码审查,因为代码审查增加了太多开销,部分原因是代码审查在流程中太迟了。

        他鼓励他的团队事先讨论一种方法,或者一起研究一些东西。

        除此之外,他们还有大量的测试和结构非常严谨的代码库,我想这对他们来说是行之有效的。

      2. 我曾在一个团队工作过,该团队不做评审,因为包括尖峰、研究等在内的所有工作都是由两名工程师结对完成的。这是远程的,整天都有摄像头。

        我觉得这让人筋疲力尽。因为配对过程占用了我大量的认知带宽,所以我的工作能力达到了 100%,但产出却只有 50%。

        1. 我参加过全职配对团队,但发现吞吐量提高了 2-5 倍,因为会议、代码审查和上网的次数减少了。这让我很疲惫,因为突然间我每天要写 7 个多小时的代码,这真的很难。

          我参加过的其他团队在没有配对的情况下,每天最多也就写 3 个小时的代码。其余时间都被其他交流渠道占用了。

      3. 我想我大概做过 1000 到 2000 次代码审查。从那以后,我对代码审查的看法发生了翻天覆地的变化。我可以列出一个长长的清单(抱歉,有点冗长……):

        CR 拖慢了工作进度,而且往往是不必要的。耗时过长

        不必要的解释浪费时间。

        当评审员只有一两个人时,有点不可能。如果审核员人数较多,可能就不需要上下文了。

        造成不发货的偏见。”等待 CR “可能会严重阻碍产品的发布。也许,今晚是你把东西放到 prod 中的好时机,而不是明天–但你正在等待 CR。

        这是流程重于人的一个例子(又名:货物崇拜)。何时/何地/如何/为何进行客户关系管理是很重要的,也是因地制宜的。在不同的情况下,客户关系管理的最佳实践会产生不同的结果。通常情况下,客户关系管理只是因为它是一种最佳做法而盲目进行。最好是深入思考什么是重要的以及为什么–而不仅仅是 “哦,对了,这是另一个我们要通过的障碍,因为 #亚马逊做到了”。

        团队分层。在审核过程中,资深/精英/受宠的人总是比较容易过关。

        CR 可能会变得政治化。Scrum 主理人和经理们争先恐后地为团队成员解围,让他们对某些事情进行审核。这对于那一次来说是件好事,但除此之外就会暴露出一个完全崩溃的流程。当 CR 被 “升级 “时,审查员有多大可能真的会花费必要的时间和来回奔波来 “正确 “地审查事情呢?

        这就容易产生 “小毛病”,而 “小毛病 “是无用的,会适得其反。花在小毛病上的时间是一种浪费,而且会耗费精力,因为要不断地回头去看某件事情,然后再去调整 “它还不够好吗”?

        没有背景的随意审查

        在审查过程中达成一致意见是很困难的。不是每个人都能观察/体验和/或解决冲突。

        CR 在代码开发过程中出现得较晚;这是最糟糕的时候之一,因为在某些东西已经完成、打磨、测试并为生产做好准备之后,突然有人认为应该以不同的方式来完成(当某些东西已经完成并开始工作时,这就更容易看出来了)。这就好比写了三次代码,一次是为了把它写对,第二次是为了把它写好,第三次则是为了满足审查员的任何要求。

        这表明对团队缺乏信任。这是把关。

        不能很好地扩展。曾经有一位审核员告诉我,我写代码的速度比他们读代码的速度还快。(当时,我每天审核大约 6 份公关报告,并发出大约 3 份。我负责 80% 的审核工作,这简直是一场灾难;我收到的审核既慢又无用–团队成员都在努力交付他们捉襟见肘的项目;我太紧张了,既无法提供适当的反馈,又不能每周工作 100 个小时)。

        还有更好的选择,即 “运送/展示/询问 “策略: https://martinfowler.com/articles/ship-show-ask.html

        后一种分支策略由代码作者决定:”这个注释中的错字修复需要审核吗?这段代码中的修正是我最初编写的,我对它了如指掌–真的需要阻塞审查吗?在最后一种情况下,如果一个人可以立即合并一堆前导重构,那么他就可以把这个问题解决掉–这样他送审的 PR 就会变得干净而有趣;而且也不会耽误管理分支或纠缠别人的时间。

        让事情变得更好的第二个方法是允许 “合并后 “审查。在我所在的几个团队中,我们已经做了很多这样的工作,因此我们知道了什么样的东西适合单独发布。在另一种程度上,我们没有足够的带宽来审查所有的东西。这并不是坏事。

        1. 这是一堆缺点,但我想我要问的是,是否有聪明人认为,考虑到这些替代方案,总的来说,还是不做为好?你似乎很反对–你会提出什么具体的替代方案,结果可能是什么?

          1. 就像没有一个最有力的 “赞成论据 “一样,”反对论据 “也是如此–>背景比 “最佳做法 “更重要。

            我注意到

            > 还有更好的选择,即 “运送/展示/询问 “策略: https://martinfowler.com/articles/ship-show-ask.html

            说到底,这就像敏捷和 Scrum。实际上,你必须认真思考你的环境,不能只是去套用一个模板式的一刀切解决方案。(最近我肩上的担子很重,因为我觉得 IT 界有太多的人不愿意认真思考他们的背景。太多了:”我想让我的团队’快马加鞭!'”。他们的口头禅是:只要做好站立、做好复古、做好代码审查、做好计划、添加 checkstyle(一种代码语法筛选器)–一切都会很顺利!我现在学会了问–但项目是否及时完成了?在这种情况下,这些项目中是否有任何一项是真正有用的?如果有用,请告诉我具体原因并提供详细信息。我还了解到,如果一个团队远在石器时代,试图采用所有最佳实践的时间很可能比该团队和/或公司的剩余寿命还要长。这就意味着,他们除了在流程变更上喋喋不休之外,不会再做任何有用的事情。这又让我想起了公司责任,有多少公司责任是真正有用的呢?有些 CR 肯定是有用的。不过,一个团队怎么可能花更多的时间去做有用的公关,而花更少的时间去做无用的公关呢?更重要的是,每个 CR 都是一项阻塞性活动,如果我们为了一项通常无用的活动而阻塞开发,那就有问题了。替代方案不一定是完全放弃 CR,我已经提到了两个:”ship/show/ask “和合并后审查(review)。

    4. > “亲切,而非友善

      在加入一个团队时,我对开发人员说的第一句话总是:”我不在乎你有多挑剔,只要诚实就好。”我认为尽早设定期望非常关键。我认为,让开发人员不觉得自己的代码受到攻击或过于自卫是一个很好的进步。在我看来,强烈捍卫自己代码的人是糟糕的开发者。

      1. 我有一个同事,他花了更多的时间为自己的代码辩护,给出一系列错误的原因,而不是真正地修复它们。这种情况已经不止一次了。

        我只是继续工作。总有一天他会意识到他的代码有多糟糕。

      2. 听起来很激进坦率,我喜欢

    5. 这些警告该如何措辞?”下次……”?我很难认真对待自己的警告,如果现在已经足够好的话。

      1. 我们会在评论前加上 “minor:”,所有员工都知道,这意味着这是一件很好但没有必要合并的事情

      2. 使用删除键。(对不起,我说的是玩笑话,但我是认真的,根本不要发送这类评论意见)。

        如果暂时没问题,那就没问题。如果不好,那就说出来。

        如果你确实有这样的顾虑,”暂时没问题”–那是线下谈话的内容,不属于 CR 的范畴。这也是检验一条意见有多重要的试金石。你会安排 15 分钟的会议与同事讨论这个问题吗?如果不会,那为什么可以在公约与建议委员会会议期间这样做呢?

      3. “这暂时没问题,但我们应该考虑一下如何序列化这些对象。请随时在后续版本中删除 N^2 算法。”

        1. 这在你们都是同一家公司的员工,而且彼此尊重的情况下非常有效,但在开源世界中往往行不通,人们就这样消失了,你再也不会听到他们的消息。他们有可能会进行后续跟踪,但根据我的经验,这种情况很少见。

          1. 是的,即使是在公司内部,我接受修改的门槛也会因我的经验和与作者的关系而有很大不同。对于外部贡献者或从未与我合作过的人(通过审核代码或让人审核我的代码),我不会接受代码,直到几乎所有的工作都让我满意为止。而对于经常与我合作的人,我在接受一项修改时往往会加上这样的评论:”这一切都很好,但您需要考虑到 X,这将改变这个补丁中的几乎所有内容”(我说得有点夸张,但只是稍微夸张)。我知道一个更新是否会有问题,是否有必要再看一遍。有时,有几种显而易见的方法可以完成某件事情,他们会选择其中一种,但如果我有理由选择另一种,我就会选择另一种,因为我有理由。

            大多数情况介于两者之间。

            虽然在某些方面,这恰恰相反。对于一个陌生的开源贡献者,我需要确信他的改动是值得的。我会在文体方面放宽要求,我会直接使用他们的补丁,之后再进行修复。如果是我合作过很多次的人(不管是熟悉的贡献者还是同事),我会相信他们对改动的基本质量的意见,但对不必要的风格差异则不那么宽容,因为他们应该已经在这些方面达成了一致,如果他们漏掉了什么,更有可能是疏忽。(另外,鉴于超过 90% 的补丁将来自普通贡献者,我不想在事后修正他们的修改)。

          2. 另外,”时不我待 “是真的。跟进很少发生,跟踪起来很麻烦。让某个人为此负责是不公平的,尤其是如果他们不同意后续行动的话(想必他们是不同意的,否则他们一开始就会做这件事)。

    6. >围绕你发现的问题与提交者会面的时间。

      什么!如果有人安排与我会面讨论公关问题,我会气疯的。我们已经有太多会议要开了,这是唯一可以幸免于难的流程之一。

      1. 我也是,我真的很不喜欢这样的会议,本来可以在 slack 或公关中问我三四个问题,然后等我十五分钟左右再回答。

      2. 会议不需要太正式,也不需要太长。我个人很喜欢公关会议,在会上我们可以探讨代码并理解它,而不是有人在午餐时间把 2000 行代码倒在我的腿上,然后希望在晚饭前把他们的意大利面搅拌均匀

      3. 生气?开会讨论工作?有些人在懒人空间等地方发表的评论听起来比原意更糟糕,而人们也意识到了这一点,所以有时会不遗余力地以原意的方式表达出来。

      4. 说白了,如果提交者想讨论问题,我就会安排时间见面。我并不要求每份公文都要见面。我会根据需要与提交者会面,但频率很低,因为提交者需要尽快熟悉情况。

      5. “当面 “审核是我认为最好的审核方式。如果一份 CR 会有十几条关于所有事情的评论,那么异步审查就是一场灾难–作者会觉得自己受到了攻击。解决冲突和分歧的对话可能不会有好结果。

        就我个人而言,如果团队不习惯当面解决冲突,我喜欢从当面解决冲突开始。只有在建立了健康的关系和冲突解决机制之后,才会进行异步公关。我还喜欢这样一条规则,即在一次 CR 中,通信往返不应超过 2 次,否则应同时进行。

        在很多环境下,推迟小的改动以允许这样的往返时间是不可行的。要做的事情太多了。不值得。当项目失败时,很少会有经理给项目贴上一个大大的 “失败 “标签。我提出这个问题是想说,项目失败总是因为团队进展太慢,而个人往往不知道他们实际上需要更快的进展(反馈回路往往缺失,”哦,我们实际上太慢了,我们需要比实际更快的发货速度。JIRA、计划、估算、CR、最佳实践、修复衬垫所花费的时间–这一切都不重要,因为这个项目实际上失败了–它花的时间太长了。)

  2. 我认为这真的很重要,因为它比 “代码审查 “更重要。它确实说明了人们对统计数据[0]的误解有多深。但人们之所以 “相信”,是因为他们讨厌代码审查,而不是因为他们 “真的 “相信审查结果。

    但统计数据是很棘手的。以文章中举的例子 “15% 的吸烟者会得肺癌 “与 “80% 的肺癌患者吸烟 “相比。这两者并不矛盾,只是看待同一事物的不同方式而已。事实上,人们往往就是这样用统计数据误导你(或者说你可能无意中误导了自己!)。

    另一个有名的例子是时不时出现在 HN 上的:”尽管只有 5.8% 的销售额,但超过 38% 的错误报告来自 Linux 社区”[1]。简而言之,这个例子讲述的是 Linux 用户在提交错误报告方面受过更多训练,而且大多数错误并不针对特定系统。因此,如果只根据提交者的架构来对错误进行分类,实际上会错过很多有价值的信息。由于统计学的工作原理,如果架构依赖率甚至低至 50%(我会很惊讶的!),那么仍然会有大量有用的错误报告。作为一名 Linux 用户,我见过这类 bug,它们并不少见。但我经常看到,因为我是从 linux 系统报告的,所以它们就被驳回了。更有甚者,支持人员会将你发送到他们的页面,要求你为某个 “功能 “或错误问题 “点赞”。你必须先登录。我无法认真对待这样的公司,但该死的是,Spotify 也这样对我,我还把出错的那行代码发给了他们。Netflix 也这样对我说,”我们不屏蔽 Firefox”,但切换用户代理后我就能访问了。有时候,我们的思考不能只停留在表面。

    所以,我想说的是,这里有一个可以抽象出来的普遍教训。

    [0] 大家都开玩笑说统计数字是编出来的,但这同样不好。

    [1] https://news.ycombinator.com/item?id=38392931

    1. > 支持 “会将您发送到他们的页面,要求您为 “功能 “或错误问题 “向上投票”。

      微软为企业产品提供这种服务,客户可能每月支付 10 万美元甚至数百万美元。

      “我们听到了,但你的抱怨还不够流行,所以请走开。”

      “当然,这是一个灾难性的数据丢失漏洞,吃掉了你的财务交易,但如果其他人无法识别他们看似无关的崩溃是完全相同的问题,那么你就没有修复的机会。”

      “既然你在一个名为’Consiser尽职尽责’的问题上获得了一万张选票,我们决定通过删除错误论坛来改善你的体验,并从头开始建立一个新的论坛,减少不爽用户的尖刻评论。”

      1. 我所在的公司/团队对错误和功能请求的处理流程截然不同。如果客户开了一张单子,而我们确定它是一个错误,我们一般会在报告的版本中或之后修复它(除非它是一个安全漏洞或其他重大问题)。但对于功能请求,我们只是告诉他们将其提交给社区,然后我们会评估它是否有效,考虑到我们的其他工作,我们可能会实施它,但不一定会很快实施。

        1. 有时,功能请求实际上是一个错误,可以说明我们没有正确理解设计。

          但我认为,如何理解用户的功能请求非常重要。他们有一种挫败感,你可能没有意识到,但他们并不知道所有的代码和限制。这甚至可能是设计方面的问题,但这仍然很重要。很多时候,有一种方法可以解决用户明确要求之外的功能请求。但要做到这一点,你必须仔细阅读字里行间的内容。当然,有些人在这方面完全走错了路,他们认为苹果公司知道什么对用户最好。这完全是一种难以取得的平衡,但我认为,将其简单化是很常见的。

          有人开玩笑说,用户是傻瓜,也许他们是傻瓜,但这并不意味着他们面临的问题是傻瓜。当一个人拉一扇写着 “推 “的门时,他并不总是哑巴,因为实际上可能是标志和设计表达了不同的意思[0]。就我个人而言,我喜欢用户提出解决问题的方法。我可能会把它扔进垃圾桶,但它往往能给我提供更好的上下文线索,让我知道他们想问什么,而且如果他们认真思考了这个问题,也确实告诉了我他们对产品的关心。他们只是没有我这样的视角,没关系。

          [0] https://www.youtube.com/watch?v=yY96hTb8WgI

          1. > 有时功能请求实际上是错误

            两个缺失的功能加起来可能就是一个错误。例如,我曾使用过同一供应商的两款云产品,其中 CDN 产品缺少的后端 HTTP 功能与 PaaS 服务缺少的 HTTP 前端功能相互影响,导致这两款 “天然契合 “的产品实际上无法结合使用。

            这使得许多本应可行的架构无法实现,迫使客户采用扭曲的设计模式或第三方产品。

            在我看来,这是一个错误(”无法使用你们的产品”),但每个团队都将其单独标记为缺失功能,然后他们在大约三年的时间里都忽略了这一点。

            另外:没有足够多的人投票支持缺失功能,因为没有足够多的人使用产品……因为他们不能。

            我知道这有点离题,但这又回到了博客原文中 “统计很难 “的引言。依靠你并不完全了解的统计数据,你可能会犯下灾难性的商业错误,比如这个 “你不会因为产品无法使用而收到很多投诉 “的例子。

            然而,对于可用的产品,你会收到很多投诉……他们有用户投诉。

            https://en.wikipedia.org/wiki/Survivorship_bias

            1. > 因为没有足够的人使用这些产品……因为他们做不到。

              我认为这完全没有跑题。我认为这是明确的主题,至少是基本主题。不只是统计很难,测量事物也很难,确定因果关系更是难上加难。这通常是统计学和数据科学的根本目标。找出事情发生的原因。测量非常困难,而人们往往认为测量很简单。问题是,无论你测量的是什么,实际上都是一种替代,都具有不确定性。如果你不能很好地理解衡量标准的含义,你往往就不知道这些不确定性。付出艰辛的努力总会有回报,但不幸的是,如果不付出艰辛的努力,就可能要花费一些时间才能使接缝开始裂开。我认为这种不对称往往是人们马虎的原因。

              1. 我喜欢用的例子是 COVID 统计数据引起的混乱,以及人们是如何误解这些数据的。

                例如,新闻中经常报道的每日感染(或死亡)率实际上是:感染率 * 测量精度 * 测量率。

                如果有更多的人接受检测,”比率 “就会上升。

                如果 PCR 检测得到改善,”比率 “就会上升。

                类似的情况也适用于住院和死亡人数。上升的原因可能是某种菌株比另一种菌株更致命,也可能是更多的人感染了同一种菌株,还可能是更多的死亡归因于 COVID 而不是其他原因。

                不同的国家有不同的报告标准,或者报告标准随着时间的推移因环境而改变,这都无济于事!

                等等……

                这很复杂!

      2. 你是说他们不再审查错误报告,不再试图让你相信他们的软件是无懈可击的?

        与我与他们打交道的时候相比,这已经是巨大的进步了。

        1. > 不要审查错误报告

          他们确实会这样做,但即使是礼貌但脾气暴躁的评论最终也会累积到看起来很糟糕的地步。这些评论是公开的–这就是关键所在–因此隐藏它们的唯一办法就是删除它们。通常这种做法会让用户更加不满,所以 “窍门 “就是把整个论坛扔在地上,换一个新软件重新开始,以此来 “改善 “服务。这并不是因为它在任何方面都更好,而是因为它隐含着从 “BUGS “中删除*的意思。

          微软现在已经是……第三个论坛了?我都数不清了。

    2. 基本上,代码审查也会发现很多其他非错误的东西(可能是小毛病和风格问题)。

      这就是为什么看百分比是危险的。您可能在每次代码评审中发现 5 个错误,这已经很多了,但如果您还提出了 30 条其他非错误意见,那么突然间 “只有 15% 的意见是错误”。

      1. 我完全同意。有很多事情是无法轻易衡量的,也有很多事情是永远无法衡量的。但这并不意味着它们不重要。按照你的观点,执行良好的风格可以避免以后出现错误,甚至可以节省很多时间,因为你的代码不会慢慢变成意大利面条。我认为这是人们经常忽略的一点。细化通常是通过一个较慢的过程发生的。是通过数十次提交,而不是少数几次提交。

  3. 代码审查的价值实际上取决于代码和处理代码的人。对于在同一个 repo 上工作多年的团队来说,代码审查可能没有太大价值。但如果团队中新来了一个人,或者是一个初级开发人员,你肯定会想要审查他们的代码。

    代码审查的作用不仅仅是发现错误。你可以指出更好的方法。也许这个 SQL 可以更有效率。也许你可以重构一些代码,使其更健壮。也许你应该在这里添加一条日志语句。这个方法的名称很混乱,我建议将其更名为 xyz?

    1. > 但如果你的团队里有新人,或者是后辈,你一定要审查他们的代码。

      来自后辈或新团队成员的审查也非常有价值,因为他们没有其他人可能拥有的历史或部落知识。他们经常会发现一些因为 “就是这样 “而被忽视的问题。

    2. > 对于在同一个 repo 上工作多年的团队来说,代码审查可能没有太大价值。

      我确实在资深开发人员编写的代码中发现过 bug [代码审查期间的 ETA],这些代码他们已经熟悉了十多年。

    3. 我真的很好奇,我想就您在审核和接受审核方面的经验问您一些后续问题。您介意发邮件到 hn@xkqr.org 吗?

    4. 代码审查还能让团队了解代码中的最新变化

      1. 常见的说法,但我认为这种说法是错误的。PR 的作用是向团队发送邮件,PR 留下的是网页和变更内容的摘要。在那里工作的是 PR,而不是 CR。这意味着,您可以打开并立即合并没有 CR 的 PR,以获得同样的好处。

        CR 的确给了其他人研究代码、熟悉代码的机会,但这与 “保持更新 “是两码事。

  4. 我不知道作者为什么忽略了”……应该阻止提交 “这一部分。

    论文摘要

    > 由于代码审查有很多用途和好处,因此它是现代软件工程工作流程的标准组成部分。由于需要人员参与,代码审查往往是代码集成活动中耗时最长的部分。利用在微软公司获得的经验和数据支持,我们认为:(1) 代码审查通常不会发现本应阻止代码提交的功能问题;(2) 有效的代码审查应由具备特定技能的人员执行;(3) 代码审查的社会方面不容忽视。我们发现,我们需要对代码审查工作流程的指导原则更加精益求精。我们将展示我们在代码审查实践中的发现是如何影响微软的代码审查工具的。最后,我们断言,代码审查实践因其成本高昂,是一个值得更好地理解、系统化并更精确地应用到软件工程工作流程中的主题,而不是目前规定的最佳实践。

    “代码审查找不到错误:当前的代码审查最佳实践如何拖慢我们的脚步

    https://www.microsoft.com/en-us/research/wp-content/uploads/

    1. 应该阻止提交 “总是最棘手的部分之一。有句话说”开车比你慢的人都是白痴,开车比你快的人都是疯子”。但的确,开得越快危险越大,有一种速度可以适当平衡利益与风险;但每个人的看法不同。

      代码气味 “问题也是如此:每个要求你改动的人都是迂腐的人,他们会为了毫无意义的美观而拖慢项目的进度;而每个反对你要求的改动的人都是牛仔,他们会让代码将来更难维护。

      那么在论文中,他们是如何决定一个非错误的修改是否 “应该阻止提交 “的呢?

      1. 如果评论指出了错误/缺陷[1],那么就应该阻止。

        仔细想想,随着错误/缺陷的删除,代码会变得更加正确,从而更加稳定,因为它不需要额外的修改来删除错误,所以删除错误可以减少未来维护的需要。

        如果我们因为对未来维护的担忧而阻塞,那么我们实际上是在断言需求是不稳定的,而且从总体上来说,删除现在的错误是没有价值的,因为需求变更会删除有错误的代码行,并用有新错误的新代码行取而代之。

        我想这取决于特定组织的代码审查流程,是否适合在这一点上阻止代码出现架构/设计问题。根据我的经验,代码审查步骤在开发流程中处于下游位置,而且只关注代码的一个子集,因此无法有效地处理对维护有重大影响的设计变更。

        [1] 论文作者审查了微软内部代码审查工具中的数据,该工具是专有的,因此我们无法看到具体的错误是什么。

  5. 代码审查不仅能发现漏洞,还能从根本上防止漏洞的出现。

    当开发人员知道会有其他人审查他们所编写和提交的代码时,他们会更加谨慎。

    不久前,我们在一个多年期项目中对代码审查政策进行了几次迭代。随着时间的推移,我们从未真正看到代码审查捕获了大量的错误,但每当我们减少代码审查时,我们就会发现生产错误率肯定会上升。

  6. 我对代码审查的不满在于,它们往往会导致大量时间的浪费,有时简单的拉取请求一周内就会花费数千美元。

    我工作了 6 年,时间不多,也不像其他人那样在很多地方工作,但我已经形成了这样的观点:代码评审就像测试一样,应该在必要时作为一种工具使用,而不应该在每次变更时都默认使用。

    在最好的情况下,创建拉取请求的人员会要求审核或决定需要测试的地方。

    我的观点显然适用于产品软件,但对于库而言,尤其是在公开发布的情况下,您需要尽可能多的讨论和测试。

    1. 对我来说,把小的、连贯的、解释过的、测试过的、可审查的变更单元作为自己的工作成果展示给他人,这对我来说有 80% 的价值。至于其他人是否真的深入思考过,或者有什么有用的意见,那都是次要的。

    2. 阻塞代码审查当然也是如此。我有兴趣探索另一种方法,即提交后审查。这里有一篇介绍这种方法的文章:https://copyconstruct.medium.com/post-commit-reviews-b4cc216…

      代码仍然会被审核,但你不会因为等待某个人的审核而导致 PR 被搁置数小时、数天甚至数周。

      1. 我以 “是 “和 “否 “的心态审核了很多代码。

        基本上,当我开始编写 PR 时,我就会在脑海中批准该 PR,直到我发现一些阻碍。例如,导致数据丢失的大问题、性能问题或破坏其他代码的问题。其他的最多只是一个小评论。默认情况下,PR 会被批准。这就赋予了开发人员责任和所有权。此外,它还能加快发布速度

        进行后续公关以改进或解决某些问题与阻止 MR 一样快,但阻止 MR 会影响士气。

        根据我的经验,这种方法能培养责任感和主人翁精神,消除代码审查中对他人工作的监管。

        此外,关于格式、何时测试、设计、特性、功能、架构的决策和讨论不应在代码审查期间进行,而应在编码之前或在工作期间进行。代码审查是最不适合讨论这些问题的时候,在我看来,它应该是对实现进行理智检查的时候。

      2. 我曾经在一个小团队里做过很多这样的事情,我们不阻止审查(我们做审查,但不阻止)。我是团队中的资深开发人员,我会花时间通读收到的新代码。这样做效果很好。

        有趣的是,这部分代码/项目没有超级严格的代码审查要求,但有大量测试,是我认为最健壮/高质量的代码。在一个相当重要的应用程序中,它的运行用户超过 1000 万。它并不庞大,而且有很好的测试(一般来说是相当可测试的)。

        尽管如此,要控制提交后的审核确实很难。也许我们需要更好的工具。就我而言,就我参与的代码领域而言,它很小,足以在我的头脑中进行跟踪。

      3. 我很想探索这种替代方法,但我不确定如何确保在推送和部署提交后发现的任何错误/建议的更改都能真正得到执行。

      4. 我很喜欢这个想法!我并不需要检查每个开发人员是如何处理他们的工作的(虽然在某些情况下,这可能会成为一个有用的指导环节),但重要的是在投入生产之前,工作看起来是什么样的。

        我认为上述方法的主要困难在于,不同的变更会交错在主干中,可能很难只提取其中一个进行部署。但这就是功能标志的作用!

    3. 这个故事可能还不止这些。创建 MR 是一门技术,也可能是一门艺术,这样才能方便审核和批准。

      对 MR 的反馈也是如此。提供简洁明了的反馈意见能更快地解决问题。

      就像 “如果变更很难,那就重构,让变更变得简单”。做一件事有很多种方法,有的更好,有的不好。

      拥有良好审查文化的公司和团队都能成功地将审查作为一种工具。

    4. 这与我在代码审查方面的经验相去甚远,所以我想问一些问题来跟进您的经验。您是否介意发送电子邮件至 hn@xkqr.org

  7. 与大多数流程一样,代码审查的难题在于弄清它对团队和组织的影响。

    在一个庞大的组织中,成千上万的工程师每天都要承受数小时的中断和流程开销,而发布跑道上的官僚机构已经盖了六枚印章,在这种情况下,强制代码审查几乎没有什么坏处(它是在噪音中进行的),但回报却很不稳定(许多人只是在流程的重压下闷头工作)。组织不会因为强制要求而损失什么,但只有某些团队才会看到它的巨大价值。

    另一个极端是,一家拥有五名工程师的初创公司会积压大量的审查工作(审查工作会被缩短),因为每个人都面临着压力,要么要保持高生产率,要么要救火。评审也许可以抓住问题,定期分享关键知识,但组织却要为开销和中断付出明显的代价。

    人们渴望 “放之四海而皆准 “的规则,并为此撰写论文和发表研究报告,但现实中的正确做法往往更加特立独行。

    1. 我并不反对 “视情况而定 “的观点,但对我来说,在 “有五名工程师的初创公司 “中,代码审查通常效果更好,开销更低。我能就您在审查和接受审查方面的经验问您一些后续问题吗?如果可以,请给我发电子邮件:hn@xkqr.org!

  8. 根据我的经验,代码评审可以捕捉到很多错误。但是,如果您发现自己在审查中一次又一次地捕捉到同类错误,那么您就应该想办法自动捕捉这些错误,而不需要审查员参与(静态分析、测试、衬垫等)。

    1. 完全同意尽可能利用静态分析。当在代码评审中发现问题时,我的第一反应就是想:”我们是否可以通过某种 <lint 规则> 来捕捉到这个问题?

  9. 我认为这篇文章的观点是错误的。文章引用的统计数字是,15% 的评论是关于 bug 的,这似乎符合人们的预期,我认为只有当这个数字_高得多_或_低得多_时,才真正值得讨论。

    相反,我认为有两个更有趣的问题值得一问:

    1.代码审查发现缺陷的比率是否足以将代码审查用作缺陷的检测机制?

    经过近 20 年的软件编写工作,我确信答案是否定的。有些审查员比其他审查员更优秀,有些情况比其他情况更有利于发现缺陷,但一般来说,我们应该尝试构建这样的流程,即不假定缺陷会通过代码审查以相当高的比率被发现。当它起作用的时候是很好,但它并不是一种足够可靠的捕获错误的方法,不能成为流程中的负载部分。

    2.强制审查所有代码是否合理?

    这是我犹豫不决的问题。我认为,在一个代码评审优先级很高的环境中,人们接受过有效评审的培训,而且组织政治因素极少,那么允许公关作者决定是否进行评审通常会提高代码的质量和速度,因为代码会更快地发布,而且可以从评审中获益的代码仍然会被评审。在这种情况下,我认为我们会看到,当代码不需要审核时,代码的交付速度会更快,审核的质量也会更高,因为代码被标记为需要审核是一个积极的信号,会让我们更加关注。

    不幸的是,我可能是错的,而且这也不是任何人都愿意冒着声誉受损的风险去推动的实验,所以我怀疑我们不太可能看到规模足够大的实验来确定。如果我们会以某种方式失败,我宁愿失败的原因是代码审查太多,而不是不够。

  10. 错误很’容易’修复,我不担心找不到它们。我担心的是界面,因为所有的用户很快就会成为修改界面的噩梦。

    1. 我很想了解您在代码审查方面的更多经验。能否请您发送电子邮件至 hn@xkqr.org,以便我提出一些后续问题?

  11. 如果有了拼写检查器、代码格式化器和线程器,代码审查就会大大改善。这比手工操作或手工审查要好得多,代码审查可以用于更高层次的想法。

    1. 没错。代码评审不应该涉及代码格式或任何可以通过精简器、格式化器、代码覆盖率限制和静态分析自动完成的工作。如果构建的 PR 是绿色的,那么所有这些都是可以接受的。

  12. 请记住,我支持代码审查,但…

    在药物研究中有一个小把戏,就是用安慰剂来测试潜在的候选药物,从而得出一个似乎显示出益处的糟糕研究结果。之所以说这是个把戏,是因为在很多情况下,替代品不是安慰剂,而是现有的治疗方法。然后,医生会了解到一种更 “现代 “的治疗方法,因为它更现代而对它青睐有加,更好的治疗方法可能就不会被开出处方。

    代码审查的替代品并非无所作为。文章称,代码审查每 10 分钟就能发现一个缺陷–但仅限于前十分钟。根据同样的论点(忽略限定条件,推断数字结果),快速自动测试有可能在一秒钟内发现数千个缺陷–如果它们运行得那么快,而且缺陷已经被测试过的话。静态分析器、结对编程、文档编制这些都是可供选择的方法,还有很多其他方法。

    如果你每天花一个小时来审查代码,那么你就花了 12.5% 的时间来做这件事。这样做会带来机会成本,而根据您特定的组织和代码库,这种机会成本可能会用得更好。当然,把所有事情都分析得一清二楚也有机会成本,但不分析通常会导致目标转移,即做某件事的所谓理由不断变化。今天是为了发现缺陷,明天是为了知识共享,后天是为了安全。它就是所有这些事情,但其他做法可能会更有效地利用时间和人们的耐心来实现这些目标。

    那么,我为什么支持代码审查呢?因为选择作为一个团队进行互动和合作,了解你的同事并与他们达成妥协,这既是良好的团队建设,又能达到其他技术目的。我确实认为结对编程可以在更大程度上实现这一点,同时也会给个人带来更多负担。但前提是你必须控制并拥有这一过程,如果这只是一种生搬硬套的仪式,那么我的感觉是你可能并没有从中获得净收益:你只是因为别无选择才这样做,而不是因为你认为这是对时间的宝贵利用。如果你同时经历过两种文化,一种是人们选择代码审查并从中发现价值的文化,另一种是人们被迫不容置疑地进行代码审查的文化,那么你可能已经见证了一句箴言是如何毁掉一种做法的社会价值的。

  13. > 开发人员每周要花六个小时进行审核。这有点太多了

    调整审核时间非常困难。各种选项都缺乏吸引力。是在达到上限后开始盲目接受修改,还是干脆停止,不让别人合并代码?

    1. 为什么要阻止合并代码?一个人花了几个小时修改代码,却被另一个不分配时间审核的人阻止,这种想法让我很不理解。我们都是专业人士,让别人合并他们的修改,并确保你有时间审查它们。如果你无法审核,而他们仍然需要你的批准,那就批准吧。

      除非你不信任你的同事。如果是这样的话,那么代码审查无论如何都是注定要失败的。

  14. > 在一天中前 60 分钟的代码审查中,审查员大约每十分钟就能发现一个缺陷–只要他们每十分钟审查的代码少于 50 行。

    哦。

    我通常只需要几秒钟就能发现代码中的缺陷。

    我一直觉得这是评估软件的平均水平。如果每个缺陷的平均时间是十分钟,我就需要重新调整对自己的期望值了。

    1. 这确实取决于代码。要找到 CSS bug,是很容易。如果要找到支付集成中的逻辑漏洞,即有人遗漏了或应该实现但没有实现(例如 webhooks),那么这就需要更多时间,开发人员基本上必须坐下来好好研究一下到底应该实现什么/他们会如何开发,然后对照已经完成的工作进行交叉检查,否则你就无法轻易找到这些逻辑漏洞,而这些漏洞实际上就是 bug,只是不像缺少分号这样简单的代码 bug。

      1. 我的日常工作是审计密码学。我可能比大多数阅读 HN 的人更慢找到 CSS bug 的根源。

    2. 你应该明白,找到代码中的 bug 需要多长时间取决于代码。如果不明白,那么我希望你读过 Linux 和 SSL 等的代码。

      1. 是的,当然这在很大程度上取决于上下文。

        我从来没有阅读 Linux 内核代码的动力。我经常发现并披露密码学库的 bug,不过通常都是业余项目,比如 “我觉得如果有一个 GHASH 的 PHP 实现就好了 “之类的,而不是 OpenSSL。

  15. 当我是审核者时,我几乎会发现每一个非小规模的拉取请求都有问题。有时这些都是小问题,但我经常发现 bug 和边缘情况。

    我看到一些关于时间的评论。代码审查需要多长时间?我可以在几分钟内审核数百行代码。在我看来,审查代码比编写代码要容易得多,尤其是当您积累了丰富的经验之后。对于较大的工作,在整个过程中都要有人盯着。

    我遇到过很多开发人员,他们在写完代码后就认为代码可以正常工作。他们不会通过代码或人工 QA 进行测试。当利益相关者告诉他们代码不工作时,他们会表现得很惊讶。第一次就把工作做好。慢就是顺,顺就是快。

    1. 我总是惊讶地发现,我经常会收到这样的拉取请求:要么无法构建,要么单元测试失败,要么两者兼而有之。这些问题至少很容易解决,但当我认为某些代码可能难以维护、反模式或可能以不明显的方式出现错误时,我就会发现很难有效地解决这些问题,并经常最终怀疑自己的建议。

    2. 当我使用 Django 时,添加代码的人在自己的系统中运行代码。而对于 lambda(我们大多在云中部署和测试),人们往往会扔下代码就走。

  16. 这篇论文的标题有点挑衅,但我认为研究结果很有趣。主要是围绕开发人员长期以来认为的价值与实际情况的对比。

    不过,你提出的关于使用缺陷变化率的观点很有道理。我希望研究人员把它作为首选的测量单位。我对流行的开源项目的变更缺陷率做了一些研究,结果发现差异很大。从 ~12% 到 ~40% [1]。

    我希望看到的未来是,作为开发人员,我们使用客观的衡量标准来证明审查时间投资的合理性。随着代理开始不断提交小的错误修复单,这一点将变得越来越重要。

    [1] https://www.shepherdly.io/post/benchmarking-risk-quality-kpi

  17. 我还记得在合并 PR 之前需要获得批准的时代(我还记得在 PR 或任何广泛使用的版本控制系统之前的时代)。

    我一只手就能数出有多少次有人在我的代码中发现了本应停止部署的错误。我并不是没有部署过严重的错误,但这些错误几乎从未被审查我代码的人发现过。

    偶尔也会有人提出更好的方法,或者提出一个问题,最终让我想出更好的方法。但这种情况也很少见。而且我也想不出有多少次是值得在这个过程中花时间去做的。

    结对编程和协作可以带来巨大的益处,但我们所形成的 “最小努力、公关批准 “的文化却不能很好地替代这一点。

    1. 代码审查和结对编程如果有特定的目的,都会非常有用。

      让别人尽快熟悉不熟悉的代码,理清毛糙的代码,使其变得更加清晰,查找错误或发现未知的未知因素,如错误或不必要的复杂性。

      不过,在很多情况下,做这些事情时不看屏幕会更有帮助。在头脑中建立一个心智模型,然后互相启发往往更有帮助。与实际编码或阅读实际代码相比,在黑板上画出东西或在标记文件中写下东西,用简单的术语解释事情,会更有帮助。

      我不确定这算不算结对编程或代码审查,但这种自由讨论代码的方式非常有效。

    2. 我在审查中发现了错误,但更好的是,我要求进行测试,而这些测试也发现了错误。

      即使是低强度的代码审查也能发现缺失的 unittests

    3. 听起来你写的代码质量很高!从您的简介来看,我倾向于认为您知道自己在说什么。我想了解一下你在这里的工作经历。您是否介意发送电子邮件到 hn@xkqr.org,以便我提出一些后续问题?

  18. 代码审查有不同的层次。根据我的经验,基于网络的代码审查工具非常糟糕。任何跨越多个文件的几行以上的代码都需要 cscope 类型的工具。

    还有,审查的类型是什么?这是一个需要高水平设计审查的原型吗,这样实际审查就不会变成设计审查?这种审查多长时间进行一次?

    评审者是谁,流程是什么?关键利益相关者的影响力更大,你需要考虑评审者的经验、知识和可信度。

    最后,代码有多重要?是内核代码,还是需要竞赛条件和内存泄漏检查的高执行守护程序代码?您是否对代码进行了静态分析?代码是否能编译并实现其设计目标?单元测试日志在哪里?

    需要考虑的问题很多。

  19. 技术债务。尽量减少技术债务,在需要时,为其写一个任务,以便日后进行研究。

    编码标准。不要提交有多余行数的代码,这些代码会拖慢下一个开发人员的工作,使他们无法了解过去的代码是做什么的。

    最重要的是,确保覆盖边缘情况,通常是通过所有可能结果的真值表。

    我经常会在 PR 上评论说:”等等等等,但不阻塞”,所以我允许这样做,但至少我的意见是众所周知的,以防日后出现代码问题。

    我的公关需要很长的时间,因为我挖空心思。

  20. 我喜欢在发布 PR 的同时看到正在运行的软件。GitLab 有一个 “审查环境”(Review Environment)的概念,把我宠坏了。从特性分支部署的短暂、动态调配的环境,对工作效率的提升绝对是惊人的。

    它为公关提供了更多的背景信息。

  21. 我发现很多标准流程都可以用类似的方式来描述–如果你注意到它们能解决什么问题,它们应该会非常有用。诀窍在于一些重要但微妙的细节,比如不要连续花两个小时审核一份过长的公关。一旦这只是流程的一部分,就很容易忘记。

  22. 我不认为代码审查有什么好处。我从事网络开发已有 12 年,在大大小小的公司工作过。

    我认为应该有一个人工的质量保证流程来测试开发人员推送的功能。

    代码审查的问题在于,它总是要花费另一位开发人员大量的时间,而且许多开发人员都超级忙,所以他们只是快速审查一下 PR,然后就批准了,或者觉得自己必须添加一些注释。在开发人员已经在做的工作和必须到 PR 前进行适当审查之间切换上下文,意味着他们应该切换到该 Git 分支,下拉代码,测试所有代码,并检查静态代码审查不会发现的逻辑错误。

    对于初级开发人员来说,代码审查仍然有用,因为您可以发现质量不佳的代码,但对于高级开发人员来说,由于上述原因,代码审查就没有那么有用了,最好是有一个质量保证流程来发现逻辑漏洞,而不是期望开发人员投入那么多时间在上下文切换上。

    1. 这里的问题不是开发人员太忙,而是代码审查被认为是二等公民,而不是编写新代码。这就好比说 “许多开发人员都在忙着开发功能 A,所以他们只是为功能 B 编写了快速而肮脏的代码”。如果审查是功能生产流水线不可或缺的一部分,那么坐下来花一天时间审查代码应该不成问题。对于更大、更复杂的事情,可以进行几轮审查。

      编写第一份 PR 所需的时间与通过所有审核所需的时间之间存在近似的非线性关系。这段时间可以很可靠地计算出来并考虑在内。

    2. 不,自动化测试涵盖了基本功能。对于大多数 PR 而言,熟悉代码的高级人员不需要检查代码并手动测试任何东西,因为大多数时候 “代码审查 “并不是这样的。如果需要他们查看运行状态下的代码,那应该是 CI 流程的一部分,而不是开发人员的手动任务。

      一个好的审查员可以指出错误的编码战略决策或对需求的曲解。质量保证完全是另一层审查。

    3. 听到这个消息我有点吃惊。您能否给 hn@xkqr.org 发一封邮件,以便我提出一些后续问题?

  23. 我唯一不喜欢代码审查的地方就是吹毛求疵的评论。每个人都有自己编写代码的主观方式,如果我的代码足够好用和美观,那就随它去吧。

  24. 代码审查可以发现错误。

    更常见的情况是,代码审查成了团队成员争吵的机会。更糟糕的是,代码审查成为非团队成员对项目行使权力的机会。

    1. 在团队中骑车是件好事。如果你们都要给车棚刷漆,就颜色达成一致会有帮助。

      更广泛地说,代码审查是逐步获得或鼓励整个团队保持一致的绝佳机会。

      至于团队选择在哪些方面保持一致以及保持一致的力度有多大,这都由团队自己决定,所以希望他们不要在无关紧要的细节上纠缠不休,但在我看来,完全放弃这个加强各种凝聚力的非常廉价的机会将是一个很大的错误。

      1. 你对代码审查做了很多正面-反面的断言。我的观点是,消极行为的机会太多了。这与技术和生活中的一切都一样,”只要每个人都尽自己的一份力,就能保持良好的状态”。然而,大多数人并没有这样做。

        1. “大多数人都没有 “这种说法太夸张了。根据我的经验,核心审核无疑是好的。如果没有它,我绝不会经营或加入一家公司。

          我现在独自编写代码,代码审查可能是我最怀念的事情。

          1. > “大多数人不 “的说法太夸张了。

            我很乐意讲道理。我想我更多的感受是,大多数开发人员并不擅长识别何时应该克制。就像大多数开发人员都是糟糕透顶的面试官一样,我认为开发人员也忘记了代码审查归根结底也是人的工作。如果给普通开发人员最小的权力,又没有足够的防护措施,那么就会出现合理的愚蠢行为。

            > 我现在独自编写代码,代码审查可能是我最怀念的事情。

            我觉得 “代码审查 “在这次对话中的含义太多了。代码审查的形式是第二个(或更多)合格的开发人员为了更大的利益阅读和评论代码?显然是好的。在非 FAANG 公司以 github PR 的形式进行代码审查?跳过。袋鼠法庭。

          1. 高级团队成员通常是最严重的违规者。

    2. 代码审查可能是破坏绩效或占据主导地位的机会。我见过无数次这样的情况。

      在排名靠前的组织中,拖延对高绩效人员进行代码审查的阴谋屡见不鲜。

      如果不在团队中符合条件的审查员中轮换审查员角色,也会破坏代码审查,在这种情况下,一切都只代表特定群体的意见。

    3. 在我看来,通常是编写 bug 的人对代码审查如此反感。

  25. 我的问题是,人工审查员发现的 bug 比 ChatGPT 多吗?https://www.thatsoftwaredude.com/content/12848/chatgpt-can-d… 说它很平庸,但那是一年前的事了,老实说,平庸的代码审查似乎已经足够了。

  26. 要学习如何审核 PR,有哪些值得阅读的精彩博客/资源?

  27. 哈?代码审查 cuz 发现 bug…人们好像真的看到了…

  28. 消除错误需要持续、警惕、整体、重叠的方法:

    – 在接受提交之前进行代码审查(Facebook 就是这样做的)

    – 重构侥幸通过的垃圾代码

    – 删除功能

    – 使用更少代码的高阶语言

    – 消除技术债务

    – 吸引更多眼球

    – 更聪明的工程师

    – 投入更多时间改进工程设计

    – 编码指南既要优化简单明了的代码,又不能过于严格,以免妨碍战略性例外情况的出现

    – 将负 LoC 作为关键绩效指标

  29. 同意。在我的职业生涯中,我主要负责管理和审查代码。我发现了很多 bug,偶尔也会发现一些可能会导致中断或给用户带来显著问题的 bug。

    但我发现更多的是没有经过深思熟虑的代码。技术债务和代码气味是真实存在的,它们会影响团队的绩效。要将这些问题消灭在萌芽状态,就需要高质量的公关审查,并花时间与提交者就发现的问题进行沟通。

    在我现在工作的公司,我和我的团队已经将高质量的公关审查变成了常态。我强烈推荐!

    其中一个关键点是 “善意而非讨好”。在公共关系中留下评论时要乐于助人,但不要为了避免冲突而表现得和蔼可亲。

    此外,如果你觉得代码审查是浪费时间,我可以向你推荐我经常做的一件事–给予警告。对于类似的 PR,我会批准并就我希望在将来修正的地方给出评论。我不会因为一些小事而耽误合并,但同时我也不会让小事一直拖延下去。

    1. “技术债务和代码气味是真实存在的

      我认为最让我头疼的是,很多时候,”尽快发布 “是一个合理的商业理由,但缺少的是对附加条件的问责。比如,好吧,如果我们现在不想修复这个问题,因为它需要在下一个版本中出现,那么我们可以按原样合并它,但你不能把它记录在外部文档中,它不能成为 API 的一部分,而且在 X、Y 和 Z 被重写为与 ABC 一致之前,不能在这个方向上进行任何进一步的开发。

      我发现这类讨论很难得到认同。每个人都乐于微笑点头,相应的票据也会被归档并附上截止日期,但下一个版本发布后,新的业务影响因素就会成为重点,清理票据就会被悄悄移到积压票据中,截止日期也会被取消。

      多年来,这种情况一直在重复,让我对这个过程产生了一种愤世嫉俗的情绪,感觉代码审查至少在一定程度上是一种挫败感的表现;我没有足够的支持来坚持在前期做好代码审查工作,所以我实际上只是在预览一两年后会发生什么。

      1. 关于这个问题有几点看法。

        1.很多问题都是由于人少事多造成的。如果只有一两个开发人员,而积压的工作越来越多,那么问题并不在于你没有时间解决问题,而是你的人手不足。如果你有足够的人手,那么从业务的角度来看,就不会出现有人在完善之前的工作,而另一个人却在做下一件事的情况。

        2.如果你的人手不是不够,那么清理新代码的最佳时机就是在编写过程中或编写完成后。我喜欢用的一句话是 “趁记忆犹新”。这样既节省了时间,又不会增加新的错误,因为你不必再次记住所有内容,将所有上下文重新载入你的大脑。

        1. > 如果你不是人手不足

          值得注意的是,有一些脂肪是好事。当你是一家初创公司,你正试图自力更生时,我可以理解,但在某些时候,你需要一些脂肪。脂肪太多不好,但没有脂肪也不好。初创企业必须精益求精,但如果大企业过于精益求精,那就叫厌食症。

          1. 的确,如果你读过《目标》或《凤凰计划》,就会发现他们把这叫做 “懈怠”。关于 “松弛 “为什么重要,有一整套理论。

          2. 另一种观点认为,脂肪在人体内是有作用的。诚然,如果你要优化一个非常狭窄的结果,非常低(但不是无)脂肪的身体看起来很理想,但首先,这实际上是一个非常不健康的身体;其次,世界上最好的举重运动员实际上都有相当可观的脂肪储备来支持和维持他们的肌肉。

            没有脂肪有助于提高速度和效率,但会妨碍你变得强壮。

      2. 不过预览还是很有价值的,当你已经知道某样东西是怎么坏的时候,你就会显得像个魔法师。

        1. 但是,当你不断提醒人们注意同样的问题,却在几个月甚至几年后不断遇到这些问题时,你就会觉得自己像卡桑德拉。

          你只能把 “惊讶的皮卡丘 “这个备忘录发这么多次,它就会失去光泽。

        2. 或者是无能。如果你早知道会出问题,为什么还要批准?你唯一的辩解就是 “当时有很大的压力要发布 xyz”。这样的辩解并不值得同情。认为被破坏的功能是有史以来最重要的事情的动物精神早已不复存在,而对之前最重要的功能所造成的新的中断的挫败感已经占据了上风。

          1. 不要批准!这其实是你可以做的一件事。

        3. 很多时候,这比 “这显然会在某个时候以某种方式影响生产 “更微妙。问题更像是觉得逻辑太复杂,以后很难维护,或者觉得应该或不应该使用某个库,或者觉得用线程做的事情应该是异步的。

          所以是的,并不像 “我说过会发生,但它确实发生了 “那样简单明了,而更像是 “我有一种感觉,这将会是一种痛苦,而我确实在审查代表这种痛苦的代码”。

      3. “没有以后。”这是我的新口头禅。

        1. 这让我想起了代码库中遍布的 “Todos”……我喜欢用 “尤达 “来形容……做或不做,都没有 Todo。

          1. TODO 本身并不坏,但我认为意图很重要–有多大可能有人纯粹是为了解决这条评论而回到这里?如果不太可能,那么 TODO 将在未来重构的背景下被使用,在这种情况下,它就是给最终考虑这项工作的人的一份礼物,帮助他们理解代码或背景的某些内容,而你在项目中意识到这些内容时已经太晚了,无法对其采取行动。

        2. 我最喜欢与此相关的咒语:

          没有什么比暂时更永恒。

          … 和 …

          我们没有时间做对,但我们有时间做两遍。

    2. 我是一名新经理,正在努力让我的团队理解代码审查的价值。我已经经历了太多的重写和重写面条代码,现在我对代码审查更加挑剔,我正试图在我的团队中推广这种文化。您有什么建议吗?

      – 同样的人在别人的合并请求上留下了详细的评论,但当别人没有为他们的合并请求付出同样的努力时,他们就会感到气馁。

      – 人们盲目地接受建议,没有任何抵触情绪,也不进行任何讨论,只为完成审核。

      – 人们把 MR 发到侧频道或其他团队,让自己的修改在没有阻力或来回讨论的情况下被合并。(我曾不得不恢复过几次这样的修改)。

      1. 良好的公关文化肯定是要从头开始建立的,并且要得到自上而下的支持。在 Shopify,我认为他们拥有非常好的公关文化,我们有一些我认为有帮助的东西(除了良好的 CICD 和静态分析工具之外):

        1.公关应该等待 2 次验收,1 次验收即可发货,0 次验收即可紧急发货。我们的团队中应该有 2 名审核人员。

        2.根据代码项目的不同,我们必须填写 PR 的模板,其中包含哪些内容,有哪些改动,测试代码时需要注意什么,等等。

        3.某些领域的代码所有者可能需要特定团队的额外审核。

        4.我们应该在审查分支时对其进行检查和测试。因此,除少数情况外,我们真的不鼓励快速阅读和 LGTM。

        我见过很多地方盲目地接受公关,这很困难,因为如果不真正执行和鼓励这种文化,就很难改变。

        1. 此外,代码审查对于需要被审查的代码也同样有效。

          最糟糕的同行评审发生在成千上万行的 PR 上,因为没有人愿意读那么多,而且会有遗漏。我所见过的成功的代码评审是,人们将代码拆分成可评审的部分,而这些单个的评审是如此之快,以至于最终完成的速度比一份巨型公关还要快。

          1. 在不把任何东西分解成一堆更小的改动的情况下,把一个自成一体的改动合理地分解成最小的改动需要多少额外的时间?

            1. 大约 10-15 分钟 ….

                  git co master
                  git co my-branch -- .
                  git add -up . # select changes relevant to first pr
                  git commit
                  git reset HEAD --hard
                  # and again...
              1. 这个问题是专门针对这种方法行不通的情况提出的,例如,您的团队不想批准只包含死代码的 PR,或者因为变更的任何子集无法编译,或者没有其他部分就无法保留正确的行为。

                1. 拥有合适的工具有助于发布 “不完整 “的工作,例如功能标志,这样您就可以发布某个功能的非常轻量级且尚未准备好供最终用户使用的版本,并继续在较小的 PR 中对其进行迭代。

                  例如,第一次发布时添加了一个新的屏幕,但只转储了输出结果

                  第二个版本添加输入字段和控件

                  下一遍添加验证

                  然后添加动画

                  等等

                  1. 理论上听起来很不错,但实际上呢?

                    1.经常需要修改或重构旧代码。仅有功能标志是不够的。

                    2.即使是功能标志本身也可能是有风险的,可能会影响现有客户的使用。

                    大多数情况下,确实需要对旧代码进行修改,至少在我的经验中,确实没有那些完美的孤立的新功能。

                    1. 如果说重构应该被放在特性标志后面,*因为*它们是如此具有破坏性。

                  2. 在我看来,这是一种糟糕的方法,也是我讨厌如今使用特性标志的原因。

                    例如,如果没有输入验证(前端或后台),我是不会批准任何东西的。我不知道你是否真的会在删除 fflag 之前添加验证功能。”相信我兄弟 “对我不起作用。

                    1. 我的意思是,你可以在功能标志后面对已编写的功能进行验证,而暂缓验证尚未存在的功能。

                      功能标志并不意味着把孩子和洗澡水一起扔掉。

            2. 实践中的忒修斯之船。

              有点像。

              原子提交很难。

          2. 您认为这可以在 PR 的提交级别上实现吗?

            1. 如果每个提交都可以单独审查,那就可以了。

              主要问题在于人、

              1.不愿意阅读冗长的内容,从而导致审批速度减慢,因为没有人愿意去碰它

              2.无法有效审查长篇大论,更有可能漏掉一些内容。

        2. 我们也有这些问题,但通常人们把这些当作官僚主义障碍,并不真正执行这些步骤。例如,模板被忽视,审稿人不检查,只是 LGTM 就可以了。很少有人真正认真去看。

      2. 代码审查文化不会凭空产生。除非您有 CI/CD、测试、任务估算、回顾、事件后记等流程,否则您永远无法让人们相信这些流程是有用的。所以,就从这些开始吧。

        增加更多的流程总是会遭到反对,但如果团队成员都认为保持工作正常是首要任务,那么这些流程就会慢慢/自然而然地出现,因为团队会意识到,积极主动地投资这些流程将为他们节省时间。

      3. 这需要时间。

        对于不习惯代码审查的团队来说,一开始可能会觉得麻烦多于值得。很可能在最初的几个月里,麻烦会大于价值。坚持做下去,最终聪明的开发人员会发现 “如果我们无论如何都要做这件事,我们不妨找点有用的东西来说说”:)

        有几件事情可以做得更顺利:

        – 管理期望值。最初可能只是 “我们只是想在每次修改时多一双眼睛 “或 “了解其他团队成员在做什么”–即沟通第一,改进代码第二。

        – 设置工具,使流程顺畅。如果有人想一劳永逸地完成工作,那么对他们来说,使用你的官方审核流程应该比使用一些旁门左道更容易。一个恶毒的替代方案就是让使用旁门左道变得更难;)

        – 利用自动化。在 PR 上运行测试、分类器、静态检查器等,这样即使没有人留下有趣的评论,开发人员也能得到有用的东西。

        – 如果团队中的某些成员已经有了代码审查的经验,那就调整他们的工作量,让他们能做更多的审查工作。他们可以以身作则,有效地培训其他人。

        – 确保审核中的代码变更大小合理。鼓励尽早并经常提交变更以供审核。说 “这是我花了 3 个月开发的功能,周五就要提交,请审核 “不会让任何人高兴。

        – 让审查不再可怕。代码审查不仅仅是为了发现错误和缺陷,也要鼓励审查者说正面的话。

        1. 这是很好的建议,我觉得 “无论如何我们都必须这样做 “这句话更像是…… “所以我们不妨让自己轻松一点”……例如,写出能正常工作的代码,并通过测试和手动(如果需要)进行自我测试,这样审阅者就不必在实际运行代码时陷入困境(开始时可以添加屏幕截图,但到后来就不需要了)。尽可能减少公关,也就是一个功能卡的多个公关接踵而至,尽快提交有价值的公关,不要因为吹毛求疵而阻拦,而是在共同的期望中开始就更好的事情达成一致,并在下一次修改中实现。

          一般的口号是 “如果它能运行,就不应该被阻止”,开发人员可以选择当场改进可维护性,也可以自行决定推迟到下一次或以后的 PR。毕竟你们彼此信任。

        2. > 设置工具,使流程顺畅。

          > 利用自动化。运行 […]流水线、静态检查器 […]。

          除非你将它们设置为只给出警告而不是阻止构建/合并,否则它们并不能使流程顺畅。无论如何,它们都可能被忽略。

          我认为,在得到团队认可之前,应避免使用内衬程序等。

          1. 这要看情况。如果你的代码库中已经没有林特警告,那么添加阻塞检查以防止出现新的林特警告就没什么大不了的。但如果阻塞检查意味着每个人都必须放弃一切,花一周的时间来修复代码,这当然就不顺利了。

            PS.另外,无论您设置了什么自动阻塞,手动覆盖都是个好主意。大多数流水线都已具备这一功能。

        3. > 一个恶毒的替代方法是增加使用侧信道的难度

          如果人们在寻求旁门左道,这就是一个信号。忽视这一点,忽视人们正在想方设法有效地完成自己的工作,我认为似乎没有抓住重点。

          > 如果一些团队成员已经有了代码评审的经验,那么调整他们的工作量,让他们可以做更多的评审。他们正在以身作则,有效地培训其他人。

          这可能会适得其反。突然之间,只有少数(可能只有一两个)团队成员在做所有的代码评审。他们感受到了压力,不想成为出货的阻塞部分,因此他们的审查工作就草草了事。他们会在其他前辈的意见上盖上 LGTM 的橡皮图章,并可能在第二天才审查其他审查意见。他们很难完成自己的工作,每天 2 个小时的代码审核工作影响巨大(如果审核其他 2 名开发人员的工作,而他们在一天内 6、8、10 个小时都在编写代码,那么第二天就需要 2 个小时来审核他们的工作)。

          > – 确保审核中的代码变更大小合理。鼓励尽早并经常提交修改以供审核。说 “这是我花了 3 个月编写的功能,周五就要提交,请审核 “不会让任何人高兴。

          反过来说,”嘿,请尽快审核,这样我就能在接下来的两个小时内再给你一系列 4 个修改,最后再发送更新来完成这件事”。

      4. 我写了一些我在团队中成功应用的规则。https://max.engineer/mindful-code-reviews

      5. 文化是创造出来的,不是偶然的。

        我会在小组会议上提出所有这些问题,甚至更多。尽量让大家了解审核给提交者和审核者带来的各种好处–让他们说出自己想要或可能得到的好处。讨论各种类型的意见(明确的错误、性能、风格、健壮性、因素和组织等),以及从不须采取行动到小毛病再到阻碍的各种优先级。讨论审核本身的优先级。减少审核的延迟会产生巨大的积极影响。

        1. 人都是聪明的–听听他们的担忧如何?在用一系列 “最佳实践 “和 “预期结果 “来打击他们之前,先听听他们的意见吧。

          我开始认为,在代码审查中,挑毛病完全会适得其反。

          自从我了解了 “Ship/Show/Ask “之后,我对代码审查的看法发生了翻天覆地的变化:https://martinfowler.com/articles/ship-show-ask.html;我不再相信审查每一个改动都是健康的,看到其他模式的不同之处,我就知道它现在是有害的。在我看来,另一种好方法是允许合并后审查,”ship/show/ask “更好,但为什么一定要在合并前进行代码审查呢?

      6. 社会氛围如何?

        我这么问是因为我有一份工作,在 COVID 之前,技术团队只有几个呆头呆脑的程序员在一间办公室里,而在 COVID 之后,技术团队只有一群我不在其中的朋友。

        我的意思是,在 COVID 之前,创始人经常会带我们出去吃午饭或打网球,就像正式的团队建设时间一样。我很喜欢这样做,因为我很挑食,很难交到朋友,所以如果公司有正式的活动,我就更容易融入其中。

        在 COVID 之后,官方活动的力度减弱了。团队太大,无法带所有人出去玩,我也没有加入那些自然而然找到社交方式的朋友圈。

        在新的环境中,我不再觉得自己是团队中平等的一员,我觉得自己就像一个局外人,拥有纸面上的权力,却没有完成工作和度过工作日所需的任何友情。

        尽管每个人都一再表示,我作为最资深的程序员受到了尊重和重视,但我发现在新的环境中,我不可能成为一个好队友,我觉得自己整天都在刻薄,没有人把我当人看。这就是我辞职的部分原因。

        在那样的环境中,我的代码审查很糟糕。

        现在,我在一家远程公司工作,在那里,我再次感觉到每个人都同样不合群。如果他们有了办公室,我可能会套现,然后去度假一年。

        编辑:差点忘了,原来那个 “书呆子程序员 “团队中的另一位女成员,也在我辞职的同时倦怠了。她在新环境中也没交到什么朋友,似乎更乐于追求自己的兴趣爱好,在工作间隙过得轻松自在。

        1. 大三学生能和大四学生做朋友吗?我觉得这是一种 “教授-学生”/”私人-中尉 “的关系。

          我在代码评审中也整天刻薄,而且和团队中的大多数人相比,我还是个相对低年级的学生!>:]他们不把我当人看,因为我不是人。我没有他们的人类情感和关切。我只关心代码。不过,感觉上他们还是喜欢和尊重我的!

          1. 我想我不喜欢成为唯一的中尉吧?

            感觉我的权力只停留在纸面上,却没有落到实处。一切都井井有条,没有人把任何事情写下来……

      7. > 同样的人在别人的合并请求上留下了详细的评论,但当别人没有为他们的合并请求付出同样的努力时,他们就会感到气馁。

        这种情况总是岌岌可危。因为一旦这些人变得颓废,你创造良好公关文化的能力也会随之消失。他们厌倦的原因有很多。如果这些人没有得到明示或暗示的重视,他们就会知道。如果做错事的人先得到晋升(甚至以同样的速度晋升!)、同样的加薪/奖金,而且在所有方面都一视同仁,那么员工几乎总是会得出这样的结论:”如果这对我没有任何好处,我为什么要付出这些额外的努力呢?我不认为提前晋升或类似的承诺会有好的效果,因为有很多员工都得到过这样的承诺,但却没有兑现[0]。因此,在短期内需要有一些奖励,哪怕是微不足道的奖励。

        此外,不要低估明确说 “干得好 “的价值。在沟通中,往往存在着一种巨大的偏见,即只有在出错的时候才会说 “做得好”,而在做得好的时候却不说。你不必事事都说 “干得好”,但我想你会惊讶于有多少人从未从管理层那里听到过这句话。

        [0] 我想和大家分享一个我遇到的故事。我是一名绿色(机械)工程师,在一家初创公司工作。我拥有物理学学位,而不是机械工程学位,但我一直都是动手能力很强的人。但正因为如此,我的薪水较低,也不被重视。我问我的经理,我需要做些什么才能得到晋升,与其他人平起平坐。我把它写成了书面材料,这样我就可以参考了。在下一次绩效考核时,我被说得一无是处。抱怨我没有做到这一点或那一点(有时是不可能做到的事情,有时则很奇怪,比如 “你的代码可能快了 20%,但 X 无法理解它,所以我们不能使用它”–X 是一位只用 C++ 写了不到一年的经理,而我__大量__记录了我对函数的使用)。我询问了我所做的事情和承诺。他们承认我做了所有这些事,甚至更多。其中之一就是拿到了一份合同(我想他们把合同写在这里并不是指望我能拿到),我是唯一一个拿到合同的非经理人,为公司带来了 20% 的收入,同时我也是那个项目上的唯一一个人。你可以想象,我从那次会议上走出来时,我的简历已经被擦得锃亮,从那时起,我就成了朝九晚五的上班族,做着最基本的工作。但我的下一任经理对我赞赏有加,会批评而不是抱怨。他理解我的工作存在未知数,当我加班时,他会让我回家。我一生中从未如此努力地工作过,这也是我最快乐的时光。一个经理可以成就一个员工,也可以毁掉一个员工。这其中的一部分原因是,也许有办法让那些崩溃的员工重新振作起来,但你可能需要先弄清楚他们为什么会崩溃。以及这是否是你能解决的问题。我相信环境对员工的态度有很大的影响,进而影响效率/生产力。如果激情能抵得上 10 点智商,那么快乐至少是让员工高效工作的一个重要因素。每个人都能赢,因为这不是一个零和游戏。

      8. 与人交谈,好奇他们为什么不重视代码审查。

      9. 请继续努力提交 PR!垃圾代码属于垃圾。

        1. 大量垃圾代码正在为所有大型科技公司赚取数十亿美元。亚马逊、Facebook 等公司的大部分代码都是垃圾代码。更不用说那些 “自负盈亏 “的小公司了,它们的代码都是创始人级别的,而且还处于不断 “修复和扩展 “的阶段。

          更重要的是,当一个人致力于某件事情,然后它被称为垃圾时,会形成一种什么样的文化?另一方面,如果有人审视了自己的进展速度,并做出了一个战术性决定:也许某件事情还不错,虽然不是很好,但已经很不错了–他们会把节省下来的时间花在完成项目上;然后,当评审者认为公关是 “垃圾 “时,又会发生什么呢?

          我还认识到,我需要更加有意识地让各种火苗燃烧起来。不可能事事顺心,有时简单低质才是最好的。

      10. 多年前,我有一个老板,他在一瞬间朝我扔了一把椅子。(这可没听起来那么夸张)。

        如果能再为他工作一次,我一定会心甘情愿。因为他虽然会对我大吼大叫或训斥我,但他也愿意给我好的建议,提升我,教导我。

        办公室不是一个安全的空间。你似乎知道哪里出了问题,我肯定你已经很客气地问过了。我相信你提供了胡萝卜,但你的团队知道你有大棒吗?

        > 同样的人在别人的合并请求上留下了详细的评论

        当众表扬这些人做得好。告诉大家,他们设定了标准,而其他人没有达到。

        > 人们盲目接受建议

        辅导,大量的一对一辅导,让他们找到并发出自己的声音。大量的 “团队建设”,让强势与弱势的声音平分秋色。找出那些沉默寡言的人的长处,并围绕这些长处开展有趣的活动。让他们找到…

        > 人们将他们的 MR 发送到侧频道或其他团队

        坚持。措辞严厉的电子邮件。当众贬低。明确告诉团队 “这是不可接受的行为”。

        至于那个扔椅子的人…他总是很公平,总是把团队放在第一位,在他手下工作,我作为一个人、一个经理和一个工程师都得到了成长。在我拿到工资支票的同时,这不是成长的快乐幸运的好时光,而是成长的痛苦,将这种(痛苦)传播开来是你工作的一部分。

        1. 至于躲避投射物:是的,办公室应该是一个安全的空间,如果有人朝我扔椅子,我们中的一个第二天就不会在那里工作了。(加上 “也许他们扔椅子是为了让你躲避从你身后爬过来的忍者 “的正常说明)。

          1. 这把 “椅子 “上有 3 个衣架和 2 个飞盘……我不知道它是怎么把人举起来的。

            那 “扔 “更像是推了一下,那东西就朝我飞过来了。

            那把椅子唯一会伤害的就是我的感情。

            这可比我坐在装运弹药的办公室里可怕多了。

            1. 我很震惊,很震惊,你居然只是为了表达自己的观点而对自己的经历撒谎。有一次,我和一个谎称曾向人扔椅子的人共事,结果发现他是个被通缉的连环杀手,公司差点破产。当然,这一切都不是真的,但如果是真的,那也是我拒绝与这样的人共事的有力佐证!

            2. 你真有勇气,做了一份可怕的工作,不是为了保护其他人过上艰苦的生活,而是为了能在公告板上对他们挑刺。也许我也该这么做

        2. > 办公室不是安全空间。

          它他妈的应该是一个安全的空间,在那里我不会被我的老板向我投掷大型射弹。

        3. 有些工作文化太不利于冲突了。我认为这当然与个人性格有关,但我想归纳为西海岸人不利于冲突。在这些例子中,你可以在 Linked-In 上找到所有的拉拉队,一切都棒极了,发货速度超快,松鼠

          在这些情况下,我发现冲突被掩盖了,而不是以冷静和理解的方式解决。如果没有后者作为范例,大家就会为了和睦相处而互相攻击,同时也就没有了解决分歧的机制。突然之间,在评审中,你就成了拖延时间的 “那个人”,而评审者和被评审者都没有一个健康的文化来讨论问题。

          很抱歉我说了这么多,我认为降权是对一些团队可以有健康的冲突并通过冲突解决问题的震惊的反应–有时它可能看起来像吼叫(通常吼叫就是吼叫,但当一个团队与另一个团队是真正的朋友时,他们会有自己独特的方式来解决冲突)。

    3. 从未意识到这是一个有争议的话题。是否有聪明人认为不需要代码审查?反对代码审查的最佳理由是什么?

      1. 我曾与一位首席技术官交谈过,他反对代码审查,因为代码审查增加了太多开销,部分原因是代码审查在流程中太迟了。

        他鼓励他的团队事先讨论一种方法,或者一起研究一些东西。

        除此之外,他们还有大量的测试和结构非常严谨的代码库,我想这对他们来说是行之有效的。

      2. 我曾在一个团队工作过,该团队不做评审,因为包括尖峰、研究等在内的所有工作都是由两名工程师结对完成的。这是远程的,整天都有摄像头。

        我觉得这让人筋疲力尽。因为配对过程占用了我大量的认知带宽,所以我的工作能力达到了 100%,但产出却只有 50%。

        1. 我参加过全职配对团队,但发现吞吐量提高了 2-5 倍,因为会议、代码审查和上网的次数减少了。这让我很疲惫,因为突然间我每天要写 7 个多小时的代码,这真的很难。

          我参加过的其他团队在没有配对的情况下,每天最多也就写 3 个小时的代码。其余时间都被其他交流渠道占用了。

      3. 我想我大概做过 1000 到 2000 次代码审查。从那以后,我对代码审查的看法发生了翻天覆地的变化。我可以列出一个长长的清单(抱歉,有点冗长……):

        CR 拖慢了工作进度,而且往往是不必要的。耗时过长

        不必要的解释浪费时间。

        当评审员只有一两个人时,有点不可能。如果审核员人数较多,可能就不需要上下文了。

        造成不发货的偏见。”等待 CR “可能会严重阻碍产品的发布。也许,今晚是你把东西放到 prod 中的好时机,而不是明天–但你正在等待 CR。

        这是流程重于人的一个例子(又名:货物崇拜)。何时/何地/如何/为何进行客户关系管理是很重要的,也是因地制宜的。在不同的情况下,客户关系管理的最佳实践会产生不同的结果。通常情况下,客户关系管理只是因为它是一种最佳做法而盲目进行。最好是深入思考什么是重要的以及为什么–而不仅仅是 “哦,对了,这是另一个我们要通过的障碍,因为 #亚马逊做到了”。

        团队分层。在审核过程中,资深/精英/受宠的人总是比较容易过关。

        CR 可能会变得政治化。Scrum 主理人和经理们争先恐后地为团队成员解围,让他们对某些事情进行审核。这对于那一次来说是件好事,但除此之外就会暴露出一个完全崩溃的流程。当 CR 被 “升级 “时,审查员有多大可能真的会花费必要的时间和来回奔波来 “正确 “地审查事情呢?

        这就容易产生 “小毛病”,而 “小毛病 “是无用的,会适得其反。花在小毛病上的时间是一种浪费,而且会耗费精力,因为要不断地回头去看某件事情,然后再去调整 “它还不够好吗”?

        没有背景的随意审查

        在审查过程中达成一致意见是很困难的。不是每个人都能观察/体验和/或解决冲突。

        CR 在代码开发过程中出现得较晚;这是最糟糕的时候之一,因为在某些东西已经完成、打磨、测试并为生产做好准备之后,突然有人认为应该以不同的方式来完成(当某些东西已经完成并开始工作时,这就更容易看出来了)。这就好比写了三次代码,一次是为了把它写对,第二次是为了把它写好,第三次则是为了满足审查员的任何要求。

        这表明对团队缺乏信任。这是把关。

        不能很好地扩展。曾经有一位审核员告诉我,我写代码的速度比他们读代码的速度还快。(当时,我每天审核大约 6 份公关报告,并发出大约 3 份。我负责 80% 的审核工作,这简直是一场灾难;我收到的审核既慢又无用–团队成员都在努力交付他们捉襟见肘的项目;我太紧张了,既无法提供适当的反馈,又不能每周工作 100 个小时)。

        还有更好的选择,即 “运送/展示/询问 “策略: https://martinfowler.com/articles/ship-show-ask.html

        后一种分支策略由代码作者决定:”这个注释中的错字修复需要审核吗?这段代码中的修正是我最初编写的,我对它了如指掌–真的需要阻塞审查吗?在最后一种情况下,如果一个人可以立即合并一堆前导重构,那么他就可以把这个问题解决掉–这样他送审的 PR 就会变得干净而有趣;而且也不会耽误管理分支或纠缠别人的时间。

        让事情变得更好的第二个方法是允许 “合并后 “审查。在我所在的几个团队中,我们已经做了很多这样的工作,因此我们知道了什么样的东西适合单独发布。在另一种程度上,我们没有足够的带宽来审查所有的东西。这并不是坏事。

        1. 这是一堆缺点,但我想我要问的是,是否有聪明人认为,考虑到这些替代方案,总的来说,还是不做为好?你似乎很反对–你会提出什么具体的替代方案,结果可能是什么?

          1. 就像没有一个最有力的 “赞成论据 “一样,”反对论据 “也是如此–>背景比 “最佳做法 “更重要。

            我注意到

            > 还有更好的选择,即 “运送/展示/询问 “策略: https://martinfowler.com/articles/ship-show-ask.html

            说到底,这就像敏捷和 Scrum。实际上,你必须认真思考你的环境,不能只是去套用一个模板式的一刀切解决方案。(最近我肩上的担子很重,因为我觉得 IT 界有太多的人不愿意认真思考他们的背景。太多了:”我想让我的团队’快马加鞭!'”。他们的口头禅是:只要做好站立、做好复古、做好代码审查、做好计划、添加 checkstyle(一种代码语法筛选器)–一切都会很顺利!我现在学会了问–但项目是否及时完成了?在这种情况下,这些项目中是否有任何一项是真正有用的?如果有用,请告诉我具体原因并提供详细信息。我还了解到,如果一个团队远在石器时代,试图采用所有最佳实践的时间很可能比该团队和/或公司的剩余寿命还要长。这就意味着,他们除了在流程变更上喋喋不休之外,不会再做任何有用的事情。这又让我想起了公司责任,有多少公司责任是真正有用的呢?有些 CR 肯定是有用的。不过,一个团队怎么可能花更多的时间去做有用的公关,而花更少的时间去做无用的公关呢?更重要的是,每个 CR 都是一项阻塞性活动,如果我们为了一项通常无用的活动而阻塞开发,那就有问题了。替代方案不一定是完全放弃 CR,我已经提到了两个:”ship/show/ask “和合并后审查(review)。

    4. > “亲切,而非友善

      在加入一个团队时,我对开发人员说的第一句话总是:”我不在乎你有多挑剔,只要诚实就好。”我认为尽早设定期望非常关键。我认为,让开发人员不觉得自己的代码受到攻击或过于自卫是一个很好的进步。在我看来,强烈捍卫自己代码的人是糟糕的开发者。

      1. 我有一个同事,他花了更多的时间为自己的代码辩护,给出一系列错误的原因,而不是真正地修复它们。这种情况已经不止一次了。

        我只是继续工作。总有一天他会意识到他的代码有多糟糕。

      2. 听起来很激进坦率,我喜欢

    5. 这些警告该如何措辞?”下次……”?我很难认真对待自己的警告,如果现在已经足够好的话。

      1. 我们会在评论前加上 “minor:”,所有员工都知道,这意味着这是一件很好但没有必要合并的事情

      2. 使用删除键。(对不起,我说的是玩笑话,但我是认真的,根本不要发送这类评论意见)。

        如果暂时没问题,那就没问题。如果不好,那就说出来。

        如果你确实有这样的顾虑,”暂时没问题”–那是线下谈话的内容,不属于 CR 的范畴。这也是检验一条意见有多重要的试金石。你会安排 15 分钟的会议与同事讨论这个问题吗?如果不会,那为什么可以在公约与建议委员会会议期间这样做呢?

      3. “这暂时没问题,但我们应该考虑一下如何序列化这些对象。请随时在后续版本中删除 N^2 算法。”

        1. 这在你们都是同一家公司的员工,而且彼此尊重的情况下非常有效,但在开源世界中往往行不通,人们就这样消失了,你再也不会听到他们的消息。他们有可能会进行后续跟踪,但根据我的经验,这种情况很少见。

          1. 是的,即使是在公司内部,我接受修改的门槛也会因我的经验和与作者的关系而有很大不同。对于外部贡献者或从未与我合作过的人(通过审核代码或让人审核我的代码),我不会接受代码,直到几乎所有的工作都让我满意为止。而对于经常与我合作的人,我在接受一项修改时往往会加上这样的评论:”这一切都很好,但您需要考虑到 X,这将改变这个补丁中的几乎所有内容”(我说得有点夸张,但只是稍微夸张)。我知道一个更新是否会有问题,是否有必要再看一遍。有时,有几种显而易见的方法可以完成某件事情,他们会选择其中一种,但如果我有理由选择另一种,我就会选择另一种,因为我有理由。

            大多数情况介于两者之间。

            虽然在某些方面,这恰恰相反。对于一个陌生的开源贡献者,我需要确信他的改动是值得的。我会在文体方面放宽要求,我会直接使用他们的补丁,之后再进行修复。如果是我合作过很多次的人(不管是熟悉的贡献者还是同事),我会相信他们对改动的基本质量的意见,但对不必要的风格差异则不那么宽容,因为他们应该已经在这些方面达成了一致,如果他们漏掉了什么,更有可能是疏忽。(另外,鉴于超过 90% 的补丁将来自普通贡献者,我不想在事后修正他们的修改)。

          2. 另外,”时不我待 “是真的。跟进很少发生,跟踪起来很麻烦。让某个人为此负责是不公平的,尤其是如果他们不同意后续行动的话(想必他们是不同意的,否则他们一开始就会做这件事)。

    6. >围绕你发现的问题与提交者会面的时间。

      什么!如果有人安排与我会面讨论公关问题,我会气疯的。我们已经有太多会议要开了,这是唯一可以幸免于难的流程之一。

      1. 我也是,我真的很不喜欢这样的会议,本来可以在 slack 或公关中问我三四个问题,然后等我十五分钟左右再回答。

      2. 会议不需要太正式,也不需要太长。我个人很喜欢公关会议,在会上我们可以探讨代码并理解它,而不是有人在午餐时间把 2000 行代码倒在我的腿上,然后希望在晚饭前把他们的意大利面搅拌均匀

      3. 生气?开会讨论工作?有些人在懒人空间等地方发表的评论听起来比原意更糟糕,而人们也意识到了这一点,所以有时会不遗余力地以原意的方式表达出来。

      4. 说白了,如果提交者想讨论问题,我就会安排时间见面。我并不要求每份公文都要见面。我会根据需要与提交者会面,但频率很低,因为提交者需要尽快熟悉情况。

      5. “当面 “审核是我认为最好的审核方式。如果一份 CR 会有十几条关于所有事情的评论,那么异步审查就是一场灾难–作者会觉得自己受到了攻击。解决冲突和分歧的对话可能不会有好结果。

        就我个人而言,如果团队不习惯当面解决冲突,我喜欢从当面解决冲突开始。只有在建立了健康的关系和冲突解决机制之后,才会进行异步公关。我还喜欢这样一条规则,即在一次 CR 中,通信往返不应超过 2 次,否则应同时进行。

        在很多环境下,推迟小的改动以允许这样的往返时间是不可行的。要做的事情太多了。不值得。当项目失败时,很少会有经理给项目贴上一个大大的 “失败 “标签。我提出这个问题是想说,项目失败总是因为团队进展太慢,而个人往往不知道他们实际上需要更快的进展(反馈回路往往缺失,”哦,我们实际上太慢了,我们需要比实际更快的发货速度。JIRA、计划、估算、CR、最佳实践、修复衬垫所花费的时间–这一切都不重要,因为这个项目实际上失败了–它花的时间太长了。)

  30. 我认为这真的很重要,因为它比 “代码审查 “更重要。它确实说明了人们对统计数据[0]的误解有多深。但人们之所以 “相信”,是因为他们讨厌代码审查,而不是因为他们 “真的 “相信审查结果。

    但统计数据是很棘手的。以文章中举的例子 “15% 的吸烟者会得肺癌 “与 “80% 的肺癌患者吸烟 “相比。这两者并不矛盾,只是看待同一事物的不同方式而已。事实上,人们往往就是这样用统计数据误导你(或者说你可能无意中误导了自己!)。

    另一个有名的例子是时不时出现在 HN 上的:”尽管只有 5.8% 的销售额,但超过 38% 的错误报告来自 Linux 社区”[1]。简而言之,这个例子讲述的是 Linux 用户在提交错误报告方面受过更多训练,而且大多数错误并不针对特定系统。因此,如果只根据提交者的架构来对错误进行分类,实际上会错过很多有价值的信息。由于统计学的工作原理,如果架构依赖率甚至低至 50%(我会很惊讶的!),那么仍然会有大量有用的错误报告。作为一名 Linux 用户,我见过这类 bug,它们并不少见。但我经常看到,因为我是从 linux 系统报告的,所以它们就被驳回了。更有甚者,支持人员会将你发送到他们的页面,要求你为某个 “功能 “或错误问题 “点赞”。你必须先登录。我无法认真对待这样的公司,但该死的是,Spotify 也这样对我,我还把出错的那行代码发给了他们。Netflix 也这样对我说,”我们不屏蔽 Firefox”,但切换用户代理后我就能访问了。有时候,我们的思考不能只停留在表面。

    所以,我想说的是,这里有一个可以抽象出来的普遍教训。

    [0] 大家都开玩笑说统计数字是编出来的,但这同样不好。

    [1] https://news.ycombinator.com/item?id=38392931

    1. > 支持 “会将您发送到他们的页面,要求您为 “功能 “或错误问题 “向上投票”。

      微软为企业产品提供这种服务,客户可能每月支付 10 万美元甚至数百万美元。

      “我们听到了,但你的抱怨还不够流行,所以请走开。”

      “当然,这是一个灾难性的数据丢失漏洞,吃掉了你的财务交易,但如果其他人无法识别他们看似无关的崩溃是完全相同的问题,那么你就没有修复的机会。”

      “既然你在一个名为’Consiser尽职尽责’的问题上获得了一万张选票,我们决定通过删除错误论坛来改善你的体验,并从头开始建立一个新的论坛,减少不爽用户的尖刻评论。”

      1. 我所在的公司/团队对错误和功能请求的处理流程截然不同。如果客户开了一张单子,而我们确定它是一个错误,我们一般会在报告的版本中或之后修复它(除非它是一个安全漏洞或其他重大问题)。但对于功能请求,我们只是告诉他们将其提交给社区,然后我们会评估它是否有效,考虑到我们的其他工作,我们可能会实施它,但不一定会很快实施。

        1. 有时,功能请求实际上是一个错误,可以说明我们没有正确理解设计。

          但我认为,如何理解用户的功能请求非常重要。他们有一种挫败感,你可能没有意识到,但他们并不知道所有的代码和限制。这甚至可能是设计方面的问题,但这仍然很重要。很多时候,有一种方法可以解决用户明确要求之外的功能请求。但要做到这一点,你必须仔细阅读字里行间的内容。当然,有些人在这方面完全走错了路,他们认为苹果公司知道什么对用户最好。这完全是一种难以取得的平衡,但我认为,将其简单化是很常见的。

          有人开玩笑说,用户是傻瓜,也许他们是傻瓜,但这并不意味着他们面临的问题是傻瓜。当一个人拉一扇写着 “推 “的门时,他并不总是哑巴,因为实际上可能是标志和设计表达了不同的意思[0]。就我个人而言,我喜欢用户提出解决问题的方法。我可能会把它扔进垃圾桶,但它往往能给我提供更好的上下文线索,让我知道他们想问什么,而且如果他们认真思考了这个问题,也确实告诉了我他们对产品的关心。他们只是没有我这样的视角,没关系。

          [0] https://www.youtube.com/watch?v=yY96hTb8WgI

          1. > 有时功能请求实际上是错误

            两个缺失的功能加起来可能就是一个错误。例如,我曾使用过同一供应商的两款云产品,其中 CDN 产品缺少的后端 HTTP 功能与 PaaS 服务缺少的 HTTP 前端功能相互影响,导致这两款 “天然契合 “的产品实际上无法结合使用。

            这使得许多本应可行的架构无法实现,迫使客户采用扭曲的设计模式或第三方产品。

            在我看来,这是一个错误(”无法使用你们的产品”),但每个团队都将其单独标记为缺失功能,然后他们在大约三年的时间里都忽略了这一点。

            另外:没有足够多的人投票支持缺失功能,因为没有足够多的人使用产品……因为他们不能。

            我知道这有点离题,但这又回到了博客原文中 “统计很难 “的引言。依靠你并不完全了解的统计数据,你可能会犯下灾难性的商业错误,比如这个 “你不会因为产品无法使用而收到很多投诉 “的例子。

            然而,对于可用的产品,你会收到很多投诉……他们有用户投诉。

            https://en.wikipedia.org/wiki/Survivorship_bias

            1. > 因为没有足够的人使用这些产品……因为他们做不到。

              我认为这完全没有跑题。我认为这是明确的主题,至少是基本主题。不只是统计很难,测量事物也很难,确定因果关系更是难上加难。这通常是统计学和数据科学的根本目标。找出事情发生的原因。测量非常困难,而人们往往认为测量很简单。问题是,无论你测量的是什么,实际上都是一种替代,都具有不确定性。如果你不能很好地理解衡量标准的含义,你往往就不知道这些不确定性。付出艰辛的努力总会有回报,但不幸的是,如果不付出艰辛的努力,就可能要花费一些时间才能使接缝开始裂开。我认为这种不对称往往是人们马虎的原因。

              1. 我喜欢用的例子是 COVID 统计数据引起的混乱,以及人们是如何误解这些数据的。

                例如,新闻中经常报道的每日感染(或死亡)率实际上是:感染率 * 测量精度 * 测量率。

                如果有更多的人接受检测,”比率 “就会上升。

                如果 PCR 检测得到改善,”比率 “就会上升。

                类似的情况也适用于住院和死亡人数。上升的原因可能是某种菌株比另一种菌株更致命,也可能是更多的人感染了同一种菌株,还可能是更多的死亡归因于 COVID 而不是其他原因。

                不同的国家有不同的报告标准,或者报告标准随着时间的推移因环境而改变,这都无济于事!

                等等……

                这很复杂!

      2. 你是说他们不再审查错误报告,不再试图让你相信他们的软件是无懈可击的?

        与我与他们打交道的时候相比,这已经是巨大的进步了。

        1. > 不要审查错误报告

          他们确实会这样做,但即使是礼貌但脾气暴躁的评论最终也会累积到看起来很糟糕的地步。这些评论是公开的–这就是关键所在–因此隐藏它们的唯一办法就是删除它们。通常这种做法会让用户更加不满,所以 “窍门 “就是把整个论坛扔在地上,换一个新软件重新开始,以此来 “改善 “服务。这并不是因为它在任何方面都更好,而是因为它隐含着从 “BUGS “中删除*的意思。

          微软现在已经是……第三个论坛了?我都数不清了。

    2. 基本上,代码审查也会发现很多其他非错误的东西(可能是小毛病和风格问题)。

      这就是为什么看百分比是危险的。您可能在每次代码评审中发现 5 个错误,这已经很多了,但如果您还提出了 30 条其他非错误意见,那么突然间 “只有 15% 的意见是错误”。

      1. 我完全同意。有很多事情是无法轻易衡量的,也有很多事情是永远无法衡量的。但这并不意味着它们不重要。按照你的观点,执行良好的风格可以避免以后出现错误,甚至可以节省很多时间,因为你的代码不会慢慢变成意大利面条。我认为这是人们经常忽略的一点。细化通常是通过一个较慢的过程发生的。是通过数十次提交,而不是少数几次提交。

  31. 代码审查的价值实际上取决于代码和处理代码的人。对于在同一个 repo 上工作多年的团队来说,代码审查可能没有太大价值。但如果团队中新来了一个人,或者是一个初级开发人员,你肯定会想要审查他们的代码。

    代码审查的作用不仅仅是发现错误。你可以指出更好的方法。也许这个 SQL 可以更有效率。也许你可以重构一些代码,使其更健壮。也许你应该在这里添加一条日志语句。这个方法的名称很混乱,我建议将其更名为 xyz?

    1. > 但如果你的团队里有新人,或者是后辈,你一定要审查他们的代码。

      来自后辈或新团队成员的审查也非常有价值,因为他们没有其他人可能拥有的历史或部落知识。他们经常会发现一些因为 “就是这样 “而被忽视的问题。

    2. > 对于在同一个 repo 上工作多年的团队来说,代码审查可能没有太大价值。

      我确实在资深开发人员编写的代码中发现过 bug [代码审查期间的 ETA],这些代码他们已经熟悉了十多年。

    3. 我真的很好奇,我想就您在审核和接受审核方面的经验问您一些后续问题。您介意发邮件到 hn@xkqr.org 吗?

    4. 代码审查还能让团队了解代码中的最新变化

      1. 常见的说法,但我认为这种说法是错误的。PR 的作用是向团队发送邮件,PR 留下的是网页和变更内容的摘要。在那里工作的是 PR,而不是 CR。这意味着,您可以打开并立即合并没有 CR 的 PR,以获得同样的好处。

        CR 的确给了其他人研究代码、熟悉代码的机会,但这与 “保持更新 “是两码事。

  32. 我不知道作者为什么忽略了”……应该阻止提交 “这一部分。

    论文摘要

    > 由于代码审查有很多用途和好处,因此它是现代软件工程工作流程的标准组成部分。由于需要人员参与,代码审查往往是代码集成活动中耗时最长的部分。利用在微软公司获得的经验和数据支持,我们认为:(1) 代码审查通常不会发现本应阻止代码提交的功能问题;(2) 有效的代码审查应由具备特定技能的人员执行;(3) 代码审查的社会方面不容忽视。我们发现,我们需要对代码审查工作流程的指导原则更加精益求精。我们将展示我们在代码审查实践中的发现是如何影响微软的代码审查工具的。最后,我们断言,代码审查实践因其成本高昂,是一个值得更好地理解、系统化并更精确地应用到软件工程工作流程中的主题,而不是目前规定的最佳实践。

    “代码审查找不到错误:当前的代码审查最佳实践如何拖慢我们的脚步

    https://www.microsoft.com/en-us/research/wp-content/uploads/

    1. 应该阻止提交 “总是最棘手的部分之一。有句话说”开车比你慢的人都是白痴,开车比你快的人都是疯子”。但的确,开得越快危险越大,有一种速度可以适当平衡利益与风险;但每个人的看法不同。

      代码气味 “问题也是如此:每个要求你改动的人都是迂腐的人,他们会为了毫无意义的美观而拖慢项目的进度;而每个反对你要求的改动的人都是牛仔,他们会让代码将来更难维护。

      那么在论文中,他们是如何决定一个非错误的修改是否 “应该阻止提交 “的呢?

      1. 如果评论指出了错误/缺陷[1],那么就应该阻止。

        仔细想想,随着错误/缺陷的删除,代码会变得更加正确,从而更加稳定,因为它不需要额外的修改来删除错误,所以删除错误可以减少未来维护的需要。

        如果我们因为对未来维护的担忧而阻塞,那么我们实际上是在断言需求是不稳定的,而且从总体上来说,删除现在的错误是没有价值的,因为需求变更会删除有错误的代码行,并用有新错误的新代码行取而代之。

        我想这取决于特定组织的代码审查流程,是否适合在这一点上阻止代码出现架构/设计问题。根据我的经验,代码审查步骤在开发流程中处于下游位置,而且只关注代码的一个子集,因此无法有效地处理对维护有重大影响的设计变更。

        [1] 论文作者审查了微软内部代码审查工具中的数据,该工具是专有的,因此我们无法看到具体的错误是什么。

  33. 代码审查不仅能发现漏洞,还能从根本上防止漏洞的出现。

    当开发人员知道会有其他人审查他们所编写和提交的代码时,他们会更加谨慎。

    不久前,我们在一个多年期项目中对代码审查政策进行了几次迭代。随着时间的推移,我们从未真正看到代码审查捕获了大量的错误,但每当我们减少代码审查时,我们就会发现生产错误率肯定会上升。

  34. 我对代码审查的不满在于,它们往往会导致大量时间的浪费,有时简单的拉取请求一周内就会花费数千美元。

    我工作了 6 年,时间不多,也不像其他人那样在很多地方工作,但我已经形成了这样的观点:代码评审就像测试一样,应该在必要时作为一种工具使用,而不应该在每次变更时都默认使用。

    在最好的情况下,创建拉取请求的人员会要求审核或决定需要测试的地方。

    我的观点显然适用于产品软件,但对于库而言,尤其是在公开发布的情况下,您需要尽可能多的讨论和测试。

    1. 对我来说,把小的、连贯的、解释过的、测试过的、可审查的变更单元作为自己的工作成果展示给他人,这对我来说有 80% 的价值。至于其他人是否真的深入思考过,或者有什么有用的意见,那都是次要的。

    2. 阻塞代码审查当然也是如此。我有兴趣探索另一种方法,即提交后审查。这里有一篇介绍这种方法的文章:https://copyconstruct.medium.com/post-commit-reviews-b4cc216…

      代码仍然会被审核,但你不会因为等待某个人的审核而导致 PR 被搁置数小时、数天甚至数周。

      1. 我以 “是 “和 “否 “的心态审核了很多代码。

        基本上,当我开始编写 PR 时,我就会在脑海中批准该 PR,直到我发现一些阻碍。例如,导致数据丢失的大问题、性能问题或破坏其他代码的问题。其他的最多只是一个小评论。默认情况下,PR 会被批准。这就赋予了开发人员责任和所有权。此外,它还能加快发布速度

        进行后续公关以改进或解决某些问题与阻止 MR 一样快,但阻止 MR 会影响士气。

        根据我的经验,这种方法能培养责任感和主人翁精神,消除代码审查中对他人工作的监管。

        此外,关于格式、何时测试、设计、特性、功能、架构的决策和讨论不应在代码审查期间进行,而应在编码之前或在工作期间进行。代码审查是最不适合讨论这些问题的时候,在我看来,它应该是对实现进行理智检查的时候。

      2. 我曾经在一个小团队里做过很多这样的事情,我们不阻止审查(我们做审查,但不阻止)。我是团队中的资深开发人员,我会花时间通读收到的新代码。这样做效果很好。

        有趣的是,这部分代码/项目没有超级严格的代码审查要求,但有大量测试,是我认为最健壮/高质量的代码。在一个相当重要的应用程序中,它的运行用户超过 1000 万。它并不庞大,而且有很好的测试(一般来说是相当可测试的)。

        尽管如此,要控制提交后的审核确实很难。也许我们需要更好的工具。就我而言,就我参与的代码领域而言,它很小,足以在我的头脑中进行跟踪。

      3. 我很想探索这种替代方法,但我不确定如何确保在推送和部署提交后发现的任何错误/建议的更改都能真正得到执行。

      4. 我很喜欢这个想法!我并不需要检查每个开发人员是如何处理他们的工作的(虽然在某些情况下,这可能会成为一个有用的指导环节),但重要的是在投入生产之前,工作看起来是什么样的。

        我认为上述方法的主要困难在于,不同的变更会交错在主干中,可能很难只提取其中一个进行部署。但这就是功能标志的作用!

    3. 这个故事可能还不止这些。创建 MR 是一门技术,也可能是一门艺术,这样才能方便审核和批准。

      对 MR 的反馈也是如此。提供简洁明了的反馈意见能更快地解决问题。

      就像 “如果变更很难,那就重构,让变更变得简单”。做一件事有很多种方法,有的更好,有的不好。

      拥有良好审查文化的公司和团队都能成功地将审查作为一种工具。

    4. 这与我在代码审查方面的经验相去甚远,所以我想问一些问题来跟进您的经验。您是否介意发送电子邮件至 hn@xkqr.org

  35. 与大多数流程一样,代码审查的难题在于弄清它对团队和组织的影响。

    在一个庞大的组织中,成千上万的工程师每天都要承受数小时的中断和流程开销,而发布跑道上的官僚机构已经盖了六枚印章,在这种情况下,强制代码审查几乎没有什么坏处(它是在噪音中进行的),但回报却很不稳定(许多人只是在流程的重压下闷头工作)。组织不会因为强制要求而损失什么,但只有某些团队才会看到它的巨大价值。

    另一个极端是,一家拥有五名工程师的初创公司会积压大量的审查工作(审查工作会被缩短),因为每个人都面临着压力,要么要保持高生产率,要么要救火。评审也许可以抓住问题,定期分享关键知识,但组织却要为开销和中断付出明显的代价。

    人们渴望 “放之四海而皆准 “的规则,并为此撰写论文和发表研究报告,但现实中的正确做法往往更加特立独行。

    1. 我并不反对 “视情况而定 “的观点,但对我来说,在 “有五名工程师的初创公司 “中,代码审查通常效果更好,开销更低。我能就您在审查和接受审查方面的经验问您一些后续问题吗?如果可以,请给我发电子邮件:hn@xkqr.org!

  36. 根据我的经验,代码评审可以捕捉到很多错误。但是,如果您发现自己在审查中一次又一次地捕捉到同类错误,那么您就应该想办法自动捕捉这些错误,而不需要审查员参与(静态分析、测试、衬垫等)。

    1. 完全同意尽可能利用静态分析。当在代码评审中发现问题时,我的第一反应就是想:”我们是否可以通过某种 <lint 规则> 来捕捉到这个问题?

  37. 我认为这篇文章的观点是错误的。文章引用的统计数字是,15% 的评论是关于 bug 的,这似乎符合人们的预期,我认为只有当这个数字_高得多_或_低得多_时,才真正值得讨论。

    相反,我认为有两个更有趣的问题值得一问:

    1.代码审查发现缺陷的比率是否足以将代码审查用作缺陷的检测机制?

    经过近 20 年的软件编写工作,我确信答案是否定的。有些审查员比其他审查员更优秀,有些情况比其他情况更有利于发现缺陷,但一般来说,我们应该尝试构建这样的流程,即不假定缺陷会通过代码审查以相当高的比率被发现。当它起作用的时候是很好,但它并不是一种足够可靠的捕获错误的方法,不能成为流程中的负载部分。

    2.强制审查所有代码是否合理?

    这是我犹豫不决的问题。我认为,在一个代码评审优先级很高的环境中,人们接受过有效评审的培训,而且组织政治因素极少,那么允许公关作者决定是否进行评审通常会提高代码的质量和速度,因为代码会更快地发布,而且可以从评审中获益的代码仍然会被评审。在这种情况下,我认为我们会看到,当代码不需要审核时,代码的交付速度会更快,审核的质量也会更高,因为代码被标记为需要审核是一个积极的信号,会让我们更加关注。

    不幸的是,我可能是错的,而且这也不是任何人都愿意冒着声誉受损的风险去推动的实验,所以我怀疑我们不太可能看到规模足够大的实验来确定。如果我们会以某种方式失败,我宁愿失败的原因是代码审查太多,而不是不够。

  38. 错误很’容易’修复,我不担心找不到它们。我担心的是界面,因为所有的用户很快就会成为修改界面的噩梦。

    1. 我很想了解您在代码审查方面的更多经验。能否请您发送电子邮件至 hn@xkqr.org,以便我提出一些后续问题?

  39. 如果有了拼写检查器、代码格式化器和线程器,代码审查就会大大改善。这比手工操作或手工审查要好得多,代码审查可以用于更高层次的想法。

    1. 没错。代码评审不应该涉及代码格式或任何可以通过精简器、格式化器、代码覆盖率限制和静态分析自动完成的工作。如果构建的 PR 是绿色的,那么所有这些都是可以接受的。

  40. 请记住,我支持代码审查,但…

    在药物研究中有一个小把戏,就是用安慰剂来测试潜在的候选药物,从而得出一个似乎显示出益处的糟糕研究结果。之所以说这是个把戏,是因为在很多情况下,替代品不是安慰剂,而是现有的治疗方法。然后,医生会了解到一种更 “现代 “的治疗方法,因为它更现代而对它青睐有加,更好的治疗方法可能就不会被开出处方。

    代码审查的替代品并非无所作为。文章称,代码审查每 10 分钟就能发现一个缺陷–但仅限于前十分钟。根据同样的论点(忽略限定条件,推断数字结果),快速自动测试有可能在一秒钟内发现数千个缺陷–如果它们运行得那么快,而且缺陷已经被测试过的话。静态分析器、结对编程、文档编制这些都是可供选择的方法,还有很多其他方法。

    如果你每天花一个小时来审查代码,那么你就花了 12.5% 的时间来做这件事。这样做会带来机会成本,而根据您特定的组织和代码库,这种机会成本可能会用得更好。当然,把所有事情都分析得一清二楚也有机会成本,但不分析通常会导致目标转移,即做某件事的所谓理由不断变化。今天是为了发现缺陷,明天是为了知识共享,后天是为了安全。它就是所有这些事情,但其他做法可能会更有效地利用时间和人们的耐心来实现这些目标。

    那么,我为什么支持代码审查呢?因为选择作为一个团队进行互动和合作,了解你的同事并与他们达成妥协,这既是良好的团队建设,又能达到其他技术目的。我确实认为结对编程可以在更大程度上实现这一点,同时也会给个人带来更多负担。但前提是你必须控制并拥有这一过程,如果这只是一种生搬硬套的仪式,那么我的感觉是你可能并没有从中获得净收益:你只是因为别无选择才这样做,而不是因为你认为这是对时间的宝贵利用。如果你同时经历过两种文化,一种是人们选择代码审查并从中发现价值的文化,另一种是人们被迫不容置疑地进行代码审查的文化,那么你可能已经见证了一句箴言是如何毁掉一种做法的社会价值的。

  41. > 开发人员每周要花六个小时进行审核。这有点太多了

    调整审核时间非常困难。各种选项都缺乏吸引力。是在达到上限后开始盲目接受修改,还是干脆停止,不让别人合并代码?

    1. 为什么要阻止合并代码?一个人花了几个小时修改代码,却被另一个不分配时间审核的人阻止,这种想法让我很不理解。我们都是专业人士,让别人合并他们的修改,并确保你有时间审查它们。如果你无法审核,而他们仍然需要你的批准,那就批准吧。

      除非你不信任你的同事。如果是这样的话,那么代码审查无论如何都是注定要失败的。

  42. > 在一天中前 60 分钟的代码审查中,审查员大约每十分钟就能发现一个缺陷–只要他们每十分钟审查的代码少于 50 行。

    哦。

    我通常只需要几秒钟就能发现代码中的缺陷。

    我一直觉得这是评估软件的平均水平。如果每个缺陷的平均时间是十分钟,我就需要重新调整对自己的期望值了。

    1. 这确实取决于代码。要找到 CSS bug,是很容易。如果要找到支付集成中的逻辑漏洞,即有人遗漏了或应该实现但没有实现(例如 webhooks),那么这就需要更多时间,开发人员基本上必须坐下来好好研究一下到底应该实现什么/他们会如何开发,然后对照已经完成的工作进行交叉检查,否则你就无法轻易找到这些逻辑漏洞,而这些漏洞实际上就是 bug,只是不像缺少分号这样简单的代码 bug。

      1. 我的日常工作是审计密码学。我可能比大多数阅读 HN 的人更慢找到 CSS bug 的根源。

    2. 你应该明白,找到代码中的 bug 需要多长时间取决于代码。如果不明白,那么我希望你读过 Linux 和 SSL 等的代码。

      1. 是的,当然这在很大程度上取决于上下文。

        我从来没有阅读 Linux 内核代码的动力。我经常发现并披露密码学库的 bug,不过通常都是业余项目,比如 “我觉得如果有一个 GHASH 的 PHP 实现就好了 “之类的,而不是 OpenSSL。

  43. 当我是审核者时,我几乎会发现每一个非小规模的拉取请求都有问题。有时这些都是小问题,但我经常发现 bug 和边缘情况。

    我看到一些关于时间的评论。代码审查需要多长时间?我可以在几分钟内审核数百行代码。在我看来,审查代码比编写代码要容易得多,尤其是当您积累了丰富的经验之后。对于较大的工作,在整个过程中都要有人盯着。

    我遇到过很多开发人员,他们在写完代码后就认为代码可以正常工作。他们不会通过代码或人工 QA 进行测试。当利益相关者告诉他们代码不工作时,他们会表现得很惊讶。第一次就把工作做好。慢就是顺,顺就是快。

    1. 我总是惊讶地发现,我经常会收到这样的拉取请求:要么无法构建,要么单元测试失败,要么两者兼而有之。这些问题至少很容易解决,但当我认为某些代码可能难以维护、反模式或可能以不明显的方式出现错误时,我就会发现很难有效地解决这些问题,并经常最终怀疑自己的建议。

    2. 当我使用 Django 时,添加代码的人在自己的系统中运行代码。而对于 lambda(我们大多在云中部署和测试),人们往往会扔下代码就走。

  44. 这篇论文的标题有点挑衅,但我认为研究结果很有趣。主要是围绕开发人员长期以来认为的价值与实际情况的对比。

    不过,你提出的关于使用缺陷变化率的观点很有道理。我希望研究人员把它作为首选的测量单位。我对流行的开源项目的变更缺陷率做了一些研究,结果发现差异很大。从 ~12% 到 ~40% [1]。

    我希望看到的未来是,作为开发人员,我们使用客观的衡量标准来证明审查时间投资的合理性。随着代理开始不断提交小的错误修复单,这一点将变得越来越重要。

    [1] https://www.shepherdly.io/post/benchmarking-risk-quality-kpi

  45. 我还记得在合并 PR 之前需要获得批准的时代(我还记得在 PR 或任何广泛使用的版本控制系统之前的时代)。

    我一只手就能数出有多少次有人在我的代码中发现了本应停止部署的错误。我并不是没有部署过严重的错误,但这些错误几乎从未被审查我代码的人发现过。

    偶尔也会有人提出更好的方法,或者提出一个问题,最终让我想出更好的方法。但这种情况也很少见。而且我也想不出有多少次是值得在这个过程中花时间去做的。

    结对编程和协作可以带来巨大的益处,但我们所形成的 “最小努力、公关批准 “的文化却不能很好地替代这一点。

    1. 代码审查和结对编程如果有特定的目的,都会非常有用。

      让别人尽快熟悉不熟悉的代码,理清毛糙的代码,使其变得更加清晰,查找错误或发现未知的未知因素,如错误或不必要的复杂性。

      不过,在很多情况下,做这些事情时不看屏幕会更有帮助。在头脑中建立一个心智模型,然后互相启发往往更有帮助。与实际编码或阅读实际代码相比,在黑板上画出东西或在标记文件中写下东西,用简单的术语解释事情,会更有帮助。

      我不确定这算不算结对编程或代码审查,但这种自由讨论代码的方式非常有效。

    2. 我在审查中发现了错误,但更好的是,我要求进行测试,而这些测试也发现了错误。

      即使是低强度的代码审查也能发现缺失的 unittests

    3. 听起来你写的代码质量很高!从您的简介来看,我倾向于认为您知道自己在说什么。我想了解一下你在这里的工作经历。您是否介意发送电子邮件到 hn@xkqr.org,以便我提出一些后续问题?

  46. 代码审查有不同的层次。根据我的经验,基于网络的代码审查工具非常糟糕。任何跨越多个文件的几行以上的代码都需要 cscope 类型的工具。

    还有,审查的类型是什么?这是一个需要高水平设计审查的原型吗,这样实际审查就不会变成设计审查?这种审查多长时间进行一次?

    评审者是谁,流程是什么?关键利益相关者的影响力更大,你需要考虑评审者的经验、知识和可信度。

    最后,代码有多重要?是内核代码,还是需要竞赛条件和内存泄漏检查的高执行守护程序代码?您是否对代码进行了静态分析?代码是否能编译并实现其设计目标?单元测试日志在哪里?

    需要考虑的问题很多。

  47. 技术债务。尽量减少技术债务,在需要时,为其写一个任务,以便日后进行研究。

    编码标准。不要提交有多余行数的代码,这些代码会拖慢下一个开发人员的工作,使他们无法了解过去的代码是做什么的。

    最重要的是,确保覆盖边缘情况,通常是通过所有可能结果的真值表。

    我经常会在 PR 上评论说:”等等等等,但不阻塞”,所以我允许这样做,但至少我的意见是众所周知的,以防日后出现代码问题。

    我的公关需要很长的时间,因为我挖空心思。

  48. 我喜欢在发布 PR 的同时看到正在运行的软件。GitLab 有一个 “审查环境”(Review Environment)的概念,把我宠坏了。从特性分支部署的短暂、动态调配的环境,对工作效率的提升绝对是惊人的。

    它为公关提供了更多的背景信息。

  49. 我发现很多标准流程都可以用类似的方式来描述–如果你注意到它们能解决什么问题,它们应该会非常有用。诀窍在于一些重要但微妙的细节,比如不要连续花两个小时审核一份过长的公关。一旦这只是流程的一部分,就很容易忘记。

  50. 我不认为代码审查有什么好处。我从事网络开发已有 12 年,在大大小小的公司工作过。

    我认为应该有一个人工的质量保证流程来测试开发人员推送的功能。

    代码审查的问题在于,它总是要花费另一位开发人员大量的时间,而且许多开发人员都超级忙,所以他们只是快速审查一下 PR,然后就批准了,或者觉得自己必须添加一些注释。在开发人员已经在做的工作和必须到 PR 前进行适当审查之间切换上下文,意味着他们应该切换到该 Git 分支,下拉代码,测试所有代码,并检查静态代码审查不会发现的逻辑错误。

    对于初级开发人员来说,代码审查仍然有用,因为您可以发现质量不佳的代码,但对于高级开发人员来说,由于上述原因,代码审查就没有那么有用了,最好是有一个质量保证流程来发现逻辑漏洞,而不是期望开发人员投入那么多时间在上下文切换上。

    1. 这里的问题不是开发人员太忙,而是代码审查被认为是二等公民,而不是编写新代码。这就好比说 “许多开发人员都在忙着开发功能 A,所以他们只是为功能 B 编写了快速而肮脏的代码”。如果审查是功能生产流水线不可或缺的一部分,那么坐下来花一天时间审查代码应该不成问题。对于更大、更复杂的事情,可以进行几轮审查。

      编写第一份 PR 所需的时间与通过所有审核所需的时间之间存在近似的非线性关系。这段时间可以很可靠地计算出来并考虑在内。

    2. 不,自动化测试涵盖了基本功能。对于大多数 PR 而言,熟悉代码的高级人员不需要检查代码并手动测试任何东西,因为大多数时候 “代码审查 “并不是这样的。如果需要他们查看运行状态下的代码,那应该是 CI 流程的一部分,而不是开发人员的手动任务。

      一个好的审查员可以指出错误的编码战略决策或对需求的曲解。质量保证完全是另一层审查。

    3. 听到这个消息我有点吃惊。您能否给 hn@xkqr.org 发一封邮件,以便我提出一些后续问题?

  51. 我唯一不喜欢代码审查的地方就是吹毛求疵的评论。每个人都有自己编写代码的主观方式,如果我的代码足够好用和美观,那就随它去吧。

  52. 代码审查可以发现错误。

    更常见的情况是,代码审查成了团队成员争吵的机会。更糟糕的是,代码审查成为非团队成员对项目行使权力的机会。

    1. 在团队中骑车是件好事。如果你们都要给车棚刷漆,就颜色达成一致会有帮助。

      更广泛地说,代码审查是逐步获得或鼓励整个团队保持一致的绝佳机会。

      至于团队选择在哪些方面保持一致以及保持一致的力度有多大,这都由团队自己决定,所以希望他们不要在无关紧要的细节上纠缠不休,但在我看来,完全放弃这个加强各种凝聚力的非常廉价的机会将是一个很大的错误。

      1. 你对代码审查做了很多正面-反面的断言。我的观点是,消极行为的机会太多了。这与技术和生活中的一切都一样,”只要每个人都尽自己的一份力,就能保持良好的状态”。然而,大多数人并没有这样做。

        1. “大多数人都没有 “这种说法太夸张了。根据我的经验,核心审核无疑是好的。如果没有它,我绝不会经营或加入一家公司。

          我现在独自编写代码,代码审查可能是我最怀念的事情。

          1. > “大多数人不 “的说法太夸张了。

            我很乐意讲道理。我想我更多的感受是,大多数开发人员并不擅长识别何时应该克制。就像大多数开发人员都是糟糕透顶的面试官一样,我认为开发人员也忘记了代码审查归根结底也是人的工作。如果给普通开发人员最小的权力,又没有足够的防护措施,那么就会出现合理的愚蠢行为。

            > 我现在独自编写代码,代码审查可能是我最怀念的事情。

            我觉得 “代码审查 “在这次对话中的含义太多了。代码审查的形式是第二个(或更多)合格的开发人员为了更大的利益阅读和评论代码?显然是好的。在非 FAANG 公司以 github PR 的形式进行代码审查?跳过。袋鼠法庭。

          1. 高级团队成员通常是最严重的违规者。

    2. 代码审查可能是破坏绩效或占据主导地位的机会。我见过无数次这样的情况。

      在排名靠前的组织中,拖延对高绩效人员进行代码审查的阴谋屡见不鲜。

      如果不在团队中符合条件的审查员中轮换审查员角色,也会破坏代码审查,在这种情况下,一切都只代表特定群体的意见。

    3. 在我看来,通常是编写 bug 的人对代码审查如此反感。

  53. 我的问题是,人工审查员发现的 bug 比 ChatGPT 多吗?https://www.thatsoftwaredude.com/content/12848/chatgpt-can-d… 说它很平庸,但那是一年前的事了,老实说,平庸的代码审查似乎已经足够了。

  54. 要学习如何审核 PR,有哪些值得阅读的精彩博客/资源?

  55. 哈?代码审查 cuz 发现 bug…人们好像真的看到了…

  56. 消除错误需要持续、警惕、整体、重叠的方法:

    – 在接受提交之前进行代码审查(Facebook 就是这样做的)

    – 重构侥幸通过的垃圾代码

    – 删除功能

    – 使用更少代码的高阶语言

    – 消除技术债务

    – 吸引更多眼球

    – 更聪明的工程师

    – 投入更多时间改进工程设计

    – 编码指南既要优化简单明了的代码,又不能过于严格,以免妨碍战略性例外情况的出现

    – 将负 LoC 作为关键绩效指标

  57. 同意。在我的职业生涯中,我主要负责管理和审查代码。我发现了很多 bug,偶尔也会发现一些可能会导致中断或给用户带来显著问题的 bug。

    但我发现更多的是没有经过深思熟虑的代码。技术债务和代码气味是真实存在的,它们会影响团队的绩效。要将这些问题消灭在萌芽状态,就需要高质量的公关审查,并花时间与提交者就发现的问题进行沟通。

    在我现在工作的公司,我和我的团队已经将高质量的公关审查变成了常态。我强烈推荐!

    其中一个关键点是 “善意而非讨好”。在公共关系中留下评论时要乐于助人,但不要为了避免冲突而表现得和蔼可亲。

    此外,如果你觉得代码审查是浪费时间,我可以向你推荐我经常做的一件事–给予警告。对于类似的 PR,我会批准并就我希望在将来修正的地方给出评论。我不会因为一些小事而耽误合并,但同时我也不会让小事一直拖延下去。

    1. “技术债务和代码气味是真实存在的

      我认为最让我头疼的是,很多时候,”尽快发布 “是一个合理的商业理由,但缺少的是对附加条件的问责。比如,好吧,如果我们现在不想修复这个问题,因为它需要在下一个版本中出现,那么我们可以按原样合并它,但你不能把它记录在外部文档中,它不能成为 API 的一部分,而且在 X、Y 和 Z 被重写为与 ABC 一致之前,不能在这个方向上进行任何进一步的开发。

      我发现这类讨论很难得到认同。每个人都乐于微笑点头,相应的票据也会被归档并附上截止日期,但下一个版本发布后,新的业务影响因素就会成为重点,清理票据就会被悄悄移到积压票据中,截止日期也会被取消。

      多年来,这种情况一直在重复,让我对这个过程产生了一种愤世嫉俗的情绪,感觉代码审查至少在一定程度上是一种挫败感的表现;我没有足够的支持来坚持在前期做好代码审查工作,所以我实际上只是在预览一两年后会发生什么。

      1. 关于这个问题有几点看法。

        1.很多问题都是由于人少事多造成的。如果只有一两个开发人员,而积压的工作越来越多,那么问题并不在于你没有时间解决问题,而是你的人手不足。如果你有足够的人手,那么从业务的角度来看,就不会出现有人在完善之前的工作,而另一个人却在做下一件事的情况。

        2.如果你的人手不是不够,那么清理新代码的最佳时机就是在编写过程中或编写完成后。我喜欢用的一句话是 “趁记忆犹新”。这样既节省了时间,又不会增加新的错误,因为你不必再次记住所有内容,将所有上下文重新载入你的大脑。

        1. > 如果你不是人手不足

          值得注意的是,有一些脂肪是好事。当你是一家初创公司,你正试图自力更生时,我可以理解,但在某些时候,你需要一些脂肪。脂肪太多不好,但没有脂肪也不好。初创企业必须精益求精,但如果大企业过于精益求精,那就叫厌食症。

          1. 的确,如果你读过《目标》或《凤凰计划》,就会发现他们把这叫做 “懈怠”。关于 “松弛 “为什么重要,有一整套理论。

          2. 另一种观点认为,脂肪在人体内是有作用的。诚然,如果你要优化一个非常狭窄的结果,非常低(但不是无)脂肪的身体看起来很理想,但首先,这实际上是一个非常不健康的身体;其次,世界上最好的举重运动员实际上都有相当可观的脂肪储备来支持和维持他们的肌肉。

            没有脂肪有助于提高速度和效率,但会妨碍你变得强壮。

      2. 不过预览还是很有价值的,当你已经知道某样东西是怎么坏的时候,你就会显得像个魔法师。

        1. 但是,当你不断提醒人们注意同样的问题,却在几个月甚至几年后不断遇到这些问题时,你就会觉得自己像卡桑德拉。

          你只能把 “惊讶的皮卡丘 “这个备忘录发这么多次,它就会失去光泽。

        2. 或者是无能。如果你早知道会出问题,为什么还要批准?你唯一的辩解就是 “当时有很大的压力要发布 xyz”。这样的辩解并不值得同情。认为被破坏的功能是有史以来最重要的事情的动物精神早已不复存在,而对之前最重要的功能所造成的新的中断的挫败感已经占据了上风。

          1. 不要批准!这其实是你可以做的一件事。

        3. 很多时候,这比 “这显然会在某个时候以某种方式影响生产 “更微妙。问题更像是觉得逻辑太复杂,以后很难维护,或者觉得应该或不应该使用某个库,或者觉得用线程做的事情应该是异步的。

          所以是的,并不像 “我说过会发生,但它确实发生了 “那样简单明了,而更像是 “我有一种感觉,这将会是一种痛苦,而我确实在审查代表这种痛苦的代码”。

      3. “没有以后。”这是我的新口头禅。

        1. 这让我想起了代码库中遍布的 “Todos”……我喜欢用 “尤达 “来形容……做或不做,都没有 Todo。

          1. TODO 本身并不坏,但我认为意图很重要–有多大可能有人纯粹是为了解决这条评论而回到这里?如果不太可能,那么 TODO 将在未来重构的背景下被使用,在这种情况下,它就是给最终考虑这项工作的人的一份礼物,帮助他们理解代码或背景的某些内容,而你在项目中意识到这些内容时已经太晚了,无法对其采取行动。

        2. 我最喜欢与此相关的咒语:

          没有什么比暂时更永恒。

          … 和 …

          我们没有时间做对,但我们有时间做两遍。

    2. 我是一名新经理,正在努力让我的团队理解代码审查的价值。我已经经历了太多的重写和重写面条代码,现在我对代码审查更加挑剔,我正试图在我的团队中推广这种文化。您有什么建议吗?

      – 同样的人在别人的合并请求上留下了详细的评论,但当别人没有为他们的合并请求付出同样的努力时,他们就会感到气馁。

      – 人们盲目地接受建议,没有任何抵触情绪,也不进行任何讨论,只为完成审核。

      – 人们把 MR 发到侧频道或其他团队,让自己的修改在没有阻力或来回讨论的情况下被合并。(我曾不得不恢复过几次这样的修改)。

      1. 良好的公关文化肯定是要从头开始建立的,并且要得到自上而下的支持。在 Shopify,我认为他们拥有非常好的公关文化,我们有一些我认为有帮助的东西(除了良好的 CICD 和静态分析工具之外):

        1.公关应该等待 2 次验收,1 次验收即可发货,0 次验收即可紧急发货。我们的团队中应该有 2 名审核人员。

        2.根据代码项目的不同,我们必须填写 PR 的模板,其中包含哪些内容,有哪些改动,测试代码时需要注意什么,等等。

        3.某些领域的代码所有者可能需要特定团队的额外审核。

        4.我们应该在审查分支时对其进行检查和测试。因此,除少数情况外,我们真的不鼓励快速阅读和 LGTM。

        我见过很多地方盲目地接受公关,这很困难,因为如果不真正执行和鼓励这种文化,就很难改变。

        1. 此外,代码审查对于需要被审查的代码也同样有效。

          最糟糕的同行评审发生在成千上万行的 PR 上,因为没有人愿意读那么多,而且会有遗漏。我所见过的成功的代码评审是,人们将代码拆分成可评审的部分,而这些单个的评审是如此之快,以至于最终完成的速度比一份巨型公关还要快。

          1. 在不把任何东西分解成一堆更小的改动的情况下,把一个自成一体的改动合理地分解成最小的改动需要多少额外的时间?

            1. 大约 10-15 分钟 ….

                  git co master
                  git co my-branch -- .
                  git add -up . # select changes relevant to first pr
                  git commit
                  git reset HEAD --hard
                  # and again...
              1. 这个问题是专门针对这种方法行不通的情况提出的,例如,您的团队不想批准只包含死代码的 PR,或者因为变更的任何子集无法编译,或者没有其他部分就无法保留正确的行为。

                1. 拥有合适的工具有助于发布 “不完整 “的工作,例如功能标志,这样您就可以发布某个功能的非常轻量级且尚未准备好供最终用户使用的版本,并继续在较小的 PR 中对其进行迭代。

                  例如,第一次发布时添加了一个新的屏幕,但只转储了输出结果

                  第二个版本添加输入字段和控件

                  下一遍添加验证

                  然后添加动画

                  等等

                  1. 理论上听起来很不错,但实际上呢?

                    1.经常需要修改或重构旧代码。仅有功能标志是不够的。

                    2.即使是功能标志本身也可能是有风险的,可能会影响现有客户的使用。

                    大多数情况下,确实需要对旧代码进行修改,至少在我的经验中,确实没有那些完美的孤立的新功能。

                    1. 如果说重构应该被放在特性标志后面,*因为*它们是如此具有破坏性。

                  2. 在我看来,这是一种糟糕的方法,也是我讨厌如今使用特性标志的原因。

                    例如,如果没有输入验证(前端或后台),我是不会批准任何东西的。我不知道你是否真的会在删除 fflag 之前添加验证功能。”相信我兄弟 “对我不起作用。

                    1. 我的意思是,你可以在功能标志后面对已编写的功能进行验证,而暂缓验证尚未存在的功能。

                      功能标志并不意味着把孩子和洗澡水一起扔掉。

            2. 实践中的忒修斯之船。

              有点像。

              原子提交很难。

          2. 您认为这可以在 PR 的提交级别上实现吗?

            1. 如果每个提交都可以单独审查,那就可以了。

              主要问题在于人、

              1.不愿意阅读冗长的内容,从而导致审批速度减慢,因为没有人愿意去碰它

              2.无法有效审查长篇大论,更有可能漏掉一些内容。

        2. 我们也有这些问题,但通常人们把这些当作官僚主义障碍,并不真正执行这些步骤。例如,模板被忽视,审稿人不检查,只是 LGTM 就可以了。很少有人真正认真去看。

      2. 代码审查文化不会凭空产生。除非您有 CI/CD、测试、任务估算、回顾、事件后记等流程,否则您永远无法让人们相信这些流程是有用的。所以,就从这些开始吧。

        增加更多的流程总是会遭到反对,但如果团队成员都认为保持工作正常是首要任务,那么这些流程就会慢慢/自然而然地出现,因为团队会意识到,积极主动地投资这些流程将为他们节省时间。

      3. 这需要时间。

        对于不习惯代码审查的团队来说,一开始可能会觉得麻烦多于值得。很可能在最初的几个月里,麻烦会大于价值。坚持做下去,最终聪明的开发人员会发现 “如果我们无论如何都要做这件事,我们不妨找点有用的东西来说说”:)

        有几件事情可以做得更顺利:

        – 管理期望值。最初可能只是 “我们只是想在每次修改时多一双眼睛 “或 “了解其他团队成员在做什么”–即沟通第一,改进代码第二。

        – 设置工具,使流程顺畅。如果有人想一劳永逸地完成工作,那么对他们来说,使用你的官方审核流程应该比使用一些旁门左道更容易。一个恶毒的替代方案就是让使用旁门左道变得更难;)

        – 利用自动化。在 PR 上运行测试、分类器、静态检查器等,这样即使没有人留下有趣的评论,开发人员也能得到有用的东西。

        – 如果团队中的某些成员已经有了代码审查的经验,那就调整他们的工作量,让他们能做更多的审查工作。他们可以以身作则,有效地培训其他人。

        – 确保审核中的代码变更大小合理。鼓励尽早并经常提交变更以供审核。说 “这是我花了 3 个月开发的功能,周五就要提交,请审核 “不会让任何人高兴。

        – 让审查不再可怕。代码审查不仅仅是为了发现错误和缺陷,也要鼓励审查者说正面的话。

        1. 这是很好的建议,我觉得 “无论如何我们都必须这样做 “这句话更像是…… “所以我们不妨让自己轻松一点”……例如,写出能正常工作的代码,并通过测试和手动(如果需要)进行自我测试,这样审阅者就不必在实际运行代码时陷入困境(开始时可以添加屏幕截图,但到后来就不需要了)。尽可能减少公关,也就是一个功能卡的多个公关接踵而至,尽快提交有价值的公关,不要因为吹毛求疵而阻拦,而是在共同的期望中开始就更好的事情达成一致,并在下一次修改中实现。

          一般的口号是 “如果它能运行,就不应该被阻止”,开发人员可以选择当场改进可维护性,也可以自行决定推迟到下一次或以后的 PR。毕竟你们彼此信任。

        2. > 设置工具,使流程顺畅。

          > 利用自动化。运行 […]流水线、静态检查器 […]。

          除非你将它们设置为只给出警告而不是阻止构建/合并,否则它们并不能使流程顺畅。无论如何,它们都可能被忽略。

          我认为,在得到团队认可之前,应避免使用内衬程序等。

          1. 这要看情况。如果你的代码库中已经没有林特警告,那么添加阻塞检查以防止出现新的林特警告就没什么大不了的。但如果阻塞检查意味着每个人都必须放弃一切,花一周的时间来修复代码,这当然就不顺利了。

            PS.另外,无论您设置了什么自动阻塞,手动覆盖都是个好主意。大多数流水线都已具备这一功能。

        3. > 一个恶毒的替代方法是增加使用侧信道的难度

          如果人们在寻求旁门左道,这就是一个信号。忽视这一点,忽视人们正在想方设法有效地完成自己的工作,我认为似乎没有抓住重点。

          > 如果一些团队成员已经有了代码评审的经验,那么调整他们的工作量,让他们可以做更多的评审。他们正在以身作则,有效地培训其他人。

          这可能会适得其反。突然之间,只有少数(可能只有一两个)团队成员在做所有的代码评审。他们感受到了压力,不想成为出货的阻塞部分,因此他们的审查工作就草草了事。他们会在其他前辈的意见上盖上 LGTM 的橡皮图章,并可能在第二天才审查其他审查意见。他们很难完成自己的工作,每天 2 个小时的代码审核工作影响巨大(如果审核其他 2 名开发人员的工作,而他们在一天内 6、8、10 个小时都在编写代码,那么第二天就需要 2 个小时来审核他们的工作)。

          > – 确保审核中的代码变更大小合理。鼓励尽早并经常提交修改以供审核。说 “这是我花了 3 个月编写的功能,周五就要提交,请审核 “不会让任何人高兴。

          反过来说,”嘿,请尽快审核,这样我就能在接下来的两个小时内再给你一系列 4 个修改,最后再发送更新来完成这件事”。

      4. 我写了一些我在团队中成功应用的规则。https://max.engineer/mindful-code-reviews

      5. 文化是创造出来的,不是偶然的。

        我会在小组会议上提出所有这些问题,甚至更多。尽量让大家了解审核给提交者和审核者带来的各种好处–让他们说出自己想要或可能得到的好处。讨论各种类型的意见(明确的错误、性能、风格、健壮性、因素和组织等),以及从不须采取行动到小毛病再到阻碍的各种优先级。讨论审核本身的优先级。减少审核的延迟会产生巨大的积极影响。

        1. 人都是聪明的–听听他们的担忧如何?在用一系列 “最佳实践 “和 “预期结果 “来打击他们之前,先听听他们的意见吧。

          我开始认为,在代码审查中,挑毛病完全会适得其反。

          自从我了解了 “Ship/Show/Ask “之后,我对代码审查的看法发生了翻天覆地的变化:https://martinfowler.com/articles/ship-show-ask.html;我不再相信审查每一个改动都是健康的,看到其他模式的不同之处,我就知道它现在是有害的。在我看来,另一种好方法是允许合并后审查,”ship/show/ask “更好,但为什么一定要在合并前进行代码审查呢?

      6. 社会氛围如何?

        我这么问是因为我有一份工作,在 COVID 之前,技术团队只有几个呆头呆脑的程序员在一间办公室里,而在 COVID 之后,技术团队只有一群我不在其中的朋友。

        我的意思是,在 COVID 之前,创始人经常会带我们出去吃午饭或打网球,就像正式的团队建设时间一样。我很喜欢这样做,因为我很挑食,很难交到朋友,所以如果公司有正式的活动,我就更容易融入其中。

        在 COVID 之后,官方活动的力度减弱了。团队太大,无法带所有人出去玩,我也没有加入那些自然而然找到社交方式的朋友圈。

        在新的环境中,我不再觉得自己是团队中平等的一员,我觉得自己就像一个局外人,拥有纸面上的权力,却没有完成工作和度过工作日所需的任何友情。

        尽管每个人都一再表示,我作为最资深的程序员受到了尊重和重视,但我发现在新的环境中,我不可能成为一个好队友,我觉得自己整天都在刻薄,没有人把我当人看。这就是我辞职的部分原因。

        在那样的环境中,我的代码审查很糟糕。

        现在,我在一家远程公司工作,在那里,我再次感觉到每个人都同样不合群。如果他们有了办公室,我可能会套现,然后去度假一年。

        编辑:差点忘了,原来那个 “书呆子程序员 “团队中的另一位女成员,也在我辞职的同时倦怠了。她在新环境中也没交到什么朋友,似乎更乐于追求自己的兴趣爱好,在工作间隙过得轻松自在。

        1. 大三学生能和大四学生做朋友吗?我觉得这是一种 “教授-学生”/”私人-中尉 “的关系。

          我在代码评审中也整天刻薄,而且和团队中的大多数人相比,我还是个相对低年级的学生!>:]他们不把我当人看,因为我不是人。我没有他们的人类情感和关切。我只关心代码。不过,感觉上他们还是喜欢和尊重我的!

          1. 我想我不喜欢成为唯一的中尉吧?

            感觉我的权力只停留在纸面上,却没有落到实处。一切都井井有条,没有人把任何事情写下来……

      7. > 同样的人在别人的合并请求上留下了详细的评论,但当别人没有为他们的合并请求付出同样的努力时,他们就会感到气馁。

        这种情况总是岌岌可危。因为一旦这些人变得颓废,你创造良好公关文化的能力也会随之消失。他们厌倦的原因有很多。如果这些人没有得到明示或暗示的重视,他们就会知道。如果做错事的人先得到晋升(甚至以同样的速度晋升!)、同样的加薪/奖金,而且在所有方面都一视同仁,那么员工几乎总是会得出这样的结论:”如果这对我没有任何好处,我为什么要付出这些额外的努力呢?我不认为提前晋升或类似的承诺会有好的效果,因为有很多员工都得到过这样的承诺,但却没有兑现[0]。因此,在短期内需要有一些奖励,哪怕是微不足道的奖励。

        此外,不要低估明确说 “干得好 “的价值。在沟通中,往往存在着一种巨大的偏见,即只有在出错的时候才会说 “做得好”,而在做得好的时候却不说。你不必事事都说 “干得好”,但我想你会惊讶于有多少人从未从管理层那里听到过这句话。

        [0] 我想和大家分享一个我遇到的故事。我是一名绿色(机械)工程师,在一家初创公司工作。我拥有物理学学位,而不是机械工程学位,但我一直都是动手能力很强的人。但正因为如此,我的薪水较低,也不被重视。我问我的经理,我需要做些什么才能得到晋升,与其他人平起平坐。我把它写成了书面材料,这样我就可以参考了。在下一次绩效考核时,我被说得一无是处。抱怨我没有做到这一点或那一点(有时是不可能做到的事情,有时则很奇怪,比如 “你的代码可能快了 20%,但 X 无法理解它,所以我们不能使用它”–X 是一位只用 C++ 写了不到一年的经理,而我__大量__记录了我对函数的使用)。我询问了我所做的事情和承诺。他们承认我做了所有这些事,甚至更多。其中之一就是拿到了一份合同(我想他们把合同写在这里并不是指望我能拿到),我是唯一一个拿到合同的非经理人,为公司带来了 20% 的收入,同时我也是那个项目上的唯一一个人。你可以想象,我从那次会议上走出来时,我的简历已经被擦得锃亮,从那时起,我就成了朝九晚五的上班族,做着最基本的工作。但我的下一任经理对我赞赏有加,会批评而不是抱怨。他理解我的工作存在未知数,当我加班时,他会让我回家。我一生中从未如此努力地工作过,这也是我最快乐的时光。一个经理可以成就一个员工,也可以毁掉一个员工。这其中的一部分原因是,也许有办法让那些崩溃的员工重新振作起来,但你可能需要先弄清楚他们为什么会崩溃。以及这是否是你能解决的问题。我相信环境对员工的态度有很大的影响,进而影响效率/生产力。如果激情能抵得上 10 点智商,那么快乐至少是让员工高效工作的一个重要因素。每个人都能赢,因为这不是一个零和游戏。

      8. 与人交谈,好奇他们为什么不重视代码审查。

      9. 请继续努力提交 PR!垃圾代码属于垃圾。

        1. 大量垃圾代码正在为所有大型科技公司赚取数十亿美元。亚马逊、Facebook 等公司的大部分代码都是垃圾代码。更不用说那些 “自负盈亏 “的小公司了,它们的代码都是创始人级别的,而且还处于不断 “修复和扩展 “的阶段。

          更重要的是,当一个人致力于某件事情,然后它被称为垃圾时,会形成一种什么样的文化?另一方面,如果有人审视了自己的进展速度,并做出了一个战术性决定:也许某件事情还不错,虽然不是很好,但已经很不错了–他们会把节省下来的时间花在完成项目上;然后,当评审者认为公关是 “垃圾 “时,又会发生什么呢?

          我还认识到,我需要更加有意识地让各种火苗燃烧起来。不可能事事顺心,有时简单低质才是最好的。

      10. 多年前,我有一个老板,他在一瞬间朝我扔了一把椅子。(这可没听起来那么夸张)。

        如果能再为他工作一次,我一定会心甘情愿。因为他虽然会对我大吼大叫或训斥我,但他也愿意给我好的建议,提升我,教导我。

        办公室不是一个安全的空间。你似乎知道哪里出了问题,我肯定你已经很客气地问过了。我相信你提供了胡萝卜,但你的团队知道你有大棒吗?

        > 同样的人在别人的合并请求上留下了详细的评论

        当众表扬这些人做得好。告诉大家,他们设定了标准,而其他人没有达到。

        > 人们盲目接受建议

        辅导,大量的一对一辅导,让他们找到并发出自己的声音。大量的 “团队建设”,让强势与弱势的声音平分秋色。找出那些沉默寡言的人的长处,并围绕这些长处开展有趣的活动。让他们找到…

        > 人们将他们的 MR 发送到侧频道或其他团队

        坚持。措辞严厉的电子邮件。当众贬低。明确告诉团队 “这是不可接受的行为”。

        至于那个扔椅子的人…他总是很公平,总是把团队放在第一位,在他手下工作,我作为一个人、一个经理和一个工程师都得到了成长。在我拿到工资支票的同时,这不是成长的快乐幸运的好时光,而是成长的痛苦,将这种(痛苦)传播开来是你工作的一部分。

        1. 至于躲避投射物:是的,办公室应该是一个安全的空间,如果有人朝我扔椅子,我们中的一个第二天就不会在那里工作了。(加上 “也许他们扔椅子是为了让你躲避从你身后爬过来的忍者 “的正常说明)。

          1. 这把 “椅子 “上有 3 个衣架和 2 个飞盘……我不知道它是怎么把人举起来的。

            那 “扔 “更像是推了一下,那东西就朝我飞过来了。

            那把椅子唯一会伤害的就是我的感情。

            这可比我坐在装运弹药的办公室里可怕多了。

            1. 我很震惊,很震惊,你居然只是为了表达自己的观点而对自己的经历撒谎。有一次,我和一个谎称曾向人扔椅子的人共事,结果发现他是个被通缉的连环杀手,公司差点破产。当然,这一切都不是真的,但如果是真的,那也是我拒绝与这样的人共事的有力佐证!

            2. 你真有勇气,做了一份可怕的工作,不是为了保护其他人过上艰苦的生活,而是为了能在公告板上对他们挑刺。也许我也该这么做

        2. > 办公室不是安全空间。

          它他妈的应该是一个安全的空间,在那里我不会被我的老板向我投掷大型射弹。

        3. 有些工作文化太不利于冲突了。我认为这当然与个人性格有关,但我想归纳为西海岸人不利于冲突。在这些例子中,你可以在 Linked-In 上找到所有的拉拉队,一切都棒极了,发货速度超快,松鼠

          在这些情况下,我发现冲突被掩盖了,而不是以冷静和理解的方式解决。如果没有后者作为范例,大家就会为了和睦相处而互相攻击,同时也就没有了解决分歧的机制。突然之间,在评审中,你就成了拖延时间的 “那个人”,而评审者和被评审者都没有一个健康的文化来讨论问题。

          很抱歉我说了这么多,我认为降权是对一些团队可以有健康的冲突并通过冲突解决问题的震惊的反应–有时它可能看起来像吼叫(通常吼叫就是吼叫,但当一个团队与另一个团队是真正的朋友时,他们会有自己独特的方式来解决冲突)。

    3. 从未意识到这是一个有争议的话题。是否有聪明人认为不需要代码审查?反对代码审查的最佳理由是什么?

      1. 我曾与一位首席技术官交谈过,他反对代码审查,因为代码审查增加了太多开销,部分原因是代码审查在流程中太迟了。

        他鼓励他的团队事先讨论一种方法,或者一起研究一些东西。

        除此之外,他们还有大量的测试和结构非常严谨的代码库,我想这对他们来说是行之有效的。

      2. 我曾在一个团队工作过,该团队不做评审,因为包括尖峰、研究等在内的所有工作都是由两名工程师结对完成的。这是远程的,整天都有摄像头。

        我觉得这让人筋疲力尽。因为配对过程占用了我大量的认知带宽,所以我的工作能力达到了 100%,但产出却只有 50%。

        1. 我参加过全职配对团队,但发现吞吐量提高了 2-5 倍,因为会议、代码审查和上网的次数减少了。这让我很疲惫,因为突然间我每天要写 7 个多小时的代码,这真的很难。

          我参加过的其他团队在没有配对的情况下,每天最多也就写 3 个小时的代码。其余时间都被其他交流渠道占用了。

      3. 我想我大概做过 1000 到 2000 次代码审查。从那以后,我对代码审查的看法发生了翻天覆地的变化。我可以列出一个长长的清单(抱歉,有点冗长……):

        CR 拖慢了工作进度,而且往往是不必要的。耗时过长

        不必要的解释浪费时间。

        当评审员只有一两个人时,有点不可能。如果审核员人数较多,可能就不需要上下文了。

        造成不发货的偏见。”等待 CR “可能会严重阻碍产品的发布。也许,今晚是你把东西放到 prod 中的好时机,而不是明天–但你正在等待 CR。

        这是流程重于人的一个例子(又名:货物崇拜)。何时/何地/如何/为何进行客户关系管理是很重要的,也是因地制宜的。在不同的情况下,客户关系管理的最佳实践会产生不同的结果。通常情况下,客户关系管理只是因为它是一种最佳做法而盲目进行。最好是深入思考什么是重要的以及为什么–而不仅仅是 “哦,对了,这是另一个我们要通过的障碍,因为 #亚马逊做到了”。

        团队分层。在审核过程中,资深/精英/受宠的人总是比较容易过关。

        CR 可能会变得政治化。Scrum 主理人和经理们争先恐后地为团队成员解围,让他们对某些事情进行审核。这对于那一次来说是件好事,但除此之外就会暴露出一个完全崩溃的流程。当 CR 被 “升级 “时,审查员有多大可能真的会花费必要的时间和来回奔波来 “正确 “地审查事情呢?

        这就容易产生 “小毛病”,而 “小毛病 “是无用的,会适得其反。花在小毛病上的时间是一种浪费,而且会耗费精力,因为要不断地回头去看某件事情,然后再去调整 “它还不够好吗”?

        没有背景的随意审查

        在审查过程中达成一致意见是很困难的。不是每个人都能观察/体验和/或解决冲突。

        CR 在代码开发过程中出现得较晚;这是最糟糕的时候之一,因为在某些东西已经完成、打磨、测试并为生产做好准备之后,突然有人认为应该以不同的方式来完成(当某些东西已经完成并开始工作时,这就更容易看出来了)。这就好比写了三次代码,一次是为了把它写对,第二次是为了把它写好,第三次则是为了满足审查员的任何要求。

        这表明对团队缺乏信任。这是把关。

        不能很好地扩展。曾经有一位审核员告诉我,我写代码的速度比他们读代码的速度还快。(当时,我每天审核大约 6 份公关报告,并发出大约 3 份。我负责 80% 的审核工作,这简直是一场灾难;我收到的审核既慢又无用–团队成员都在努力交付他们捉襟见肘的项目;我太紧张了,既无法提供适当的反馈,又不能每周工作 100 个小时)。

        还有更好的选择,即 “运送/展示/询问 “策略: https://martinfowler.com/articles/ship-show-ask.html

        后一种分支策略由代码作者决定:”这个注释中的错字修复需要审核吗?这段代码中的修正是我最初编写的,我对它了如指掌–真的需要阻塞审查吗?在最后一种情况下,如果一个人可以立即合并一堆前导重构,那么他就可以把这个问题解决掉–这样他送审的 PR 就会变得干净而有趣;而且也不会耽误管理分支或纠缠别人的时间。

        让事情变得更好的第二个方法是允许 “合并后 “审查。在我所在的几个团队中,我们已经做了很多这样的工作,因此我们知道了什么样的东西适合单独发布。在另一种程度上,我们没有足够的带宽来审查所有的东西。这并不是坏事。

        1. 这是一堆缺点,但我想我要问的是,是否有聪明人认为,考虑到这些替代方案,总的来说,还是不做为好?你似乎很反对–你会提出什么具体的替代方案,结果可能是什么?

          1. 就像没有一个最有力的 “赞成论据 “一样,”反对论据 “也是如此–>背景比 “最佳做法 “更重要。

            我注意到

            > 还有更好的选择,即 “运送/展示/询问 “策略: https://martinfowler.com/articles/ship-show-ask.html

            说到底,这就像敏捷和 Scrum。实际上,你必须认真思考你的环境,不能只是去套用一个模板式的一刀切解决方案。(最近我肩上的担子很重,因为我觉得 IT 界有太多的人不愿意认真思考他们的背景。太多了:”我想让我的团队’快马加鞭!'”。他们的口头禅是:只要做好站立、做好复古、做好代码审查、做好计划、添加 checkstyle(一种代码语法筛选器)–一切都会很顺利!我现在学会了问–但项目是否及时完成了?在这种情况下,这些项目中是否有任何一项是真正有用的?如果有用,请告诉我具体原因并提供详细信息。我还了解到,如果一个团队远在石器时代,试图采用所有最佳实践的时间很可能比该团队和/或公司的剩余寿命还要长。这就意味着,他们除了在流程变更上喋喋不休之外,不会再做任何有用的事情。这又让我想起了公司责任,有多少公司责任是真正有用的呢?有些 CR 肯定是有用的。不过,一个团队怎么可能花更多的时间去做有用的公关,而花更少的时间去做无用的公关呢?更重要的是,每个 CR 都是一项阻塞性活动,如果我们为了一项通常无用的活动而阻塞开发,那就有问题了。替代方案不一定是完全放弃 CR,我已经提到了两个:”ship/show/ask “和合并后审查(review)。

    4. > “亲切,而非友善

      在加入一个团队时,我对开发人员说的第一句话总是:”我不在乎你有多挑剔,只要诚实就好。”我认为尽早设定期望非常关键。我认为,让开发人员不觉得自己的代码受到攻击或过于自卫是一个很好的进步。在我看来,强烈捍卫自己代码的人是糟糕的开发者。

      1. 我有一个同事,他花了更多的时间为自己的代码辩护,给出一系列错误的原因,而不是真正地修复它们。这种情况已经不止一次了。

        我只是继续工作。总有一天他会意识到他的代码有多糟糕。

      2. 听起来很激进坦率,我喜欢

    5. 这些警告该如何措辞?”下次……”?我很难认真对待自己的警告,如果现在已经足够好的话。

      1. 我们会在评论前加上 “minor:”,所有员工都知道,这意味着这是一件很好但没有必要合并的事情

      2. 使用删除键。(对不起,我说的是玩笑话,但我是认真的,根本不要发送这类评论意见)。

        如果暂时没问题,那就没问题。如果不好,那就说出来。

        如果你确实有这样的顾虑,”暂时没问题”–那是线下谈话的内容,不属于 CR 的范畴。这也是检验一条意见有多重要的试金石。你会安排 15 分钟的会议与同事讨论这个问题吗?如果不会,那为什么可以在公约与建议委员会会议期间这样做呢?

      3. “这暂时没问题,但我们应该考虑一下如何序列化这些对象。请随时在后续版本中删除 N^2 算法。”

        1. 这在你们都是同一家公司的员工,而且彼此尊重的情况下非常有效,但在开源世界中往往行不通,人们就这样消失了,你再也不会听到他们的消息。他们有可能会进行后续跟踪,但根据我的经验,这种情况很少见。

          1. 是的,即使是在公司内部,我接受修改的门槛也会因我的经验和与作者的关系而有很大不同。对于外部贡献者或从未与我合作过的人(通过审核代码或让人审核我的代码),我不会接受代码,直到几乎所有的工作都让我满意为止。而对于经常与我合作的人,我在接受一项修改时往往会加上这样的评论:”这一切都很好,但您需要考虑到 X,这将改变这个补丁中的几乎所有内容”(我说得有点夸张,但只是稍微夸张)。我知道一个更新是否会有问题,是否有必要再看一遍。有时,有几种显而易见的方法可以完成某件事情,他们会选择其中一种,但如果我有理由选择另一种,我就会选择另一种,因为我有理由。

            大多数情况介于两者之间。

            虽然在某些方面,这恰恰相反。对于一个陌生的开源贡献者,我需要确信他的改动是值得的。我会在文体方面放宽要求,我会直接使用他们的补丁,之后再进行修复。如果是我合作过很多次的人(不管是熟悉的贡献者还是同事),我会相信他们对改动的基本质量的意见,但对不必要的风格差异则不那么宽容,因为他们应该已经在这些方面达成了一致,如果他们漏掉了什么,更有可能是疏忽。(另外,鉴于超过 90% 的补丁将来自普通贡献者,我不想在事后修正他们的修改)。

          2. 另外,”时不我待 “是真的。跟进很少发生,跟踪起来很麻烦。让某个人为此负责是不公平的,尤其是如果他们不同意后续行动的话(想必他们是不同意的,否则他们一开始就会做这件事)。

    6. >围绕你发现的问题与提交者会面的时间。

      什么!如果有人安排与我会面讨论公关问题,我会气疯的。我们已经有太多会议要开了,这是唯一可以幸免于难的流程之一。

      1. 我也是,我真的很不喜欢这样的会议,本来可以在 slack 或公关中问我三四个问题,然后等我十五分钟左右再回答。

      2. 会议不需要太正式,也不需要太长。我个人很喜欢公关会议,在会上我们可以探讨代码并理解它,而不是有人在午餐时间把 2000 行代码倒在我的腿上,然后希望在晚饭前把他们的意大利面搅拌均匀

      3. 生气?开会讨论工作?有些人在懒人空间等地方发表的评论听起来比原意更糟糕,而人们也意识到了这一点,所以有时会不遗余力地以原意的方式表达出来。

      4. 说白了,如果提交者想讨论问题,我就会安排时间见面。我并不要求每份公文都要见面。我会根据需要与提交者会面,但频率很低,因为提交者需要尽快熟悉情况。

      5. “当面 “审核是我认为最好的审核方式。如果一份 CR 会有十几条关于所有事情的评论,那么异步审查就是一场灾难–作者会觉得自己受到了攻击。解决冲突和分歧的对话可能不会有好结果。

        就我个人而言,如果团队不习惯当面解决冲突,我喜欢从当面解决冲突开始。只有在建立了健康的关系和冲突解决机制之后,才会进行异步公关。我还喜欢这样一条规则,即在一次 CR 中,通信往返不应超过 2 次,否则应同时进行。

        在很多环境下,推迟小的改动以允许这样的往返时间是不可行的。要做的事情太多了。不值得。当项目失败时,很少会有经理给项目贴上一个大大的 “失败 “标签。我提出这个问题是想说,项目失败总是因为团队进展太慢,而个人往往不知道他们实际上需要更快的进展(反馈回路往往缺失,”哦,我们实际上太慢了,我们需要比实际更快的发货速度。JIRA、计划、估算、CR、最佳实践、修复衬垫所花费的时间–这一切都不重要,因为这个项目实际上失败了–它花的时间太长了。)

  58. 我认为这真的很重要,因为它比 “代码审查 “更重要。它确实说明了人们对统计数据[0]的误解有多深。但人们之所以 “相信”,是因为他们讨厌代码审查,而不是因为他们 “真的 “相信审查结果。

    但统计数据是很棘手的。以文章中举的例子 “15% 的吸烟者会得肺癌 “与 “80% 的肺癌患者吸烟 “相比。这两者并不矛盾,只是看待同一事物的不同方式而已。事实上,人们往往就是这样用统计数据误导你(或者说你可能无意中误导了自己!)。

    另一个有名的例子是时不时出现在 HN 上的:”尽管只有 5.8% 的销售额,但超过 38% 的错误报告来自 Linux 社区”[1]。简而言之,这个例子讲述的是 Linux 用户在提交错误报告方面受过更多训练,而且大多数错误并不针对特定系统。因此,如果只根据提交者的架构来对错误进行分类,实际上会错过很多有价值的信息。由于统计学的工作原理,如果架构依赖率甚至低至 50%(我会很惊讶的!),那么仍然会有大量有用的错误报告。作为一名 Linux 用户,我见过这类 bug,它们并不少见。但我经常看到,因为我是从 linux 系统报告的,所以它们就被驳回了。更有甚者,支持人员会将你发送到他们的页面,要求你为某个 “功能 “或错误问题 “点赞”。你必须先登录。我无法认真对待这样的公司,但该死的是,Spotify 也这样对我,我还把出错的那行代码发给了他们。Netflix 也这样对我说,”我们不屏蔽 Firefox”,但切换用户代理后我就能访问了。有时候,我们的思考不能只停留在表面。

    所以,我想说的是,这里有一个可以抽象出来的普遍教训。

    [0] 大家都开玩笑说统计数字是编出来的,但这同样不好。

    [1] https://news.ycombinator.com/item?id=38392931

    1. > 支持 “会将您发送到他们的页面,要求您为 “功能 “或错误问题 “向上投票”。

      微软为企业产品提供这种服务,客户可能每月支付 10 万美元甚至数百万美元。

      “我们听到了,但你的抱怨还不够流行,所以请走开。”

      “当然,这是一个灾难性的数据丢失漏洞,吃掉了你的财务交易,但如果其他人无法识别他们看似无关的崩溃是完全相同的问题,那么你就没有修复的机会。”

      “既然你在一个名为’Consiser尽职尽责’的问题上获得了一万张选票,我们决定通过删除错误论坛来改善你的体验,并从头开始建立一个新的论坛,减少不爽用户的尖刻评论。”

      1. 我所在的公司/团队对错误和功能请求的处理流程截然不同。如果客户开了一张单子,而我们确定它是一个错误,我们一般会在报告的版本中或之后修复它(除非它是一个安全漏洞或其他重大问题)。但对于功能请求,我们只是告诉他们将其提交给社区,然后我们会评估它是否有效,考虑到我们的其他工作,我们可能会实施它,但不一定会很快实施。

        1. 有时,功能请求实际上是一个错误,可以说明我们没有正确理解设计。

          但我认为,如何理解用户的功能请求非常重要。他们有一种挫败感,你可能没有意识到,但他们并不知道所有的代码和限制。这甚至可能是设计方面的问题,但这仍然很重要。很多时候,有一种方法可以解决用户明确要求之外的功能请求。但要做到这一点,你必须仔细阅读字里行间的内容。当然,有些人在这方面完全走错了路,他们认为苹果公司知道什么对用户最好。这完全是一种难以取得的平衡,但我认为,将其简单化是很常见的。

          有人开玩笑说,用户是傻瓜,也许他们是傻瓜,但这并不意味着他们面临的问题是傻瓜。当一个人拉一扇写着 “推 “的门时,他并不总是哑巴,因为实际上可能是标志和设计表达了不同的意思[0]。就我个人而言,我喜欢用户提出解决问题的方法。我可能会把它扔进垃圾桶,但它往往能给我提供更好的上下文线索,让我知道他们想问什么,而且如果他们认真思考了这个问题,也确实告诉了我他们对产品的关心。他们只是没有我这样的视角,没关系。

          [0] https://www.youtube.com/watch?v=yY96hTb8WgI

          1. > 有时功能请求实际上是错误

            两个缺失的功能加起来可能就是一个错误。例如,我曾使用过同一供应商的两款云产品,其中 CDN 产品缺少的后端 HTTP 功能与 PaaS 服务缺少的 HTTP 前端功能相互影响,导致这两款 “天然契合 “的产品实际上无法结合使用。

            这使得许多本应可行的架构无法实现,迫使客户采用扭曲的设计模式或第三方产品。

            在我看来,这是一个错误(”无法使用你们的产品”),但每个团队都将其单独标记为缺失功能,然后他们在大约三年的时间里都忽略了这一点。

            另外:没有足够多的人投票支持缺失功能,因为没有足够多的人使用产品……因为他们不能。

            我知道这有点离题,但这又回到了博客原文中 “统计很难 “的引言。依靠你并不完全了解的统计数据,你可能会犯下灾难性的商业错误,比如这个 “你不会因为产品无法使用而收到很多投诉 “的例子。

            然而,对于可用的产品,你会收到很多投诉……他们有用户投诉。

            https://en.wikipedia.org/wiki/Survivorship_bias

            1. > 因为没有足够的人使用这些产品……因为他们做不到。

              我认为这完全没有跑题。我认为这是明确的主题,至少是基本主题。不只是统计很难,测量事物也很难,确定因果关系更是难上加难。这通常是统计学和数据科学的根本目标。找出事情发生的原因。测量非常困难,而人们往往认为测量很简单。问题是,无论你测量的是什么,实际上都是一种替代,都具有不确定性。如果你不能很好地理解衡量标准的含义,你往往就不知道这些不确定性。付出艰辛的努力总会有回报,但不幸的是,如果不付出艰辛的努力,就可能要花费一些时间才能使接缝开始裂开。我认为这种不对称往往是人们马虎的原因。

              1. 我喜欢用的例子是 COVID 统计数据引起的混乱,以及人们是如何误解这些数据的。

                例如,新闻中经常报道的每日感染(或死亡)率实际上是:感染率 * 测量精度 * 测量率。

                如果有更多的人接受检测,”比率 “就会上升。

                如果 PCR 检测得到改善,”比率 “就会上升。

                类似的情况也适用于住院和死亡人数。上升的原因可能是某种菌株比另一种菌株更致命,也可能是更多的人感染了同一种菌株,还可能是更多的死亡归因于 COVID 而不是其他原因。

                不同的国家有不同的报告标准,或者报告标准随着时间的推移因环境而改变,这都无济于事!

                等等……

                这很复杂!

      2. 你是说他们不再审查错误报告,不再试图让你相信他们的软件是无懈可击的?

        与我与他们打交道的时候相比,这已经是巨大的进步了。

        1. > 不要审查错误报告

          他们确实会这样做,但即使是礼貌但脾气暴躁的评论最终也会累积到看起来很糟糕的地步。这些评论是公开的–这就是关键所在–因此隐藏它们的唯一办法就是删除它们。通常这种做法会让用户更加不满,所以 “窍门 “就是把整个论坛扔在地上,换一个新软件重新开始,以此来 “改善 “服务。这并不是因为它在任何方面都更好,而是因为它隐含着从 “BUGS “中删除*的意思。

          微软现在已经是……第三个论坛了?我都数不清了。

    2. 基本上,代码审查也会发现很多其他非错误的东西(可能是小毛病和风格问题)。

      这就是为什么看百分比是危险的。您可能在每次代码评审中发现 5 个错误,这已经很多了,但如果您还提出了 30 条其他非错误意见,那么突然间 “只有 15% 的意见是错误”。

      1. 我完全同意。有很多事情是无法轻易衡量的,也有很多事情是永远无法衡量的。但这并不意味着它们不重要。按照你的观点,执行良好的风格可以避免以后出现错误,甚至可以节省很多时间,因为你的代码不会慢慢变成意大利面条。我认为这是人们经常忽略的一点。细化通常是通过一个较慢的过程发生的。是通过数十次提交,而不是少数几次提交。

  59. 代码审查的价值实际上取决于代码和处理代码的人。对于在同一个 repo 上工作多年的团队来说,代码审查可能没有太大价值。但如果团队中新来了一个人,或者是一个初级开发人员,你肯定会想要审查他们的代码。

    代码审查的作用不仅仅是发现错误。你可以指出更好的方法。也许这个 SQL 可以更有效率。也许你可以重构一些代码,使其更健壮。也许你应该在这里添加一条日志语句。这个方法的名称很混乱,我建议将其更名为 xyz?

    1. > 但如果你的团队里有新人,或者是后辈,你一定要审查他们的代码。

      来自后辈或新团队成员的审查也非常有价值,因为他们没有其他人可能拥有的历史或部落知识。他们经常会发现一些因为 “就是这样 “而被忽视的问题。

    2. > 对于在同一个 repo 上工作多年的团队来说,代码审查可能没有太大价值。

      我确实在资深开发人员编写的代码中发现过 bug [代码审查期间的 ETA],这些代码他们已经熟悉了十多年。

    3. 我真的很好奇,我想就您在审核和接受审核方面的经验问您一些后续问题。您介意发邮件到 hn@xkqr.org 吗?

    4. 代码审查还能让团队了解代码中的最新变化

      1. 常见的说法,但我认为这种说法是错误的。PR 的作用是向团队发送邮件,PR 留下的是网页和变更内容的摘要。在那里工作的是 PR,而不是 CR。这意味着,您可以打开并立即合并没有 CR 的 PR,以获得同样的好处。

        CR 的确给了其他人研究代码、熟悉代码的机会,但这与 “保持更新 “是两码事。

  60. 我不知道作者为什么忽略了”……应该阻止提交 “这一部分。

    论文摘要

    > 由于代码审查有很多用途和好处,因此它是现代软件工程工作流程的标准组成部分。由于需要人员参与,代码审查往往是代码集成活动中耗时最长的部分。利用在微软公司获得的经验和数据支持,我们认为:(1) 代码审查通常不会发现本应阻止代码提交的功能问题;(2) 有效的代码审查应由具备特定技能的人员执行;(3) 代码审查的社会方面不容忽视。我们发现,我们需要对代码审查工作流程的指导原则更加精益求精。我们将展示我们在代码审查实践中的发现是如何影响微软的代码审查工具的。最后,我们断言,代码审查实践因其成本高昂,是一个值得更好地理解、系统化并更精确地应用到软件工程工作流程中的主题,而不是目前规定的最佳实践。

    “代码审查找不到错误:当前的代码审查最佳实践如何拖慢我们的脚步

    https://www.microsoft.com/en-us/research/wp-content/uploads/

    1. 应该阻止提交 “总是最棘手的部分之一。有句话说”开车比你慢的人都是白痴,开车比你快的人都是疯子”。但的确,开得越快危险越大,有一种速度可以适当平衡利益与风险;但每个人的看法不同。

      代码气味 “问题也是如此:每个要求你改动的人都是迂腐的人,他们会为了毫无意义的美观而拖慢项目的进度;而每个反对你要求的改动的人都是牛仔,他们会让代码将来更难维护。

      那么在论文中,他们是如何决定一个非错误的修改是否 “应该阻止提交 “的呢?

      1. 如果评论指出了错误/缺陷[1],那么就应该阻止。

        仔细想想,随着错误/缺陷的删除,代码会变得更加正确,从而更加稳定,因为它不需要额外的修改来删除错误,所以删除错误可以减少未来维护的需要。

        如果我们因为对未来维护的担忧而阻塞,那么我们实际上是在断言需求是不稳定的,而且从总体上来说,删除现在的错误是没有价值的,因为需求变更会删除有错误的代码行,并用有新错误的新代码行取而代之。

        我想这取决于特定组织的代码审查流程,是否适合在这一点上阻止代码出现架构/设计问题。根据我的经验,代码审查步骤在开发流程中处于下游位置,而且只关注代码的一个子集,因此无法有效地处理对维护有重大影响的设计变更。

        [1] 论文作者审查了微软内部代码审查工具中的数据,该工具是专有的,因此我们无法看到具体的错误是什么。

  61. 代码审查不仅能发现漏洞,还能从根本上防止漏洞的出现。

    当开发人员知道会有其他人审查他们所编写和提交的代码时,他们会更加谨慎。

    不久前,我们在一个多年期项目中对代码审查政策进行了几次迭代。随着时间的推移,我们从未真正看到代码审查捕获了大量的错误,但每当我们减少代码审查时,我们就会发现生产错误率肯定会上升。

  62. 我对代码审查的不满在于,它们往往会导致大量时间的浪费,有时简单的拉取请求一周内就会花费数千美元。

    我工作了 6 年,时间不多,也不像其他人那样在很多地方工作,但我已经形成了这样的观点:代码评审就像测试一样,应该在必要时作为一种工具使用,而不应该在每次变更时都默认使用。

    在最好的情况下,创建拉取请求的人员会要求审核或决定需要测试的地方。

    我的观点显然适用于产品软件,但对于库而言,尤其是在公开发布的情况下,您需要尽可能多的讨论和测试。

    1. 对我来说,把小的、连贯的、解释过的、测试过的、可审查的变更单元作为自己的工作成果展示给他人,这对我来说有 80% 的价值。至于其他人是否真的深入思考过,或者有什么有用的意见,那都是次要的。

    2. 阻塞代码审查当然也是如此。我有兴趣探索另一种方法,即提交后审查。这里有一篇介绍这种方法的文章:https://copyconstruct.medium.com/post-commit-reviews-b4cc216…

      代码仍然会被审核,但你不会因为等待某个人的审核而导致 PR 被搁置数小时、数天甚至数周。

      1. 我以 “是 “和 “否 “的心态审核了很多代码。

        基本上,当我开始编写 PR 时,我就会在脑海中批准该 PR,直到我发现一些阻碍。例如,导致数据丢失的大问题、性能问题或破坏其他代码的问题。其他的最多只是一个小评论。默认情况下,PR 会被批准。这就赋予了开发人员责任和所有权。此外,它还能加快发布速度

        进行后续公关以改进或解决某些问题与阻止 MR 一样快,但阻止 MR 会影响士气。

        根据我的经验,这种方法能培养责任感和主人翁精神,消除代码审查中对他人工作的监管。

        此外,关于格式、何时测试、设计、特性、功能、架构的决策和讨论不应在代码审查期间进行,而应在编码之前或在工作期间进行。代码审查是最不适合讨论这些问题的时候,在我看来,它应该是对实现进行理智检查的时候。

      2. 我曾经在一个小团队里做过很多这样的事情,我们不阻止审查(我们做审查,但不阻止)。我是团队中的资深开发人员,我会花时间通读收到的新代码。这样做效果很好。

        有趣的是,这部分代码/项目没有超级严格的代码审查要求,但有大量测试,是我认为最健壮/高质量的代码。在一个相当重要的应用程序中,它的运行用户超过 1000 万。它并不庞大,而且有很好的测试(一般来说是相当可测试的)。

        尽管如此,要控制提交后的审核确实很难。也许我们需要更好的工具。就我而言,就我参与的代码领域而言,它很小,足以在我的头脑中进行跟踪。

      3. 我很想探索这种替代方法,但我不确定如何确保在推送和部署提交后发现的任何错误/建议的更改都能真正得到执行。

      4. 我很喜欢这个想法!我并不需要检查每个开发人员是如何处理他们的工作的(虽然在某些情况下,这可能会成为一个有用的指导环节),但重要的是在投入生产之前,工作看起来是什么样的。

        我认为上述方法的主要困难在于,不同的变更会交错在主干中,可能很难只提取其中一个进行部署。但这就是功能标志的作用!

    3. 这个故事可能还不止这些。创建 MR 是一门技术,也可能是一门艺术,这样才能方便审核和批准。

      对 MR 的反馈也是如此。提供简洁明了的反馈意见能更快地解决问题。

      就像 “如果变更很难,那就重构,让变更变得简单”。做一件事有很多种方法,有的更好,有的不好。

      拥有良好审查文化的公司和团队都能成功地将审查作为一种工具。

    4. 这与我在代码审查方面的经验相去甚远,所以我想问一些问题来跟进您的经验。您是否介意发送电子邮件至 hn@xkqr.org

  63. 与大多数流程一样,代码审查的难题在于弄清它对团队和组织的影响。

    在一个庞大的组织中,成千上万的工程师每天都要承受数小时的中断和流程开销,而发布跑道上的官僚机构已经盖了六枚印章,在这种情况下,强制代码审查几乎没有什么坏处(它是在噪音中进行的),但回报却很不稳定(许多人只是在流程的重压下闷头工作)。组织不会因为强制要求而损失什么,但只有某些团队才会看到它的巨大价值。

    另一个极端是,一家拥有五名工程师的初创公司会积压大量的审查工作(审查工作会被缩短),因为每个人都面临着压力,要么要保持高生产率,要么要救火。评审也许可以抓住问题,定期分享关键知识,但组织却要为开销和中断付出明显的代价。

    人们渴望 “放之四海而皆准 “的规则,并为此撰写论文和发表研究报告,但现实中的正确做法往往更加特立独行。

    1. 我并不反对 “视情况而定 “的观点,但对我来说,在 “有五名工程师的初创公司 “中,代码审查通常效果更好,开销更低。我能就您在审查和接受审查方面的经验问您一些后续问题吗?如果可以,请给我发电子邮件:hn@xkqr.org!

  64. 根据我的经验,代码评审可以捕捉到很多错误。但是,如果您发现自己在审查中一次又一次地捕捉到同类错误,那么您就应该想办法自动捕捉这些错误,而不需要审查员参与(静态分析、测试、衬垫等)。

    1. 完全同意尽可能利用静态分析。当在代码评审中发现问题时,我的第一反应就是想:”我们是否可以通过某种 <lint 规则> 来捕捉到这个问题?

  65. 我认为这篇文章的观点是错误的。文章引用的统计数字是,15% 的评论是关于 bug 的,这似乎符合人们的预期,我认为只有当这个数字_高得多_或_低得多_时,才真正值得讨论。

    相反,我认为有两个更有趣的问题值得一问:

    1.代码审查发现缺陷的比率是否足以将代码审查用作缺陷的检测机制?

    经过近 20 年的软件编写工作,我确信答案是否定的。有些审查员比其他审查员更优秀,有些情况比其他情况更有利于发现缺陷,但一般来说,我们应该尝试构建这样的流程,即不假定缺陷会通过代码审查以相当高的比率被发现。当它起作用的时候是很好,但它并不是一种足够可靠的捕获错误的方法,不能成为流程中的负载部分。

    2.强制审查所有代码是否合理?

    这是我犹豫不决的问题。我认为,在一个代码评审优先级很高的环境中,人们接受过有效评审的培训,而且组织政治因素极少,那么允许公关作者决定是否进行评审通常会提高代码的质量和速度,因为代码会更快地发布,而且可以从评审中获益的代码仍然会被评审。在这种情况下,我认为我们会看到,当代码不需要审核时,代码的交付速度会更快,审核的质量也会更高,因为代码被标记为需要审核是一个积极的信号,会让我们更加关注。

    不幸的是,我可能是错的,而且这也不是任何人都愿意冒着声誉受损的风险去推动的实验,所以我怀疑我们不太可能看到规模足够大的实验来确定。如果我们会以某种方式失败,我宁愿失败的原因是代码审查太多,而不是不够。

  66. 错误很’容易’修复,我不担心找不到它们。我担心的是界面,因为所有的用户很快就会成为修改界面的噩梦。

    1. 我很想了解您在代码审查方面的更多经验。能否请您发送电子邮件至 hn@xkqr.org,以便我提出一些后续问题?

  67. 如果有了拼写检查器、代码格式化器和线程器,代码审查就会大大改善。这比手工操作或手工审查要好得多,代码审查可以用于更高层次的想法。

    1. 没错。代码评审不应该涉及代码格式或任何可以通过精简器、格式化器、代码覆盖率限制和静态分析自动完成的工作。如果构建的 PR 是绿色的,那么所有这些都是可以接受的。

  68. 请记住,我支持代码审查,但…

    在药物研究中有一个小把戏,就是用安慰剂来测试潜在的候选药物,从而得出一个似乎显示出益处的糟糕研究结果。之所以说这是个把戏,是因为在很多情况下,替代品不是安慰剂,而是现有的治疗方法。然后,医生会了解到一种更 “现代 “的治疗方法,因为它更现代而对它青睐有加,更好的治疗方法可能就不会被开出处方。

    代码审查的替代品并非无所作为。文章称,代码审查每 10 分钟就能发现一个缺陷–但仅限于前十分钟。根据同样的论点(忽略限定条件,推断数字结果),快速自动测试有可能在一秒钟内发现数千个缺陷–如果它们运行得那么快,而且缺陷已经被测试过的话。静态分析器、结对编程、文档编制这些都是可供选择的方法,还有很多其他方法。

    如果你每天花一个小时来审查代码,那么你就花了 12.5% 的时间来做这件事。这样做会带来机会成本,而根据您特定的组织和代码库,这种机会成本可能会用得更好。当然,把所有事情都分析得一清二楚也有机会成本,但不分析通常会导致目标转移,即做某件事的所谓理由不断变化。今天是为了发现缺陷,明天是为了知识共享,后天是为了安全。它就是所有这些事情,但其他做法可能会更有效地利用时间和人们的耐心来实现这些目标。

    那么,我为什么支持代码审查呢?因为选择作为一个团队进行互动和合作,了解你的同事并与他们达成妥协,这既是良好的团队建设,又能达到其他技术目的。我确实认为结对编程可以在更大程度上实现这一点,同时也会给个人带来更多负担。但前提是你必须控制并拥有这一过程,如果这只是一种生搬硬套的仪式,那么我的感觉是你可能并没有从中获得净收益:你只是因为别无选择才这样做,而不是因为你认为这是对时间的宝贵利用。如果你同时经历过两种文化,一种是人们选择代码审查并从中发现价值的文化,另一种是人们被迫不容置疑地进行代码审查的文化,那么你可能已经见证了一句箴言是如何毁掉一种做法的社会价值的。

  69. > 开发人员每周要花六个小时进行审核。这有点太多了

    调整审核时间非常困难。各种选项都缺乏吸引力。是在达到上限后开始盲目接受修改,还是干脆停止,不让别人合并代码?

    1. 为什么要阻止合并代码?一个人花了几个小时修改代码,却被另一个不分配时间审核的人阻止,这种想法让我很不理解。我们都是专业人士,让别人合并他们的修改,并确保你有时间审查它们。如果你无法审核,而他们仍然需要你的批准,那就批准吧。

      除非你不信任你的同事。如果是这样的话,那么代码审查无论如何都是注定要失败的。

  70. > 在一天中前 60 分钟的代码审查中,审查员大约每十分钟就能发现一个缺陷–只要他们每十分钟审查的代码少于 50 行。

    哦。

    我通常只需要几秒钟就能发现代码中的缺陷。

    我一直觉得这是评估软件的平均水平。如果每个缺陷的平均时间是十分钟,我就需要重新调整对自己的期望值了。

    1. 这确实取决于代码。要找到 CSS bug,是很容易。如果要找到支付集成中的逻辑漏洞,即有人遗漏了或应该实现但没有实现(例如 webhooks),那么这就需要更多时间,开发人员基本上必须坐下来好好研究一下到底应该实现什么/他们会如何开发,然后对照已经完成的工作进行交叉检查,否则你就无法轻易找到这些逻辑漏洞,而这些漏洞实际上就是 bug,只是不像缺少分号这样简单的代码 bug。

      1. 我的日常工作是审计密码学。我可能比大多数阅读 HN 的人更慢找到 CSS bug 的根源。

    2. 你应该明白,找到代码中的 bug 需要多长时间取决于代码。如果不明白,那么我希望你读过 Linux 和 SSL 等的代码。

      1. 是的,当然这在很大程度上取决于上下文。

        我从来没有阅读 Linux 内核代码的动力。我经常发现并披露密码学库的 bug,不过通常都是业余项目,比如 “我觉得如果有一个 GHASH 的 PHP 实现就好了 “之类的,而不是 OpenSSL。

  71. 当我是审核者时,我几乎会发现每一个非小规模的拉取请求都有问题。有时这些都是小问题,但我经常发现 bug 和边缘情况。

    我看到一些关于时间的评论。代码审查需要多长时间?我可以在几分钟内审核数百行代码。在我看来,审查代码比编写代码要容易得多,尤其是当您积累了丰富的经验之后。对于较大的工作,在整个过程中都要有人盯着。

    我遇到过很多开发人员,他们在写完代码后就认为代码可以正常工作。他们不会通过代码或人工 QA 进行测试。当利益相关者告诉他们代码不工作时,他们会表现得很惊讶。第一次就把工作做好。慢就是顺,顺就是快。

    1. 我总是惊讶地发现,我经常会收到这样的拉取请求:要么无法构建,要么单元测试失败,要么两者兼而有之。这些问题至少很容易解决,但当我认为某些代码可能难以维护、反模式或可能以不明显的方式出现错误时,我就会发现很难有效地解决这些问题,并经常最终怀疑自己的建议。

    2. 当我使用 Django 时,添加代码的人在自己的系统中运行代码。而对于 lambda(我们大多在云中部署和测试),人们往往会扔下代码就走。

  72. 这篇论文的标题有点挑衅,但我认为研究结果很有趣。主要是围绕开发人员长期以来认为的价值与实际情况的对比。

    不过,你提出的关于使用缺陷变化率的观点很有道理。我希望研究人员把它作为首选的测量单位。我对流行的开源项目的变更缺陷率做了一些研究,结果发现差异很大。从 ~12% 到 ~40% [1]。

    我希望看到的未来是,作为开发人员,我们使用客观的衡量标准来证明审查时间投资的合理性。随着代理开始不断提交小的错误修复单,这一点将变得越来越重要。

    [1] https://www.shepherdly.io/post/benchmarking-risk-quality-kpi

  73. 我还记得在合并 PR 之前需要获得批准的时代(我还记得在 PR 或任何广泛使用的版本控制系统之前的时代)。

    我一只手就能数出有多少次有人在我的代码中发现了本应停止部署的错误。我并不是没有部署过严重的错误,但这些错误几乎从未被审查我代码的人发现过。

    偶尔也会有人提出更好的方法,或者提出一个问题,最终让我想出更好的方法。但这种情况也很少见。而且我也想不出有多少次是值得在这个过程中花时间去做的。

    结对编程和协作可以带来巨大的益处,但我们所形成的 “最小努力、公关批准 “的文化却不能很好地替代这一点。

    1. 代码审查和结对编程如果有特定的目的,都会非常有用。

      让别人尽快熟悉不熟悉的代码,理清毛糙的代码,使其变得更加清晰,查找错误或发现未知的未知因素,如错误或不必要的复杂性。

      不过,在很多情况下,做这些事情时不看屏幕会更有帮助。在头脑中建立一个心智模型,然后互相启发往往更有帮助。与实际编码或阅读实际代码相比,在黑板上画出东西或在标记文件中写下东西,用简单的术语解释事情,会更有帮助。

      我不确定这算不算结对编程或代码审查,但这种自由讨论代码的方式非常有效。

    2. 我在审查中发现了错误,但更好的是,我要求进行测试,而这些测试也发现了错误。

      即使是低强度的代码审查也能发现缺失的 unittests

    3. 听起来你写的代码质量很高!从您的简介来看,我倾向于认为您知道自己在说什么。我想了解一下你在这里的工作经历。您是否介意发送电子邮件到 hn@xkqr.org,以便我提出一些后续问题?

  74. 代码审查有不同的层次。根据我的经验,基于网络的代码审查工具非常糟糕。任何跨越多个文件的几行以上的代码都需要 cscope 类型的工具。

    还有,审查的类型是什么?这是一个需要高水平设计审查的原型吗,这样实际审查就不会变成设计审查?这种审查多长时间进行一次?

    评审者是谁,流程是什么?关键利益相关者的影响力更大,你需要考虑评审者的经验、知识和可信度。

    最后,代码有多重要?是内核代码,还是需要竞赛条件和内存泄漏检查的高执行守护程序代码?您是否对代码进行了静态分析?代码是否能编译并实现其设计目标?单元测试日志在哪里?

    需要考虑的问题很多。

  75. 技术债务。尽量减少技术债务,在需要时,为其写一个任务,以便日后进行研究。

    编码标准。不要提交有多余行数的代码,这些代码会拖慢下一个开发人员的工作,使他们无法了解过去的代码是做什么的。

    最重要的是,确保覆盖边缘情况,通常是通过所有可能结果的真值表。

    我经常会在 PR 上评论说:”等等等等,但不阻塞”,所以我允许这样做,但至少我的意见是众所周知的,以防日后出现代码问题。

    我的公关需要很长的时间,因为我挖空心思。

  76. 我喜欢在发布 PR 的同时看到正在运行的软件。GitLab 有一个 “审查环境”(Review Environment)的概念,把我宠坏了。从特性分支部署的短暂、动态调配的环境,对工作效率的提升绝对是惊人的。

    它为公关提供了更多的背景信息。

  77. 我发现很多标准流程都可以用类似的方式来描述–如果你注意到它们能解决什么问题,它们应该会非常有用。诀窍在于一些重要但微妙的细节,比如不要连续花两个小时审核一份过长的公关。一旦这只是流程的一部分,就很容易忘记。

  78. 我不认为代码审查有什么好处。我从事网络开发已有 12 年,在大大小小的公司工作过。

    我认为应该有一个人工的质量保证流程来测试开发人员推送的功能。

    代码审查的问题在于,它总是要花费另一位开发人员大量的时间,而且许多开发人员都超级忙,所以他们只是快速审查一下 PR,然后就批准了,或者觉得自己必须添加一些注释。在开发人员已经在做的工作和必须到 PR 前进行适当审查之间切换上下文,意味着他们应该切换到该 Git 分支,下拉代码,测试所有代码,并检查静态代码审查不会发现的逻辑错误。

    对于初级开发人员来说,代码审查仍然有用,因为您可以发现质量不佳的代码,但对于高级开发人员来说,由于上述原因,代码审查就没有那么有用了,最好是有一个质量保证流程来发现逻辑漏洞,而不是期望开发人员投入那么多时间在上下文切换上。

    1. 这里的问题不是开发人员太忙,而是代码审查被认为是二等公民,而不是编写新代码。这就好比说 “许多开发人员都在忙着开发功能 A,所以他们只是为功能 B 编写了快速而肮脏的代码”。如果审查是功能生产流水线不可或缺的一部分,那么坐下来花一天时间审查代码应该不成问题。对于更大、更复杂的事情,可以进行几轮审查。

      编写第一份 PR 所需的时间与通过所有审核所需的时间之间存在近似的非线性关系。这段时间可以很可靠地计算出来并考虑在内。

    2. 不,自动化测试涵盖了基本功能。对于大多数 PR 而言,熟悉代码的高级人员不需要检查代码并手动测试任何东西,因为大多数时候 “代码审查 “并不是这样的。如果需要他们查看运行状态下的代码,那应该是 CI 流程的一部分,而不是开发人员的手动任务。

      一个好的审查员可以指出错误的编码战略决策或对需求的曲解。质量保证完全是另一层审查。

    3. 听到这个消息我有点吃惊。您能否给 hn@xkqr.org 发一封邮件,以便我提出一些后续问题?

  79. 我唯一不喜欢代码审查的地方就是吹毛求疵的评论。每个人都有自己编写代码的主观方式,如果我的代码足够好用和美观,那就随它去吧。

  80. 代码审查可以发现错误。

    更常见的情况是,代码审查成了团队成员争吵的机会。更糟糕的是,代码审查成为非团队成员对项目行使权力的机会。

    1. 在团队中骑车是件好事。如果你们都要给车棚刷漆,就颜色达成一致会有帮助。

      更广泛地说,代码审查是逐步获得或鼓励整个团队保持一致的绝佳机会。

      至于团队选择在哪些方面保持一致以及保持一致的力度有多大,这都由团队自己决定,所以希望他们不要在无关紧要的细节上纠缠不休,但在我看来,完全放弃这个加强各种凝聚力的非常廉价的机会将是一个很大的错误。

      1. 你对代码审查做了很多正面-反面的断言。我的观点是,消极行为的机会太多了。这与技术和生活中的一切都一样,”只要每个人都尽自己的一份力,就能保持良好的状态”。然而,大多数人并没有这样做。

        1. “大多数人都没有 “这种说法太夸张了。根据我的经验,核心审核无疑是好的。如果没有它,我绝不会经营或加入一家公司。

          我现在独自编写代码,代码审查可能是我最怀念的事情。

          1. > “大多数人不 “的说法太夸张了。

            我很乐意讲道理。我想我更多的感受是,大多数开发人员并不擅长识别何时应该克制。就像大多数开发人员都是糟糕透顶的面试官一样,我认为开发人员也忘记了代码审查归根结底也是人的工作。如果给普通开发人员最小的权力,又没有足够的防护措施,那么就会出现合理的愚蠢行为。

            > 我现在独自编写代码,代码审查可能是我最怀念的事情。

            我觉得 “代码审查 “在这次对话中的含义太多了。代码审查的形式是第二个(或更多)合格的开发人员为了更大的利益阅读和评论代码?显然是好的。在非 FAANG 公司以 github PR 的形式进行代码审查?跳过。袋鼠法庭。

          1. 高级团队成员通常是最严重的违规者。

    2. 代码审查可能是破坏绩效或占据主导地位的机会。我见过无数次这样的情况。

      在排名靠前的组织中,拖延对高绩效人员进行代码审查的阴谋屡见不鲜。

      如果不在团队中符合条件的审查员中轮换审查员角色,也会破坏代码审查,在这种情况下,一切都只代表特定群体的意见。

    3. 在我看来,通常是编写 bug 的人对代码审查如此反感。

  81. 我的问题是,人工审查员发现的 bug 比 ChatGPT 多吗?https://www.thatsoftwaredude.com/content/12848/chatgpt-can-d… 说它很平庸,但那是一年前的事了,老实说,平庸的代码审查似乎已经足够了。

  82. 要学习如何审核 PR,有哪些值得阅读的精彩博客/资源?

  83. 哈?代码审查 cuz 发现 bug…人们好像真的看到了…

  84. 消除错误需要持续、警惕、整体、重叠的方法:

    – 在接受提交之前进行代码审查(Facebook 就是这样做的)

    – 重构侥幸通过的垃圾代码

    – 删除功能

    – 使用更少代码的高阶语言

    – 消除技术债务

    – 吸引更多眼球

    – 更聪明的工程师

    – 投入更多时间改进工程设计

    – 编码指南既要优化简单明了的代码,又不能过于严格,以免妨碍战略性例外情况的出现

    – 将负 LoC 作为关键绩效指标

  85. 同意。在我的职业生涯中,我主要负责管理和审查代码。我发现了很多 bug,偶尔也会发现一些可能会导致中断或给用户带来显著问题的 bug。

    但我发现更多的是没有经过深思熟虑的代码。技术债务和代码气味是真实存在的,它们会影响团队的绩效。要将这些问题消灭在萌芽状态,就需要高质量的公关审查,并花时间与提交者就发现的问题进行沟通。

    在我现在工作的公司,我和我的团队已经将高质量的公关审查变成了常态。我强烈推荐!

    其中一个关键点是 “善意而非讨好”。在公共关系中留下评论时要乐于助人,但不要为了避免冲突而表现得和蔼可亲。

    此外,如果你觉得代码审查是浪费时间,我可以向你推荐我经常做的一件事–给予警告。对于类似的 PR,我会批准并就我希望在将来修正的地方给出评论。我不会因为一些小事而耽误合并,但同时我也不会让小事一直拖延下去。

    1. “技术债务和代码气味是真实存在的

      我认为最让我头疼的是,很多时候,”尽快发布 “是一个合理的商业理由,但缺少的是对附加条件的问责。比如,好吧,如果我们现在不想修复这个问题,因为它需要在下一个版本中出现,那么我们可以按原样合并它,但你不能把它记录在外部文档中,它不能成为 API 的一部分,而且在 X、Y 和 Z 被重写为与 ABC 一致之前,不能在这个方向上进行任何进一步的开发。

      我发现这类讨论很难得到认同。每个人都乐于微笑点头,相应的票据也会被归档并附上截止日期,但下一个版本发布后,新的业务影响因素就会成为重点,清理票据就会被悄悄移到积压票据中,截止日期也会被取消。

      多年来,这种情况一直在重复,让我对这个过程产生了一种愤世嫉俗的情绪,感觉代码审查至少在一定程度上是一种挫败感的表现;我没有足够的支持来坚持在前期做好代码审查工作,所以我实际上只是在预览一两年后会发生什么。

      1. 关于这个问题有几点看法。

        1.很多问题都是由于人少事多造成的。如果只有一两个开发人员,而积压的工作越来越多,那么问题并不在于你没有时间解决问题,而是你的人手不足。如果你有足够的人手,那么从业务的角度来看,就不会出现有人在完善之前的工作,而另一个人却在做下一件事的情况。

        2.如果你的人手不是不够,那么清理新代码的最佳时机就是在编写过程中或编写完成后。我喜欢用的一句话是 “趁记忆犹新”。这样既节省了时间,又不会增加新的错误,因为你不必再次记住所有内容,将所有上下文重新载入你的大脑。

        1. > 如果你不是人手不足

          值得注意的是,有一些脂肪是好事。当你是一家初创公司,你正试图自力更生时,我可以理解,但在某些时候,你需要一些脂肪。脂肪太多不好,但没有脂肪也不好。初创企业必须精益求精,但如果大企业过于精益求精,那就叫厌食症。

          1. 的确,如果你读过《目标》或《凤凰计划》,就会发现他们把这叫做 “懈怠”。关于 “松弛 “为什么重要,有一整套理论。

          2. 另一种观点认为,脂肪在人体内是有作用的。诚然,如果你要优化一个非常狭窄的结果,非常低(但不是无)脂肪的身体看起来很理想,但首先,这实际上是一个非常不健康的身体;其次,世界上最好的举重运动员实际上都有相当可观的脂肪储备来支持和维持他们的肌肉。

            没有脂肪有助于提高速度和效率,但会妨碍你变得强壮。

      2. 不过预览还是很有价值的,当你已经知道某样东西是怎么坏的时候,你就会显得像个魔法师。

        1. 但是,当你不断提醒人们注意同样的问题,却在几个月甚至几年后不断遇到这些问题时,你就会觉得自己像卡桑德拉。

          你只能把 “惊讶的皮卡丘 “这个备忘录发这么多次,它就会失去光泽。

        2. 或者是无能。如果你早知道会出问题,为什么还要批准?你唯一的辩解就是 “当时有很大的压力要发布 xyz”。这样的辩解并不值得同情。认为被破坏的功能是有史以来最重要的事情的动物精神早已不复存在,而对之前最重要的功能所造成的新的中断的挫败感已经占据了上风。

          1. 不要批准!这其实是你可以做的一件事。

        3. 很多时候,这比 “这显然会在某个时候以某种方式影响生产 “更微妙。问题更像是觉得逻辑太复杂,以后很难维护,或者觉得应该或不应该使用某个库,或者觉得用线程做的事情应该是异步的。

          所以是的,并不像 “我说过会发生,但它确实发生了 “那样简单明了,而更像是 “我有一种感觉,这将会是一种痛苦,而我确实在审查代表这种痛苦的代码”。

      3. “没有以后。”这是我的新口头禅。

        1. 这让我想起了代码库中遍布的 “Todos”……我喜欢用 “尤达 “来形容……做或不做,都没有 Todo。

          1. TODO 本身并不坏,但我认为意图很重要–有多大可能有人纯粹是为了解决这条评论而回到这里?如果不太可能,那么 TODO 将在未来重构的背景下被使用,在这种情况下,它就是给最终考虑这项工作的人的一份礼物,帮助他们理解代码或背景的某些内容,而你在项目中意识到这些内容时已经太晚了,无法对其采取行动。

        2. 我最喜欢与此相关的咒语:

          没有什么比暂时更永恒。

          … 和 …

          我们没有时间做对,但我们有时间做两遍。

    2. 我是一名新经理,正在努力让我的团队理解代码审查的价值。我已经经历了太多的重写和重写面条代码,现在我对代码审查更加挑剔,我正试图在我的团队中推广这种文化。您有什么建议吗?

      – 同样的人在别人的合并请求上留下了详细的评论,但当别人没有为他们的合并请求付出同样的努力时,他们就会感到气馁。

      – 人们盲目地接受建议,没有任何抵触情绪,也不进行任何讨论,只为完成审核。

      – 人们把 MR 发到侧频道或其他团队,让自己的修改在没有阻力或来回讨论的情况下被合并。(我曾不得不恢复过几次这样的修改)。

      1. 良好的公关文化肯定是要从头开始建立的,并且要得到自上而下的支持。在 Shopify,我认为他们拥有非常好的公关文化,我们有一些我认为有帮助的东西(除了良好的 CICD 和静态分析工具之外):

        1.公关应该等待 2 次验收,1 次验收即可发货,0 次验收即可紧急发货。我们的团队中应该有 2 名审核人员。

        2.根据代码项目的不同,我们必须填写 PR 的模板,其中包含哪些内容,有哪些改动,测试代码时需要注意什么,等等。

        3.某些领域的代码所有者可能需要特定团队的额外审核。

        4.我们应该在审查分支时对其进行检查和测试。因此,除少数情况外,我们真的不鼓励快速阅读和 LGTM。

        我见过很多地方盲目地接受公关,这很困难,因为如果不真正执行和鼓励这种文化,就很难改变。

        1. 此外,代码审查对于需要被审查的代码也同样有效。

          最糟糕的同行评审发生在成千上万行的 PR 上,因为没有人愿意读那么多,而且会有遗漏。我所见过的成功的代码评审是,人们将代码拆分成可评审的部分,而这些单个的评审是如此之快,以至于最终完成的速度比一份巨型公关还要快。

          1. 在不把任何东西分解成一堆更小的改动的情况下,把一个自成一体的改动合理地分解成最小的改动需要多少额外的时间?

            1. 大约 10-15 分钟 ….

                  git co master
                  git co my-branch -- .
                  git add -up . # select changes relevant to first pr
                  git commit
                  git reset HEAD --hard
                  # and again...
              1. 这个问题是专门针对这种方法行不通的情况提出的,例如,您的团队不想批准只包含死代码的 PR,或者因为变更的任何子集无法编译,或者没有其他部分就无法保留正确的行为。

                1. 拥有合适的工具有助于发布 “不完整 “的工作,例如功能标志,这样您就可以发布某个功能的非常轻量级且尚未准备好供最终用户使用的版本,并继续在较小的 PR 中对其进行迭代。

                  例如,第一次发布时添加了一个新的屏幕,但只转储了输出结果

                  第二个版本添加输入字段和控件

                  下一遍添加验证

                  然后添加动画

                  等等

                  1. 理论上听起来很不错,但实际上呢?

                    1.经常需要修改或重构旧代码。仅有功能标志是不够的。

                    2.即使是功能标志本身也可能是有风险的,可能会影响现有客户的使用。

                    大多数情况下,确实需要对旧代码进行修改,至少在我的经验中,确实没有那些完美的孤立的新功能。

                    1. 如果说重构应该被放在特性标志后面,*因为*它们是如此具有破坏性。

                  2. 在我看来,这是一种糟糕的方法,也是我讨厌如今使用特性标志的原因。

                    例如,如果没有输入验证(前端或后台),我是不会批准任何东西的。我不知道你是否真的会在删除 fflag 之前添加验证功能。”相信我兄弟 “对我不起作用。

                    1. 我的意思是,你可以在功能标志后面对已编写的功能进行验证,而暂缓验证尚未存在的功能。

                      功能标志并不意味着把孩子和洗澡水一起扔掉。

            2. 实践中的忒修斯之船。

              有点像。

              原子提交很难。

          2. 您认为这可以在 PR 的提交级别上实现吗?

            1. 如果每个提交都可以单独审查,那就可以了。

              主要问题在于人、

              1.不愿意阅读冗长的内容,从而导致审批速度减慢,因为没有人愿意去碰它

              2.无法有效审查长篇大论,更有可能漏掉一些内容。

        2. 我们也有这些问题,但通常人们把这些当作官僚主义障碍,并不真正执行这些步骤。例如,模板被忽视,审稿人不检查,只是 LGTM 就可以了。很少有人真正认真去看。

      2. 代码审查文化不会凭空产生。除非您有 CI/CD、测试、任务估算、回顾、事件后记等流程,否则您永远无法让人们相信这些流程是有用的。所以,就从这些开始吧。

        增加更多的流程总是会遭到反对,但如果团队成员都认为保持工作正常是首要任务,那么这些流程就会慢慢/自然而然地出现,因为团队会意识到,积极主动地投资这些流程将为他们节省时间。

      3. 这需要时间。

        对于不习惯代码审查的团队来说,一开始可能会觉得麻烦多于值得。很可能在最初的几个月里,麻烦会大于价值。坚持做下去,最终聪明的开发人员会发现 “如果我们无论如何都要做这件事,我们不妨找点有用的东西来说说”:)

        有几件事情可以做得更顺利:

        – 管理期望值。最初可能只是 “我们只是想在每次修改时多一双眼睛 “或 “了解其他团队成员在做什么”–即沟通第一,改进代码第二。

        – 设置工具,使流程顺畅。如果有人想一劳永逸地完成工作,那么对他们来说,使用你的官方审核流程应该比使用一些旁门左道更容易。一个恶毒的替代方案就是让使用旁门左道变得更难;)

        – 利用自动化。在 PR 上运行测试、分类器、静态检查器等,这样即使没有人留下有趣的评论,开发人员也能得到有用的东西。

        – 如果团队中的某些成员已经有了代码审查的经验,那就调整他们的工作量,让他们能做更多的审查工作。他们可以以身作则,有效地培训其他人。

        – 确保审核中的代码变更大小合理。鼓励尽早并经常提交变更以供审核。说 “这是我花了 3 个月开发的功能,周五就要提交,请审核 “不会让任何人高兴。

        – 让审查不再可怕。代码审查不仅仅是为了发现错误和缺陷,也要鼓励审查者说正面的话。

        1. 这是很好的建议,我觉得 “无论如何我们都必须这样做 “这句话更像是…… “所以我们不妨让自己轻松一点”……例如,写出能正常工作的代码,并通过测试和手动(如果需要)进行自我测试,这样审阅者就不必在实际运行代码时陷入困境(开始时可以添加屏幕截图,但到后来就不需要了)。尽可能减少公关,也就是一个功能卡的多个公关接踵而至,尽快提交有价值的公关,不要因为吹毛求疵而阻拦,而是在共同的期望中开始就更好的事情达成一致,并在下一次修改中实现。

          一般的口号是 “如果它能运行,就不应该被阻止”,开发人员可以选择当场改进可维护性,也可以自行决定推迟到下一次或以后的 PR。毕竟你们彼此信任。

        2. > 设置工具,使流程顺畅。

          > 利用自动化。运行 […]流水线、静态检查器 […]。

          除非你将它们设置为只给出警告而不是阻止构建/合并,否则它们并不能使流程顺畅。无论如何,它们都可能被忽略。

          我认为,在得到团队认可之前,应避免使用内衬程序等。

          1. 这要看情况。如果你的代码库中已经没有林特警告,那么添加阻塞检查以防止出现新的林特警告就没什么大不了的。但如果阻塞检查意味着每个人都必须放弃一切,花一周的时间来修复代码,这当然就不顺利了。

            PS.另外,无论您设置了什么自动阻塞,手动覆盖都是个好主意。大多数流水线都已具备这一功能。

        3. > 一个恶毒的替代方法是增加使用侧信道的难度

          如果人们在寻求旁门左道,这就是一个信号。忽视这一点,忽视人们正在想方设法有效地完成自己的工作,我认为似乎没有抓住重点。

          > 如果一些团队成员已经有了代码评审的经验,那么调整他们的工作量,让他们可以做更多的评审。他们正在以身作则,有效地培训其他人。

          这可能会适得其反。突然之间,只有少数(可能只有一两个)团队成员在做所有的代码评审。他们感受到了压力,不想成为出货的阻塞部分,因此他们的审查工作就草草了事。他们会在其他前辈的意见上盖上 LGTM 的橡皮图章,并可能在第二天才审查其他审查意见。他们很难完成自己的工作,每天 2 个小时的代码审核工作影响巨大(如果审核其他 2 名开发人员的工作,而他们在一天内 6、8、10 个小时都在编写代码,那么第二天就需要 2 个小时来审核他们的工作)。

          > – 确保审核中的代码变更大小合理。鼓励尽早并经常提交修改以供审核。说 “这是我花了 3 个月编写的功能,周五就要提交,请审核 “不会让任何人高兴。

          反过来说,”嘿,请尽快审核,这样我就能在接下来的两个小时内再给你一系列 4 个修改,最后再发送更新来完成这件事”。

      4. 我写了一些我在团队中成功应用的规则。https://max.engineer/mindful-code-reviews

      5. 文化是创造出来的,不是偶然的。

        我会在小组会议上提出所有这些问题,甚至更多。尽量让大家了解审核给提交者和审核者带来的各种好处–让他们说出自己想要或可能得到的好处。讨论各种类型的意见(明确的错误、性能、风格、健壮性、因素和组织等),以及从不须采取行动到小毛病再到阻碍的各种优先级。讨论审核本身的优先级。减少审核的延迟会产生巨大的积极影响。

        1. 人都是聪明的–听听他们的担忧如何?在用一系列 “最佳实践 “和 “预期结果 “来打击他们之前,先听听他们的意见吧。

          我开始认为,在代码审查中,挑毛病完全会适得其反。

          自从我了解了 “Ship/Show/Ask “之后,我对代码审查的看法发生了翻天覆地的变化:https://martinfowler.com/articles/ship-show-ask.html;我不再相信审查每一个改动都是健康的,看到其他模式的不同之处,我就知道它现在是有害的。在我看来,另一种好方法是允许合并后审查,”ship/show/ask “更好,但为什么一定要在合并前进行代码审查呢?

      6. 社会氛围如何?

        我这么问是因为我有一份工作,在 COVID 之前,技术团队只有几个呆头呆脑的程序员在一间办公室里,而在 COVID 之后,技术团队只有一群我不在其中的朋友。

        我的意思是,在 COVID 之前,创始人经常会带我们出去吃午饭或打网球,就像正式的团队建设时间一样。我很喜欢这样做,因为我很挑食,很难交到朋友,所以如果公司有正式的活动,我就更容易融入其中。

        在 COVID 之后,官方活动的力度减弱了。团队太大,无法带所有人出去玩,我也没有加入那些自然而然找到社交方式的朋友圈。

        在新的环境中,我不再觉得自己是团队中平等的一员,我觉得自己就像一个局外人,拥有纸面上的权力,却没有完成工作和度过工作日所需的任何友情。

        尽管每个人都一再表示,我作为最资深的程序员受到了尊重和重视,但我发现在新的环境中,我不可能成为一个好队友,我觉得自己整天都在刻薄,没有人把我当人看。这就是我辞职的部分原因。

        在那样的环境中,我的代码审查很糟糕。

        现在,我在一家远程公司工作,在那里,我再次感觉到每个人都同样不合群。如果他们有了办公室,我可能会套现,然后去度假一年。

        编辑:差点忘了,原来那个 “书呆子程序员 “团队中的另一位女成员,也在我辞职的同时倦怠了。她在新环境中也没交到什么朋友,似乎更乐于追求自己的兴趣爱好,在工作间隙过得轻松自在。

        1. 大三学生能和大四学生做朋友吗?我觉得这是一种 “教授-学生”/”私人-中尉 “的关系。

          我在代码评审中也整天刻薄,而且和团队中的大多数人相比,我还是个相对低年级的学生!>:]他们不把我当人看,因为我不是人。我没有他们的人类情感和关切。我只关心代码。不过,感觉上他们还是喜欢和尊重我的!

          1. 我想我不喜欢成为唯一的中尉吧?

            感觉我的权力只停留在纸面上,却没有落到实处。一切都井井有条,没有人把任何事情写下来……

      7. > 同样的人在别人的合并请求上留下了详细的评论,但当别人没有为他们的合并请求付出同样的努力时,他们就会感到气馁。

        这种情况总是岌岌可危。因为一旦这些人变得颓废,你创造良好公关文化的能力也会随之消失。他们厌倦的原因有很多。如果这些人没有得到明示或暗示的重视,他们就会知道。如果做错事的人先得到晋升(甚至以同样的速度晋升!)、同样的加薪/奖金,而且在所有方面都一视同仁,那么员工几乎总是会得出这样的结论:”如果这对我没有任何好处,我为什么要付出这些额外的努力呢?我不认为提前晋升或类似的承诺会有好的效果,因为有很多员工都得到过这样的承诺,但却没有兑现[0]。因此,在短期内需要有一些奖励,哪怕是微不足道的奖励。

        此外,不要低估明确说 “干得好 “的价值。在沟通中,往往存在着一种巨大的偏见,即只有在出错的时候才会说 “做得好”,而在做得好的时候却不说。你不必事事都说 “干得好”,但我想你会惊讶于有多少人从未从管理层那里听到过这句话。

        [0] 我想和大家分享一个我遇到的故事。我是一名绿色(机械)工程师,在一家初创公司工作。我拥有物理学学位,而不是机械工程学位,但我一直都是动手能力很强的人。但正因为如此,我的薪水较低,也不被重视。我问我的经理,我需要做些什么才能得到晋升,与其他人平起平坐。我把它写成了书面材料,这样我就可以参考了。在下一次绩效考核时,我被说得一无是处。抱怨我没有做到这一点或那一点(有时是不可能做到的事情,有时则很奇怪,比如 “你的代码可能快了 20%,但 X 无法理解它,所以我们不能使用它”–X 是一位只用 C++ 写了不到一年的经理,而我__大量__记录了我对函数的使用)。我询问了我所做的事情和承诺。他们承认我做了所有这些事,甚至更多。其中之一就是拿到了一份合同(我想他们把合同写在这里并不是指望我能拿到),我是唯一一个拿到合同的非经理人,为公司带来了 20% 的收入,同时我也是那个项目上的唯一一个人。你可以想象,我从那次会议上走出来时,我的简历已经被擦得锃亮,从那时起,我就成了朝九晚五的上班族,做着最基本的工作。但我的下一任经理对我赞赏有加,会批评而不是抱怨。他理解我的工作存在未知数,当我加班时,他会让我回家。我一生中从未如此努力地工作过,这也是我最快乐的时光。一个经理可以成就一个员工,也可以毁掉一个员工。这其中的一部分原因是,也许有办法让那些崩溃的员工重新振作起来,但你可能需要先弄清楚他们为什么会崩溃。以及这是否是你能解决的问题。我相信环境对员工的态度有很大的影响,进而影响效率/生产力。如果激情能抵得上 10 点智商,那么快乐至少是让员工高效工作的一个重要因素。每个人都能赢,因为这不是一个零和游戏。

      8. 与人交谈,好奇他们为什么不重视代码审查。

      9. 请继续努力提交 PR!垃圾代码属于垃圾。

        1. 大量垃圾代码正在为所有大型科技公司赚取数十亿美元。亚马逊、Facebook 等公司的大部分代码都是垃圾代码。更不用说那些 “自负盈亏 “的小公司了,它们的代码都是创始人级别的,而且还处于不断 “修复和扩展 “的阶段。

          更重要的是,当一个人致力于某件事情,然后它被称为垃圾时,会形成一种什么样的文化?另一方面,如果有人审视了自己的进展速度,并做出了一个战术性决定:也许某件事情还不错,虽然不是很好,但已经很不错了–他们会把节省下来的时间花在完成项目上;然后,当评审者认为公关是 “垃圾 “时,又会发生什么呢?

          我还认识到,我需要更加有意识地让各种火苗燃烧起来。不可能事事顺心,有时简单低质才是最好的。

      10. 多年前,我有一个老板,他在一瞬间朝我扔了一把椅子。(这可没听起来那么夸张)。

        如果能再为他工作一次,我一定会心甘情愿。因为他虽然会对我大吼大叫或训斥我,但他也愿意给我好的建议,提升我,教导我。

        办公室不是一个安全的空间。你似乎知道哪里出了问题,我肯定你已经很客气地问过了。我相信你提供了胡萝卜,但你的团队知道你有大棒吗?

        > 同样的人在别人的合并请求上留下了详细的评论

        当众表扬这些人做得好。告诉大家,他们设定了标准,而其他人没有达到。

        > 人们盲目接受建议

        辅导,大量的一对一辅导,让他们找到并发出自己的声音。大量的 “团队建设”,让强势与弱势的声音平分秋色。找出那些沉默寡言的人的长处,并围绕这些长处开展有趣的活动。让他们找到…

        > 人们将他们的 MR 发送到侧频道或其他团队

        坚持。措辞严厉的电子邮件。当众贬低。明确告诉团队 “这是不可接受的行为”。

        至于那个扔椅子的人…他总是很公平,总是把团队放在第一位,在他手下工作,我作为一个人、一个经理和一个工程师都得到了成长。在我拿到工资支票的同时,这不是成长的快乐幸运的好时光,而是成长的痛苦,将这种(痛苦)传播开来是你工作的一部分。

        1. 至于躲避投射物:是的,办公室应该是一个安全的空间,如果有人朝我扔椅子,我们中的一个第二天就不会在那里工作了。(加上 “也许他们扔椅子是为了让你躲避从你身后爬过来的忍者 “的正常说明)。

          1. 这把 “椅子 “上有 3 个衣架和 2 个飞盘……我不知道它是怎么把人举起来的。

            那 “扔 “更像是推了一下,那东西就朝我飞过来了。

            那把椅子唯一会伤害的就是我的感情。

            这可比我坐在装运弹药的办公室里可怕多了。

            1. 我很震惊,很震惊,你居然只是为了表达自己的观点而对自己的经历撒谎。有一次,我和一个谎称曾向人扔椅子的人共事,结果发现他是个被通缉的连环杀手,公司差点破产。当然,这一切都不是真的,但如果是真的,那也是我拒绝与这样的人共事的有力佐证!

            2. 你真有勇气,做了一份可怕的工作,不是为了保护其他人过上艰苦的生活,而是为了能在公告板上对他们挑刺。也许我也该这么做

        2. > 办公室不是安全空间。

          它他妈的应该是一个安全的空间,在那里我不会被我的老板向我投掷大型射弹。

        3. 有些工作文化太不利于冲突了。我认为这当然与个人性格有关,但我想归纳为西海岸人不利于冲突。在这些例子中,你可以在 Linked-In 上找到所有的拉拉队,一切都棒极了,发货速度超快,松鼠

          在这些情况下,我发现冲突被掩盖了,而不是以冷静和理解的方式解决。如果没有后者作为范例,大家就会为了和睦相处而互相攻击,同时也就没有了解决分歧的机制。突然之间,在评审中,你就成了拖延时间的 “那个人”,而评审者和被评审者都没有一个健康的文化来讨论问题。

          很抱歉我说了这么多,我认为降权是对一些团队可以有健康的冲突并通过冲突解决问题的震惊的反应–有时它可能看起来像吼叫(通常吼叫就是吼叫,但当一个团队与另一个团队是真正的朋友时,他们会有自己独特的方式来解决冲突)。

    3. 从未意识到这是一个有争议的话题。是否有聪明人认为不需要代码审查?反对代码审查的最佳理由是什么?

      1. 我曾与一位首席技术官交谈过,他反对代码审查,因为代码审查增加了太多开销,部分原因是代码审查在流程中太迟了。

        他鼓励他的团队事先讨论一种方法,或者一起研究一些东西。

        除此之外,他们还有大量的测试和结构非常严谨的代码库,我想这对他们来说是行之有效的。

      2. 我曾在一个团队工作过,该团队不做评审,因为包括尖峰、研究等在内的所有工作都是由两名工程师结对完成的。这是远程的,整天都有摄像头。

        我觉得这让人筋疲力尽。因为配对过程占用了我大量的认知带宽,所以我的工作能力达到了 100%,但产出却只有 50%。

        1. 我参加过全职配对团队,但发现吞吐量提高了 2-5 倍,因为会议、代码审查和上网的次数减少了。这让我很疲惫,因为突然间我每天要写 7 个多小时的代码,这真的很难。

          我参加过的其他团队在没有配对的情况下,每天最多也就写 3 个小时的代码。其余时间都被其他交流渠道占用了。

      3. 我想我大概做过 1000 到 2000 次代码审查。从那以后,我对代码审查的看法发生了翻天覆地的变化。我可以列出一个长长的清单(抱歉,有点冗长……):

        CR 拖慢了工作进度,而且往往是不必要的。耗时过长

        不必要的解释浪费时间。

        当评审员只有一两个人时,有点不可能。如果审核员人数较多,可能就不需要上下文了。

        造成不发货的偏见。”等待 CR “可能会严重阻碍产品的发布。也许,今晚是你把东西放到 prod 中的好时机,而不是明天–但你正在等待 CR。

        这是流程重于人的一个例子(又名:货物崇拜)。何时/何地/如何/为何进行客户关系管理是很重要的,也是因地制宜的。在不同的情况下,客户关系管理的最佳实践会产生不同的结果。通常情况下,客户关系管理只是因为它是一种最佳做法而盲目进行。最好是深入思考什么是重要的以及为什么–而不仅仅是 “哦,对了,这是另一个我们要通过的障碍,因为 #亚马逊做到了”。

        团队分层。在审核过程中,资深/精英/受宠的人总是比较容易过关。

        CR 可能会变得政治化。Scrum 主理人和经理们争先恐后地为团队成员解围,让他们对某些事情进行审核。这对于那一次来说是件好事,但除此之外就会暴露出一个完全崩溃的流程。当 CR 被 “升级 “时,审查员有多大可能真的会花费必要的时间和来回奔波来 “正确 “地审查事情呢?

        这就容易产生 “小毛病”,而 “小毛病 “是无用的,会适得其反。花在小毛病上的时间是一种浪费,而且会耗费精力,因为要不断地回头去看某件事情,然后再去调整 “它还不够好吗”?

        没有背景的随意审查

        在审查过程中达成一致意见是很困难的。不是每个人都能观察/体验和/或解决冲突。

        CR 在代码开发过程中出现得较晚;这是最糟糕的时候之一,因为在某些东西已经完成、打磨、测试并为生产做好准备之后,突然有人认为应该以不同的方式来完成(当某些东西已经完成并开始工作时,这就更容易看出来了)。这就好比写了三次代码,一次是为了把它写对,第二次是为了把它写好,第三次则是为了满足审查员的任何要求。

        这表明对团队缺乏信任。这是把关。

        不能很好地扩展。曾经有一位审核员告诉我,我写代码的速度比他们读代码的速度还快。(当时,我每天审核大约 6 份公关报告,并发出大约 3 份。我负责 80% 的审核工作,这简直是一场灾难;我收到的审核既慢又无用–团队成员都在努力交付他们捉襟见肘的项目;我太紧张了,既无法提供适当的反馈,又不能每周工作 100 个小时)。

        还有更好的选择,即 “运送/展示/询问 “策略: https://martinfowler.com/articles/ship-show-ask.html

        后一种分支策略由代码作者决定:”这个注释中的错字修复需要审核吗?这段代码中的修正是我最初编写的,我对它了如指掌–真的需要阻塞审查吗?在最后一种情况下,如果一个人可以立即合并一堆前导重构,那么他就可以把这个问题解决掉–这样他送审的 PR 就会变得干净而有趣;而且也不会耽误管理分支或纠缠别人的时间。

        让事情变得更好的第二个方法是允许 “合并后 “审查。在我所在的几个团队中,我们已经做了很多这样的工作,因此我们知道了什么样的东西适合单独发布。在另一种程度上,我们没有足够的带宽来审查所有的东西。这并不是坏事。

        1. 这是一堆缺点,但我想我要问的是,是否有聪明人认为,考虑到这些替代方案,总的来说,还是不做为好?你似乎很反对–你会提出什么具体的替代方案,结果可能是什么?

          1. 就像没有一个最有力的 “赞成论据 “一样,”反对论据 “也是如此–>背景比 “最佳做法 “更重要。

            我注意到

            > 还有更好的选择,即 “运送/展示/询问 “策略: https://martinfowler.com/articles/ship-show-ask.html

            说到底,这就像敏捷和 Scrum。实际上,你必须认真思考你的环境,不能只是去套用一个模板式的一刀切解决方案。(最近我肩上的担子很重,因为我觉得 IT 界有太多的人不愿意认真思考他们的背景。太多了:”我想让我的团队’快马加鞭!'”。他们的口头禅是:只要做好站立、做好复古、做好代码审查、做好计划、添加 checkstyle(一种代码语法筛选器)–一切都会很顺利!我现在学会了问–但项目是否及时完成了?在这种情况下,这些项目中是否有任何一项是真正有用的?如果有用,请告诉我具体原因并提供详细信息。我还了解到,如果一个团队远在石器时代,试图采用所有最佳实践的时间很可能比该团队和/或公司的剩余寿命还要长。这就意味着,他们除了在流程变更上喋喋不休之外,不会再做任何有用的事情。这又让我想起了公司责任,有多少公司责任是真正有用的呢?有些 CR 肯定是有用的。不过,一个团队怎么可能花更多的时间去做有用的公关,而花更少的时间去做无用的公关呢?更重要的是,每个 CR 都是一项阻塞性活动,如果我们为了一项通常无用的活动而阻塞开发,那就有问题了。替代方案不一定是完全放弃 CR,我已经提到了两个:”ship/show/ask “和合并后审查(review)。

    4. > “亲切,而非友善

      在加入一个团队时,我对开发人员说的第一句话总是:”我不在乎你有多挑剔,只要诚实就好。”我认为尽早设定期望非常关键。我认为,让开发人员不觉得自己的代码受到攻击或过于自卫是一个很好的进步。在我看来,强烈捍卫自己代码的人是糟糕的开发者。

      1. 我有一个同事,他花了更多的时间为自己的代码辩护,给出一系列错误的原因,而不是真正地修复它们。这种情况已经不止一次了。

        我只是继续工作。总有一天他会意识到他的代码有多糟糕。

      2. 听起来很激进坦率,我喜欢

    5. 这些警告该如何措辞?”下次……”?我很难认真对待自己的警告,如果现在已经足够好的话。

      1. 我们会在评论前加上 “minor:”,所有员工都知道,这意味着这是一件很好但没有必要合并的事情

      2. 使用删除键。(对不起,我说的是玩笑话,但我是认真的,根本不要发送这类评论意见)。

        如果暂时没问题,那就没问题。如果不好,那就说出来。

        如果你确实有这样的顾虑,”暂时没问题”–那是线下谈话的内容,不属于 CR 的范畴。这也是检验一条意见有多重要的试金石。你会安排 15 分钟的会议与同事讨论这个问题吗?如果不会,那为什么可以在公约与建议委员会会议期间这样做呢?

      3. “这暂时没问题,但我们应该考虑一下如何序列化这些对象。请随时在后续版本中删除 N^2 算法。”

        1. 这在你们都是同一家公司的员工,而且彼此尊重的情况下非常有效,但在开源世界中往往行不通,人们就这样消失了,你再也不会听到他们的消息。他们有可能会进行后续跟踪,但根据我的经验,这种情况很少见。

          1. 是的,即使是在公司内部,我接受修改的门槛也会因我的经验和与作者的关系而有很大不同。对于外部贡献者或从未与我合作过的人(通过审核代码或让人审核我的代码),我不会接受代码,直到几乎所有的工作都让我满意为止。而对于经常与我合作的人,我在接受一项修改时往往会加上这样的评论:”这一切都很好,但您需要考虑到 X,这将改变这个补丁中的几乎所有内容”(我说得有点夸张,但只是稍微夸张)。我知道一个更新是否会有问题,是否有必要再看一遍。有时,有几种显而易见的方法可以完成某件事情,他们会选择其中一种,但如果我有理由选择另一种,我就会选择另一种,因为我有理由。

            大多数情况介于两者之间。

            虽然在某些方面,这恰恰相反。对于一个陌生的开源贡献者,我需要确信他的改动是值得的。我会在文体方面放宽要求,我会直接使用他们的补丁,之后再进行修复。如果是我合作过很多次的人(不管是熟悉的贡献者还是同事),我会相信他们对改动的基本质量的意见,但对不必要的风格差异则不那么宽容,因为他们应该已经在这些方面达成了一致,如果他们漏掉了什么,更有可能是疏忽。(另外,鉴于超过 90% 的补丁将来自普通贡献者,我不想在事后修正他们的修改)。

          2. 另外,”时不我待 “是真的。跟进很少发生,跟踪起来很麻烦。让某个人为此负责是不公平的,尤其是如果他们不同意后续行动的话(想必他们是不同意的,否则他们一开始就会做这件事)。

    6. >围绕你发现的问题与提交者会面的时间。

      什么!如果有人安排与我会面讨论公关问题,我会气疯的。我们已经有太多会议要开了,这是唯一可以幸免于难的流程之一。

      1. 我也是,我真的很不喜欢这样的会议,本来可以在 slack 或公关中问我三四个问题,然后等我十五分钟左右再回答。

      2. 会议不需要太正式,也不需要太长。我个人很喜欢公关会议,在会上我们可以探讨代码并理解它,而不是有人在午餐时间把 2000 行代码倒在我的腿上,然后希望在晚饭前把他们的意大利面搅拌均匀

      3. 生气?开会讨论工作?有些人在懒人空间等地方发表的评论听起来比原意更糟糕,而人们也意识到了这一点,所以有时会不遗余力地以原意的方式表达出来。

      4. 说白了,如果提交者想讨论问题,我就会安排时间见面。我并不要求每份公文都要见面。我会根据需要与提交者会面,但频率很低,因为提交者需要尽快熟悉情况。

      5. “当面 “审核是我认为最好的审核方式。如果一份 CR 会有十几条关于所有事情的评论,那么异步审查就是一场灾难–作者会觉得自己受到了攻击。解决冲突和分歧的对话可能不会有好结果。

        就我个人而言,如果团队不习惯当面解决冲突,我喜欢从当面解决冲突开始。只有在建立了健康的关系和冲突解决机制之后,才会进行异步公关。我还喜欢这样一条规则,即在一次 CR 中,通信往返不应超过 2 次,否则应同时进行。

        在很多环境下,推迟小的改动以允许这样的往返时间是不可行的。要做的事情太多了。不值得。当项目失败时,很少会有经理给项目贴上一个大大的 “失败 “标签。我提出这个问题是想说,项目失败总是因为团队进展太慢,而个人往往不知道他们实际上需要更快的进展(反馈回路往往缺失,”哦,我们实际上太慢了,我们需要比实际更快的发货速度。JIRA、计划、估算、CR、最佳实践、修复衬垫所花费的时间–这一切都不重要,因为这个项目实际上失败了–它花的时间太长了。)

  86. 我认为这真的很重要,因为它比 “代码审查 “更重要。它确实说明了人们对统计数据[0]的误解有多深。但人们之所以 “相信”,是因为他们讨厌代码审查,而不是因为他们 “真的 “相信审查结果。

    但统计数据是很棘手的。以文章中举的例子 “15% 的吸烟者会得肺癌 “与 “80% 的肺癌患者吸烟 “相比。这两者并不矛盾,只是看待同一事物的不同方式而已。事实上,人们往往就是这样用统计数据误导你(或者说你可能无意中误导了自己!)。

    另一个有名的例子是时不时出现在 HN 上的:”尽管只有 5.8% 的销售额,但超过 38% 的错误报告来自 Linux 社区”[1]。简而言之,这个例子讲述的是 Linux 用户在提交错误报告方面受过更多训练,而且大多数错误并不针对特定系统。因此,如果只根据提交者的架构来对错误进行分类,实际上会错过很多有价值的信息。由于统计学的工作原理,如果架构依赖率甚至低至 50%(我会很惊讶的!),那么仍然会有大量有用的错误报告。作为一名 Linux 用户,我见过这类 bug,它们并不少见。但我经常看到,因为我是从 linux 系统报告的,所以它们就被驳回了。更有甚者,支持人员会将你发送到他们的页面,要求你为某个 “功能 “或错误问题 “点赞”。你必须先登录。我无法认真对待这样的公司,但该死的是,Spotify 也这样对我,我还把出错的那行代码发给了他们。Netflix 也这样对我说,”我们不屏蔽 Firefox”,但切换用户代理后我就能访问了。有时候,我们的思考不能只停留在表面。

    所以,我想说的是,这里有一个可以抽象出来的普遍教训。

    [0] 大家都开玩笑说统计数字是编出来的,但这同样不好。

    [1] https://news.ycombinator.com/item?id=38392931

    1. > 支持 “会将您发送到他们的页面,要求您为 “功能 “或错误问题 “向上投票”。

      微软为企业产品提供这种服务,客户可能每月支付 10 万美元甚至数百万美元。

      “我们听到了,但你的抱怨还不够流行,所以请走开。”

      “当然,这是一个灾难性的数据丢失漏洞,吃掉了你的财务交易,但如果其他人无法识别他们看似无关的崩溃是完全相同的问题,那么你就没有修复的机会。”

      “既然你在一个名为’Consiser尽职尽责’的问题上获得了一万张选票,我们决定通过删除错误论坛来改善你的体验,并从头开始建立一个新的论坛,减少不爽用户的尖刻评论。”

      1. 我所在的公司/团队对错误和功能请求的处理流程截然不同。如果客户开了一张单子,而我们确定它是一个错误,我们一般会在报告的版本中或之后修复它(除非它是一个安全漏洞或其他重大问题)。但对于功能请求,我们只是告诉他们将其提交给社区,然后我们会评估它是否有效,考虑到我们的其他工作,我们可能会实施它,但不一定会很快实施。

        1. 有时,功能请求实际上是一个错误,可以说明我们没有正确理解设计。

          但我认为,如何理解用户的功能请求非常重要。他们有一种挫败感,你可能没有意识到,但他们并不知道所有的代码和限制。这甚至可能是设计方面的问题,但这仍然很重要。很多时候,有一种方法可以解决用户明确要求之外的功能请求。但要做到这一点,你必须仔细阅读字里行间的内容。当然,有些人在这方面完全走错了路,他们认为苹果公司知道什么对用户最好。这完全是一种难以取得的平衡,但我认为,将其简单化是很常见的。

          有人开玩笑说,用户是傻瓜,也许他们是傻瓜,但这并不意味着他们面临的问题是傻瓜。当一个人拉一扇写着 “推 “的门时,他并不总是哑巴,因为实际上可能是标志和设计表达了不同的意思[0]。就我个人而言,我喜欢用户提出解决问题的方法。我可能会把它扔进垃圾桶,但它往往能给我提供更好的上下文线索,让我知道他们想问什么,而且如果他们认真思考了这个问题,也确实告诉了我他们对产品的关心。他们只是没有我这样的视角,没关系。

          [0] https://www.youtube.com/watch?v=yY96hTb8WgI

          1. > 有时功能请求实际上是错误

            两个缺失的功能加起来可能就是一个错误。例如,我曾使用过同一供应商的两款云产品,其中 CDN 产品缺少的后端 HTTP 功能与 PaaS 服务缺少的 HTTP 前端功能相互影响,导致这两款 “天然契合 “的产品实际上无法结合使用。

            这使得许多本应可行的架构无法实现,迫使客户采用扭曲的设计模式或第三方产品。

            在我看来,这是一个错误(”无法使用你们的产品”),但每个团队都将其单独标记为缺失功能,然后他们在大约三年的时间里都忽略了这一点。

            另外:没有足够多的人投票支持缺失功能,因为没有足够多的人使用产品……因为他们不能。

            我知道这有点离题,但这又回到了博客原文中 “统计很难 “的引言。依靠你并不完全了解的统计数据,你可能会犯下灾难性的商业错误,比如这个 “你不会因为产品无法使用而收到很多投诉 “的例子。

            然而,对于可用的产品,你会收到很多投诉……他们有用户投诉。

            https://en.wikipedia.org/wiki/Survivorship_bias

            1. > 因为没有足够的人使用这些产品……因为他们做不到。

              我认为这完全没有跑题。我认为这是明确的主题,至少是基本主题。不只是统计很难,测量事物也很难,确定因果关系更是难上加难。这通常是统计学和数据科学的根本目标。找出事情发生的原因。测量非常困难,而人们往往认为测量很简单。问题是,无论你测量的是什么,实际上都是一种替代,都具有不确定性。如果你不能很好地理解衡量标准的含义,你往往就不知道这些不确定性。付出艰辛的努力总会有回报,但不幸的是,如果不付出艰辛的努力,就可能要花费一些时间才能使接缝开始裂开。我认为这种不对称往往是人们马虎的原因。

              1. 我喜欢用的例子是 COVID 统计数据引起的混乱,以及人们是如何误解这些数据的。

                例如,新闻中经常报道的每日感染(或死亡)率实际上是:感染率 * 测量精度 * 测量率。

                如果有更多的人接受检测,”比率 “就会上升。

                如果 PCR 检测得到改善,”比率 “就会上升。

                类似的情况也适用于住院和死亡人数。上升的原因可能是某种菌株比另一种菌株更致命,也可能是更多的人感染了同一种菌株,还可能是更多的死亡归因于 COVID 而不是其他原因。

                不同的国家有不同的报告标准,或者报告标准随着时间的推移因环境而改变,这都无济于事!

                等等……

                这很复杂!

      2. 你是说他们不再审查错误报告,不再试图让你相信他们的软件是无懈可击的?

        与我与他们打交道的时候相比,这已经是巨大的进步了。

        1. > 不要审查错误报告

          他们确实会这样做,但即使是礼貌但脾气暴躁的评论最终也会累积到看起来很糟糕的地步。这些评论是公开的–这就是关键所在–因此隐藏它们的唯一办法就是删除它们。通常这种做法会让用户更加不满,所以 “窍门 “就是把整个论坛扔在地上,换一个新软件重新开始,以此来 “改善 “服务。这并不是因为它在任何方面都更好,而是因为它隐含着从 “BUGS “中删除*的意思。

          微软现在已经是……第三个论坛了?我都数不清了。

    2. 基本上,代码审查也会发现很多其他非错误的东西(可能是小毛病和风格问题)。

      这就是为什么看百分比是危险的。您可能在每次代码评审中发现 5 个错误,这已经很多了,但如果您还提出了 30 条其他非错误意见,那么突然间 “只有 15% 的意见是错误”。

      1. 我完全同意。有很多事情是无法轻易衡量的,也有很多事情是永远无法衡量的。但这并不意味着它们不重要。按照你的观点,执行良好的风格可以避免以后出现错误,甚至可以节省很多时间,因为你的代码不会慢慢变成意大利面条。我认为这是人们经常忽略的一点。细化通常是通过一个较慢的过程发生的。是通过数十次提交,而不是少数几次提交。

  87. 代码审查的价值实际上取决于代码和处理代码的人。对于在同一个 repo 上工作多年的团队来说,代码审查可能没有太大价值。但如果团队中新来了一个人,或者是一个初级开发人员,你肯定会想要审查他们的代码。

    代码审查的作用不仅仅是发现错误。你可以指出更好的方法。也许这个 SQL 可以更有效率。也许你可以重构一些代码,使其更健壮。也许你应该在这里添加一条日志语句。这个方法的名称很混乱,我建议将其更名为 xyz?

    1. > 但如果你的团队里有新人,或者是后辈,你一定要审查他们的代码。

      来自后辈或新团队成员的审查也非常有价值,因为他们没有其他人可能拥有的历史或部落知识。他们经常会发现一些因为 “就是这样 “而被忽视的问题。

    2. > 对于在同一个 repo 上工作多年的团队来说,代码审查可能没有太大价值。

      我确实在资深开发人员编写的代码中发现过 bug [代码审查期间的 ETA],这些代码他们已经熟悉了十多年。

    3. 我真的很好奇,我想就您在审核和接受审核方面的经验问您一些后续问题。您介意发邮件到 hn@xkqr.org 吗?

    4. 代码审查还能让团队了解代码中的最新变化

      1. 常见的说法,但我认为这种说法是错误的。PR 的作用是向团队发送邮件,PR 留下的是网页和变更内容的摘要。在那里工作的是 PR,而不是 CR。这意味着,您可以打开并立即合并没有 CR 的 PR,以获得同样的好处。

        CR 的确给了其他人研究代码、熟悉代码的机会,但这与 “保持更新 “是两码事。

  88. 我不知道作者为什么忽略了”……应该阻止提交 “这一部分。

    论文摘要

    > 由于代码审查有很多用途和好处,因此它是现代软件工程工作流程的标准组成部分。由于需要人员参与,代码审查往往是代码集成活动中耗时最长的部分。利用在微软公司获得的经验和数据支持,我们认为:(1) 代码审查通常不会发现本应阻止代码提交的功能问题;(2) 有效的代码审查应由具备特定技能的人员执行;(3) 代码审查的社会方面不容忽视。我们发现,我们需要对代码审查工作流程的指导原则更加精益求精。我们将展示我们在代码审查实践中的发现是如何影响微软的代码审查工具的。最后,我们断言,代码审查实践因其成本高昂,是一个值得更好地理解、系统化并更精确地应用到软件工程工作流程中的主题,而不是目前规定的最佳实践。

    “代码审查找不到错误:当前的代码审查最佳实践如何拖慢我们的脚步

    https://www.microsoft.com/en-us/research/wp-content/uploads/

    1. 应该阻止提交 “总是最棘手的部分之一。有句话说”开车比你慢的人都是白痴,开车比你快的人都是疯子”。但的确,开得越快危险越大,有一种速度可以适当平衡利益与风险;但每个人的看法不同。

      代码气味 “问题也是如此:每个要求你改动的人都是迂腐的人,他们会为了毫无意义的美观而拖慢项目的进度;而每个反对你要求的改动的人都是牛仔,他们会让代码将来更难维护。

      那么在论文中,他们是如何决定一个非错误的修改是否 “应该阻止提交 “的呢?

      1. 如果评论指出了错误/缺陷[1],那么就应该阻止。

        仔细想想,随着错误/缺陷的删除,代码会变得更加正确,从而更加稳定,因为它不需要额外的修改来删除错误,所以删除错误可以减少未来维护的需要。

        如果我们因为对未来维护的担忧而阻塞,那么我们实际上是在断言需求是不稳定的,而且从总体上来说,删除现在的错误是没有价值的,因为需求变更会删除有错误的代码行,并用有新错误的新代码行取而代之。

        我想这取决于特定组织的代码审查流程,是否适合在这一点上阻止代码出现架构/设计问题。根据我的经验,代码审查步骤在开发流程中处于下游位置,而且只关注代码的一个子集,因此无法有效地处理对维护有重大影响的设计变更。

        [1] 论文作者审查了微软内部代码审查工具中的数据,该工具是专有的,因此我们无法看到具体的错误是什么。

  89. 代码审查不仅能发现漏洞,还能从根本上防止漏洞的出现。

    当开发人员知道会有其他人审查他们所编写和提交的代码时,他们会更加谨慎。

    不久前,我们在一个多年期项目中对代码审查政策进行了几次迭代。随着时间的推移,我们从未真正看到代码审查捕获了大量的错误,但每当我们减少代码审查时,我们就会发现生产错误率肯定会上升。

  90. 我对代码审查的不满在于,它们往往会导致大量时间的浪费,有时简单的拉取请求一周内就会花费数千美元。

    我工作了 6 年,时间不多,也不像其他人那样在很多地方工作,但我已经形成了这样的观点:代码评审就像测试一样,应该在必要时作为一种工具使用,而不应该在每次变更时都默认使用。

    在最好的情况下,创建拉取请求的人员会要求审核或决定需要测试的地方。

    我的观点显然适用于产品软件,但对于库而言,尤其是在公开发布的情况下,您需要尽可能多的讨论和测试。

    1. 对我来说,把小的、连贯的、解释过的、测试过的、可审查的变更单元作为自己的工作成果展示给他人,这对我来说有 80% 的价值。至于其他人是否真的深入思考过,或者有什么有用的意见,那都是次要的。

    2. 阻塞代码审查当然也是如此。我有兴趣探索另一种方法,即提交后审查。这里有一篇介绍这种方法的文章:https://copyconstruct.medium.com/post-commit-reviews-b4cc216…

      代码仍然会被审核,但你不会因为等待某个人的审核而导致 PR 被搁置数小时、数天甚至数周。

      1. 我以 “是 “和 “否 “的心态审核了很多代码。

        基本上,当我开始编写 PR 时,我就会在脑海中批准该 PR,直到我发现一些阻碍。例如,导致数据丢失的大问题、性能问题或破坏其他代码的问题。其他的最多只是一个小评论。默认情况下,PR 会被批准。这就赋予了开发人员责任和所有权。此外,它还能加快发布速度

        进行后续公关以改进或解决某些问题与阻止 MR 一样快,但阻止 MR 会影响士气。

        根据我的经验,这种方法能培养责任感和主人翁精神,消除代码审查中对他人工作的监管。

        此外,关于格式、何时测试、设计、特性、功能、架构的决策和讨论不应在代码审查期间进行,而应在编码之前或在工作期间进行。代码审查是最不适合讨论这些问题的时候,在我看来,它应该是对实现进行理智检查的时候。

      2. 我曾经在一个小团队里做过很多这样的事情,我们不阻止审查(我们做审查,但不阻止)。我是团队中的资深开发人员,我会花时间通读收到的新代码。这样做效果很好。

        有趣的是,这部分代码/项目没有超级严格的代码审查要求,但有大量测试,是我认为最健壮/高质量的代码。在一个相当重要的应用程序中,它的运行用户超过 1000 万。它并不庞大,而且有很好的测试(一般来说是相当可测试的)。

        尽管如此,要控制提交后的审核确实很难。也许我们需要更好的工具。就我而言,就我参与的代码领域而言,它很小,足以在我的头脑中进行跟踪。

      3. 我很想探索这种替代方法,但我不确定如何确保在推送和部署提交后发现的任何错误/建议的更改都能真正得到执行。

      4. 我很喜欢这个想法!我并不需要检查每个开发人员是如何处理他们的工作的(虽然在某些情况下,这可能会成为一个有用的指导环节),但重要的是在投入生产之前,工作看起来是什么样的。

        我认为上述方法的主要困难在于,不同的变更会交错在主干中,可能很难只提取其中一个进行部署。但这就是功能标志的作用!

    3. 这个故事可能还不止这些。创建 MR 是一门技术,也可能是一门艺术,这样才能方便审核和批准。

      对 MR 的反馈也是如此。提供简洁明了的反馈意见能更快地解决问题。

      就像 “如果变更很难,那就重构,让变更变得简单”。做一件事有很多种方法,有的更好,有的不好。

      拥有良好审查文化的公司和团队都能成功地将审查作为一种工具。

    4. 这与我在代码审查方面的经验相去甚远,所以我想问一些问题来跟进您的经验。您是否介意发送电子邮件至 hn@xkqr.org

  91. 与大多数流程一样,代码审查的难题在于弄清它对团队和组织的影响。

    在一个庞大的组织中,成千上万的工程师每天都要承受数小时的中断和流程开销,而发布跑道上的官僚机构已经盖了六枚印章,在这种情况下,强制代码审查几乎没有什么坏处(它是在噪音中进行的),但回报却很不稳定(许多人只是在流程的重压下闷头工作)。组织不会因为强制要求而损失什么,但只有某些团队才会看到它的巨大价值。

    另一个极端是,一家拥有五名工程师的初创公司会积压大量的审查工作(审查工作会被缩短),因为每个人都面临着压力,要么要保持高生产率,要么要救火。评审也许可以抓住问题,定期分享关键知识,但组织却要为开销和中断付出明显的代价。

    人们渴望 “放之四海而皆准 “的规则,并为此撰写论文和发表研究报告,但现实中的正确做法往往更加特立独行。

    1. 我并不反对 “视情况而定 “的观点,但对我来说,在 “有五名工程师的初创公司 “中,代码审查通常效果更好,开销更低。我能就您在审查和接受审查方面的经验问您一些后续问题吗?如果可以,请给我发电子邮件:hn@xkqr.org!

  92. 根据我的经验,代码评审可以捕捉到很多错误。但是,如果您发现自己在审查中一次又一次地捕捉到同类错误,那么您就应该想办法自动捕捉这些错误,而不需要审查员参与(静态分析、测试、衬垫等)。

    1. 完全同意尽可能利用静态分析。当在代码评审中发现问题时,我的第一反应就是想:”我们是否可以通过某种 <lint 规则> 来捕捉到这个问题?

  93. 我认为这篇文章的观点是错误的。文章引用的统计数字是,15% 的评论是关于 bug 的,这似乎符合人们的预期,我认为只有当这个数字_高得多_或_低得多_时,才真正值得讨论。

    相反,我认为有两个更有趣的问题值得一问:

    1.代码审查发现缺陷的比率是否足以将代码审查用作缺陷的检测机制?

    经过近 20 年的软件编写工作,我确信答案是否定的。有些审查员比其他审查员更优秀,有些情况比其他情况更有利于发现缺陷,但一般来说,我们应该尝试构建这样的流程,即不假定缺陷会通过代码审查以相当高的比率被发现。当它起作用的时候是很好,但它并不是一种足够可靠的捕获错误的方法,不能成为流程中的负载部分。

    2.强制审查所有代码是否合理?

    这是我犹豫不决的问题。我认为,在一个代码评审优先级很高的环境中,人们接受过有效评审的培训,而且组织政治因素极少,那么允许公关作者决定是否进行评审通常会提高代码的质量和速度,因为代码会更快地发布,而且可以从评审中获益的代码仍然会被评审。在这种情况下,我认为我们会看到,当代码不需要审核时,代码的交付速度会更快,审核的质量也会更高,因为代码被标记为需要审核是一个积极的信号,会让我们更加关注。

    不幸的是,我可能是错的,而且这也不是任何人都愿意冒着声誉受损的风险去推动的实验,所以我怀疑我们不太可能看到规模足够大的实验来确定。如果我们会以某种方式失败,我宁愿失败的原因是代码审查太多,而不是不够。

  94. 错误很’容易’修复,我不担心找不到它们。我担心的是界面,因为所有的用户很快就会成为修改界面的噩梦。

    1. 我很想了解您在代码审查方面的更多经验。能否请您发送电子邮件至 hn@xkqr.org,以便我提出一些后续问题?

  95. 如果有了拼写检查器、代码格式化器和线程器,代码审查就会大大改善。这比手工操作或手工审查要好得多,代码审查可以用于更高层次的想法。

    1. 没错。代码评审不应该涉及代码格式或任何可以通过精简器、格式化器、代码覆盖率限制和静态分析自动完成的工作。如果构建的 PR 是绿色的,那么所有这些都是可以接受的。

  96. 请记住,我支持代码审查,但…

    在药物研究中有一个小把戏,就是用安慰剂来测试潜在的候选药物,从而得出一个似乎显示出益处的糟糕研究结果。之所以说这是个把戏,是因为在很多情况下,替代品不是安慰剂,而是现有的治疗方法。然后,医生会了解到一种更 “现代 “的治疗方法,因为它更现代而对它青睐有加,更好的治疗方法可能就不会被开出处方。

    代码审查的替代品并非无所作为。文章称,代码审查每 10 分钟就能发现一个缺陷–但仅限于前十分钟。根据同样的论点(忽略限定条件,推断数字结果),快速自动测试有可能在一秒钟内发现数千个缺陷–如果它们运行得那么快,而且缺陷已经被测试过的话。静态分析器、结对编程、文档编制这些都是可供选择的方法,还有很多其他方法。

    如果你每天花一个小时来审查代码,那么你就花了 12.5% 的时间来做这件事。这样做会带来机会成本,而根据您特定的组织和代码库,这种机会成本可能会用得更好。当然,把所有事情都分析得一清二楚也有机会成本,但不分析通常会导致目标转移,即做某件事的所谓理由不断变化。今天是为了发现缺陷,明天是为了知识共享,后天是为了安全。它就是所有这些事情,但其他做法可能会更有效地利用时间和人们的耐心来实现这些目标。

    那么,我为什么支持代码审查呢?因为选择作为一个团队进行互动和合作,了解你的同事并与他们达成妥协,这既是良好的团队建设,又能达到其他技术目的。我确实认为结对编程可以在更大程度上实现这一点,同时也会给个人带来更多负担。但前提是你必须控制并拥有这一过程,如果这只是一种生搬硬套的仪式,那么我的感觉是你可能并没有从中获得净收益:你只是因为别无选择才这样做,而不是因为你认为这是对时间的宝贵利用。如果你同时经历过两种文化,一种是人们选择代码审查并从中发现价值的文化,另一种是人们被迫不容置疑地进行代码审查的文化,那么你可能已经见证了一句箴言是如何毁掉一种做法的社会价值的。

  97. > 开发人员每周要花六个小时进行审核。这有点太多了

    调整审核时间非常困难。各种选项都缺乏吸引力。是在达到上限后开始盲目接受修改,还是干脆停止,不让别人合并代码?

    1. 为什么要阻止合并代码?一个人花了几个小时修改代码,却被另一个不分配时间审核的人阻止,这种想法让我很不理解。我们都是专业人士,让别人合并他们的修改,并确保你有时间审查它们。如果你无法审核,而他们仍然需要你的批准,那就批准吧。

      除非你不信任你的同事。如果是这样的话,那么代码审查无论如何都是注定要失败的。

  98. > 在一天中前 60 分钟的代码审查中,审查员大约每十分钟就能发现一个缺陷–只要他们每十分钟审查的代码少于 50 行。

    哦。

    我通常只需要几秒钟就能发现代码中的缺陷。

    我一直觉得这是评估软件的平均水平。如果每个缺陷的平均时间是十分钟,我就需要重新调整对自己的期望值了。

    1. 这确实取决于代码。要找到 CSS bug,是很容易。如果要找到支付集成中的逻辑漏洞,即有人遗漏了或应该实现但没有实现(例如 webhooks),那么这就需要更多时间,开发人员基本上必须坐下来好好研究一下到底应该实现什么/他们会如何开发,然后对照已经完成的工作进行交叉检查,否则你就无法轻易找到这些逻辑漏洞,而这些漏洞实际上就是 bug,只是不像缺少分号这样简单的代码 bug。

      1. 我的日常工作是审计密码学。我可能比大多数阅读 HN 的人更慢找到 CSS bug 的根源。

    2. 你应该明白,找到代码中的 bug 需要多长时间取决于代码。如果不明白,那么我希望你读过 Linux 和 SSL 等的代码。

      1. 是的,当然这在很大程度上取决于上下文。

        我从来没有阅读 Linux 内核代码的动力。我经常发现并披露密码学库的 bug,不过通常都是业余项目,比如 “我觉得如果有一个 GHASH 的 PHP 实现就好了 “之类的,而不是 OpenSSL。

  99. 当我是审核者时,我几乎会发现每一个非小规模的拉取请求都有问题。有时这些都是小问题,但我经常发现 bug 和边缘情况。

    我看到一些关于时间的评论。代码审查需要多长时间?我可以在几分钟内审核数百行代码。在我看来,审查代码比编写代码要容易得多,尤其是当您积累了丰富的经验之后。对于较大的工作,在整个过程中都要有人盯着。

    我遇到过很多开发人员,他们在写完代码后就认为代码可以正常工作。他们不会通过代码或人工 QA 进行测试。当利益相关者告诉他们代码不工作时,他们会表现得很惊讶。第一次就把工作做好。慢就是顺,顺就是快。

    1. 我总是惊讶地发现,我经常会收到这样的拉取请求:要么无法构建,要么单元测试失败,要么两者兼而有之。这些问题至少很容易解决,但当我认为某些代码可能难以维护、反模式或可能以不明显的方式出现错误时,我就会发现很难有效地解决这些问题,并经常最终怀疑自己的建议。

    2. 当我使用 Django 时,添加代码的人在自己的系统中运行代码。而对于 lambda(我们大多在云中部署和测试),人们往往会扔下代码就走。

  100. 这篇论文的标题有点挑衅,但我认为研究结果很有趣。主要是围绕开发人员长期以来认为的价值与实际情况的对比。

    不过,你提出的关于使用缺陷变化率的观点很有道理。我希望研究人员把它作为首选的测量单位。我对流行的开源项目的变更缺陷率做了一些研究,结果发现差异很大。从 ~12% 到 ~40% [1]。

    我希望看到的未来是,作为开发人员,我们使用客观的衡量标准来证明审查时间投资的合理性。随着代理开始不断提交小的错误修复单,这一点将变得越来越重要。

    [1] https://www.shepherdly.io/post/benchmarking-risk-quality-kpi

  101. 我还记得在合并 PR 之前需要获得批准的时代(我还记得在 PR 或任何广泛使用的版本控制系统之前的时代)。

    我一只手就能数出有多少次有人在我的代码中发现了本应停止部署的错误。我并不是没有部署过严重的错误,但这些错误几乎从未被审查我代码的人发现过。

    偶尔也会有人提出更好的方法,或者提出一个问题,最终让我想出更好的方法。但这种情况也很少见。而且我也想不出有多少次是值得在这个过程中花时间去做的。

    结对编程和协作可以带来巨大的益处,但我们所形成的 “最小努力、公关批准 “的文化却不能很好地替代这一点。

    1. 代码审查和结对编程如果有特定的目的,都会非常有用。

      让别人尽快熟悉不熟悉的代码,理清毛糙的代码,使其变得更加清晰,查找错误或发现未知的未知因素,如错误或不必要的复杂性。

      不过,在很多情况下,做这些事情时不看屏幕会更有帮助。在头脑中建立一个心智模型,然后互相启发往往更有帮助。与实际编码或阅读实际代码相比,在黑板上画出东西或在标记文件中写下东西,用简单的术语解释事情,会更有帮助。

      我不确定这算不算结对编程或代码审查,但这种自由讨论代码的方式非常有效。

    2. 我在审查中发现了错误,但更好的是,我要求进行测试,而这些测试也发现了错误。

      即使是低强度的代码审查也能发现缺失的 unittests

    3. 听起来你写的代码质量很高!从您的简介来看,我倾向于认为您知道自己在说什么。我想了解一下你在这里的工作经历。您是否介意发送电子邮件到 hn@xkqr.org,以便我提出一些后续问题?

  102. 代码审查有不同的层次。根据我的经验,基于网络的代码审查工具非常糟糕。任何跨越多个文件的几行以上的代码都需要 cscope 类型的工具。

    还有,审查的类型是什么?这是一个需要高水平设计审查的原型吗,这样实际审查就不会变成设计审查?这种审查多长时间进行一次?

    评审者是谁,流程是什么?关键利益相关者的影响力更大,你需要考虑评审者的经验、知识和可信度。

    最后,代码有多重要?是内核代码,还是需要竞赛条件和内存泄漏检查的高执行守护程序代码?您是否对代码进行了静态分析?代码是否能编译并实现其设计目标?单元测试日志在哪里?

    需要考虑的问题很多。

  103. 技术债务。尽量减少技术债务,在需要时,为其写一个任务,以便日后进行研究。

    编码标准。不要提交有多余行数的代码,这些代码会拖慢下一个开发人员的工作,使他们无法了解过去的代码是做什么的。

    最重要的是,确保覆盖边缘情况,通常是通过所有可能结果的真值表。

    我经常会在 PR 上评论说:”等等等等,但不阻塞”,所以我允许这样做,但至少我的意见是众所周知的,以防日后出现代码问题。

    我的公关需要很长的时间,因为我挖空心思。

  104. 我喜欢在发布 PR 的同时看到正在运行的软件。GitLab 有一个 “审查环境”(Review Environment)的概念,把我宠坏了。从特性分支部署的短暂、动态调配的环境,对工作效率的提升绝对是惊人的。

    它为公关提供了更多的背景信息。

  105. 我发现很多标准流程都可以用类似的方式来描述–如果你注意到它们能解决什么问题,它们应该会非常有用。诀窍在于一些重要但微妙的细节,比如不要连续花两个小时审核一份过长的公关。一旦这只是流程的一部分,就很容易忘记。

  106. 我不认为代码审查有什么好处。我从事网络开发已有 12 年,在大大小小的公司工作过。

    我认为应该有一个人工的质量保证流程来测试开发人员推送的功能。

    代码审查的问题在于,它总是要花费另一位开发人员大量的时间,而且许多开发人员都超级忙,所以他们只是快速审查一下 PR,然后就批准了,或者觉得自己必须添加一些注释。在开发人员已经在做的工作和必须到 PR 前进行适当审查之间切换上下文,意味着他们应该切换到该 Git 分支,下拉代码,测试所有代码,并检查静态代码审查不会发现的逻辑错误。

    对于初级开发人员来说,代码审查仍然有用,因为您可以发现质量不佳的代码,但对于高级开发人员来说,由于上述原因,代码审查就没有那么有用了,最好是有一个质量保证流程来发现逻辑漏洞,而不是期望开发人员投入那么多时间在上下文切换上。

    1. 这里的问题不是开发人员太忙,而是代码审查被认为是二等公民,而不是编写新代码。这就好比说 “许多开发人员都在忙着开发功能 A,所以他们只是为功能 B 编写了快速而肮脏的代码”。如果审查是功能生产流水线不可或缺的一部分,那么坐下来花一天时间审查代码应该不成问题。对于更大、更复杂的事情,可以进行几轮审查。

      编写第一份 PR 所需的时间与通过所有审核所需的时间之间存在近似的非线性关系。这段时间可以很可靠地计算出来并考虑在内。

    2. 不,自动化测试涵盖了基本功能。对于大多数 PR 而言,熟悉代码的高级人员不需要检查代码并手动测试任何东西,因为大多数时候 “代码审查 “并不是这样的。如果需要他们查看运行状态下的代码,那应该是 CI 流程的一部分,而不是开发人员的手动任务。

      一个好的审查员可以指出错误的编码战略决策或对需求的曲解。质量保证完全是另一层审查。

    3. 听到这个消息我有点吃惊。您能否给 hn@xkqr.org 发一封邮件,以便我提出一些后续问题?

  107. 我唯一不喜欢代码审查的地方就是吹毛求疵的评论。每个人都有自己编写代码的主观方式,如果我的代码足够好用和美观,那就随它去吧。

  108. 代码审查可以发现错误。

    更常见的情况是,代码审查成了团队成员争吵的机会。更糟糕的是,代码审查成为非团队成员对项目行使权力的机会。

    1. 在团队中骑车是件好事。如果你们都要给车棚刷漆,就颜色达成一致会有帮助。

      更广泛地说,代码审查是逐步获得或鼓励整个团队保持一致的绝佳机会。

      至于团队选择在哪些方面保持一致以及保持一致的力度有多大,这都由团队自己决定,所以希望他们不要在无关紧要的细节上纠缠不休,但在我看来,完全放弃这个加强各种凝聚力的非常廉价的机会将是一个很大的错误。

      1. 你对代码审查做了很多正面-反面的断言。我的观点是,消极行为的机会太多了。这与技术和生活中的一切都一样,”只要每个人都尽自己的一份力,就能保持良好的状态”。然而,大多数人并没有这样做。

        1. “大多数人都没有 “这种说法太夸张了。根据我的经验,核心审核无疑是好的。如果没有它,我绝不会经营或加入一家公司。

          我现在独自编写代码,代码审查可能是我最怀念的事情。

          1. > “大多数人不 “的说法太夸张了。

            我很乐意讲道理。我想我更多的感受是,大多数开发人员并不擅长识别何时应该克制。就像大多数开发人员都是糟糕透顶的面试官一样,我认为开发人员也忘记了代码审查归根结底也是人的工作。如果给普通开发人员最小的权力,又没有足够的防护措施,那么就会出现合理的愚蠢行为。

            > 我现在独自编写代码,代码审查可能是我最怀念的事情。

            我觉得 “代码审查 “在这次对话中的含义太多了。代码审查的形式是第二个(或更多)合格的开发人员为了更大的利益阅读和评论代码?显然是好的。在非 FAANG 公司以 github PR 的形式进行代码审查?跳过。袋鼠法庭。

          1. 高级团队成员通常是最严重的违规者。

    2. 代码审查可能是破坏绩效或占据主导地位的机会。我见过无数次这样的情况。

      在排名靠前的组织中,拖延对高绩效人员进行代码审查的阴谋屡见不鲜。

      如果不在团队中符合条件的审查员中轮换审查员角色,也会破坏代码审查,在这种情况下,一切都只代表特定群体的意见。

    3. 在我看来,通常是编写 bug 的人对代码审查如此反感。