团队扩大后,同一个项目会出现多种命名、格式和提交习惯。每次评审都花时间讨论分号、目录和变量顺序,真正影响行为的逻辑反而被淹没。
规范常被误解为审美统一。它更实际的价值,是把低价值决定自动化,让协作结果变得可预测。
能自动检查的不要靠提醒
文档里的规范很快会被遗忘。格式交给 Prettier,语法与常见错误交给 ESLint,提交前通过脚本检查。工具给出的反馈一致,也避免评审者扮演格式警察。
但规则不能无限增加。每一条规则都应该回答它在防止什么错误,或者减少什么协作成本。无法说明价值的偏好,不值得阻断提交。
我倾向把反馈按成本分层,越便宜的检查越早执行:
编辑器:格式、基础类型提示
提交前:只检查本次变更文件
拉取请求:完整类型、单元测试、依赖与构建检查
主分支:集成测试、制品生成
发布前:环境与迁移检查把所有检查都塞进 pre-commit,会让一次提交等待几分钟,开发者最终会习惯 --no-verify。把所有问题都留给 CI,又把最便宜的反馈推迟到十分钟以后。规则是否正确是一件事,反馈出现的位置同样决定它能否被长期遵守。
提交记录也是产品界面
清晰的提交信息让后来的人理解变化意图,也让回滚与发布记录更可靠。一次提交最好完成一个可以说明的变化,避免把格式化、重构和功能修改混在一起。
我会用“能否独立回滚”检查提交边界。若数据库迁移、服务端兼容字段和前端消费必须按顺序发布,可以分成三个有依赖说明的提交;如果把全仓格式化混进去,任何一步都难以审查和回滚。
提交信息也不复述文件名,而是说明行为:
fix(search): ignore responses from superseded queries
Users can submit a second query before the first request resolves.
The previous response must not replace results for the current query.两行正文保存了代码看不出的时间约束。半年后定位竞态问题时,它比“fix bug”有价值得多。
规范真正生效,需要默认路径足够轻。脚手架提供一致目录,CI 自动验证,新成员不必背诵整本手册。好的规范像道路标线:多数时候不被注意,却让所有人更快到达。
规则也需要生命周期
项目升级后,过去用于兼容旧环境的规则可能不再成立。规范如果只增不减,检查会越来越慢,例外注释也会越来越多。每条特殊规则应记录原因和适用范围,工具升级时顺便重新评估。
团队可以通过少量真实样本验证规则是否减少缺陷,而不是用规则数量证明工程化程度。当某条检查长期只产生误报,开发者会开始忽略整个反馈系统。保持信号可信,比覆盖所有可能问题更重要。
工程化不是堆工具,而是识别重复摩擦并系统性消除。团队时间有限,应该花在业务判断与系统设计上,而不是反复做同一种小决定。
图:规范既要有产生原因,也要有退出条件。
每条规范都要有删除条件
规范旁边记录它阻止过什么问题、自动化检查在哪里、负责人是谁、什么条件下可以移除。没有真实失败案例又无法自动检查的规则,优先降级为建议,而不是继续增加评审争论。
规则:禁止页面直接调用生产域名
原因:环境切换曾导致测试请求进入生产
检查:eslint no-direct-production-url
移除条件:所有网络调用统一经过生成客户端规范的目标是减少决定,不是永久保存组织历史。