overreactedby Dan Abramov

抑制的抑制

June 11, 2025

通常,当我们想到构建失败时,首先想到的是语法错误,或者“模块未找到”之类的错误。你肯定不希望忘记提交你正在使用的文件。现在出现构建错误,总比以后程序崩溃要好。

我们还可以把视野放宽,考虑一些即使“技术上可以构建通过”,但我们希望构建失败的情况。例如,如果代码风格检查(lint)未通过,你大概不希望部署这次构建。即使它已经被合并进了 main 分支!如果某条 lint 规则本身有问题,你总可以选择抑制(suppress)它。所以,让 CI 失败总比上线有问题的代码要好。如果你确信代码没问题,你可以抑制这条规则,并让其他人审核你的抑制操作。

实际上,抑制是很有用的。有时候规则确实错了。有时候规则过于严格,或者你正在迁移一段早于该规则制定的旧代码,这时引入抑制就很合理。换句话说,有些代码本来就一直不符合这条规则。

但随着大家越来越习惯于抑制规则,你可能会遇到新问题。有些规则其实非常非常不应该被抑制!即使你以为自己的判断没问题,你也可能会因此让网站崩溃或严重影响性能。我自己过去就因为自以为安全的抑制操作搞坏过东西。

那该怎么解决这个问题呢?你不能一刀切地禁止所有抑制,因为它们确实有用。抑制机制让你可以逐步引入和废弃规则,也为极少数真正的误报和特殊情况提供了“逃生通道”。

这里有一个可行的办法。

你可以再引入一条新的 lint 规则。这条新规则会检测并标记对某些可配置 lint 规则的抑制操作。这样,如果负责父目录链 lint 配置的团队对哪些规则绝对不能被抑制有明确意见,那么尝试抑制这些规则就会再触发一条规则违规——也就是违反了“禁止抑制这些规则”的规则。

换句话说,就是有一条 lint 规则,专门禁止你去抑制其他某些 lint 规则。

这听起来像个玩笑,但 Facebook 真的有类似的 lint 规则,而且非常有用。在开源社区中,eslint-plugin-eslint-comments/no-restricted-disable 似乎也是出于类似的动机。

不过,这个方案有一个缺陷。如果有人非常想抑制某条规则,他们也可能会顺便抑制掉“禁止抑制该规则”的那条规则。从根本上说,这就变成了代码评审能否把关的问题。有些事情可以在新员工培训时直接说明:“这么做是不被允许的。”如果你真的非做不可,那就得和 lint 配置的负责人沟通,让他们审核你的 PR。

你也可以部分依赖自动化。事后可以用脚本查找所有新提交的“双重抑制”操作,并自动分配带有服务级别协议(SLA)的工单给提交人。或者强制要求每个“双重抑制”注释都要关联一个工单链接。甚至可以直接阻止代码合并——任何包含“双重抑制”的 PR 都必须由全站基础设施团队盖章。这有助于避免“这里破坏了规则导致全站挂掉”这种情况。当然,有时候你必须快速上线。希望那时基础设施值班同事在线!

我很希望看到更多关于我们工具背后“社会契约”的讨论。社会契约无处不在——体现在我们如何做版本管理,如何将组织结构映射到文件结构,如何将产品拆分给不同团队,以及如何分担上线新功能、避免犯错、推动代码库模式演进的责任。

还有,最重要的是——别把网站搞挂了。

Pay what you like

Edit on GitHub