
代码审查这件事做得好是整个团队的工程质量护城河做得不好就是每天多出来的一个必须点开的红点。我在去年年底开始折腾一个叫 open-code-review 的开源辅助项目初衷很简单把团队里那套靠自觉、靠口口相传、靠某个人心情好坏来决定质量的 Code Review变成一套有清单、有模板、有自动门禁的开放流程。这篇文章把整个项目的设计思路、核心实现和接入踩坑记录都摊开来讲适合正在搭审查流程的小团队技术负责人也适合想把手头 Review 流程弄得规范一点的普通开发。1. 为什么代码审查总流于形式核心痛点与方案思路1.1 代码审查常见的五种失败模式先说现象。我见过不少团队Git 托管平台上开着分支保护PR/MR 必须至少一个人 approve 才能合并看着流程挺完善实际操作起来却是另一回事。第一种叫橡皮图章式审查。审查人打开 PR扫一眼标题和文件列表看到改动不大直接点了 Approve。评论可能有那么一两条都是LGTM1没毛病。这种审查不是真的验证过代码更像是给流程签字盖章。第二种叫马拉松式审查。一个 PR 挂了两周没人理发起人催了三次终于有人来看却发现分支已经落后主干一大截合并冲突一堆改也不是重开也不是。审查拖得越久讨论成本越高最后往往不了了之。第三种叫点兵点将式审查。团队里有两个人写代码风格天差地别A 写的代码 B 怎么看都不顺眼B 审 A 的代码时每行都挑刺反过来 A 审 B 时又懒得认真看。审查质量取决于轮到谁而不是代码本身如何。第四种叫只盯风格式审查。整个 Review 的注意力全花在命名、缩进、空行这类表层问题上真正涉及并发安全、边界条件、数据一致性这些核心风险点的地方反而没人看。表面功夫做足了底下的雷一个没排。第五种叫不看上下文式审查。审查人只盯着 diff 里的新增行没看调用方是谁、依赖方改没改、数据流经的完整路径是什么。很多线上事故就是在这种只见树木不见森林的审查下溜过去的。这五种模式有个共同点审查规则是隐性的。标准在每个人的脑子里版本还不一样互相之间没法对齐更无从改进。1.2 开放审查模式的三个关键词清单化、自动化、透明化open-code-review 这个名字里的 open我理解的不只是开源更是开放——把整个审查过程从私人经验变成团队共识。第一是规则开放也就是清单化。所有审查标准都写成一份看得见的检查清单谁审都是按同一套标准来。新手不会因为经验不足而漏掉关键检查项老手也不能因为资历深就跳过流程。标准本身放在公共位置谁都能提议修改规则是大家的规则。第二是过程透明。每个 PR/MR 当前卡在哪、哪个审查人还没看、哪些问题提了还没修这些信息对全团队可见而不是只有发起人和审查人私聊才知道。另外一个很重要的点是每条审查意见都要对应到最终代码的修改不留说了但没改的悬空评论。第三是反馈闭环。审查不是提完意见就完事得有标记状态、有催办机制、有结论沉淀。这条意见是必须修的还是建议参考的修改后是否验证过这些信息如果不记录审查就永远是一次性的口水仗。1.3 方案选型为什么选择命令行工具加模板的组合一开始我也考虑过直接上重量级的平台工具后来想明白了我们团队就七八个人不是大厂基建团队搞一套需要专门运维的审查系统是杀鸡用牛刀。真正需要的其实是三样东西一份可复用的检查清单、一组自动扫描规则、一个能对接现有 Git 流程的轻量脚本。所以 open-code-review 最终定下的是命令行工具 模板文件 CI 脚本的组合。命令行工具负责本地检查比如提交前扫一遍调试遗留代码、生成审查建议模板文件负责把清单固化下来让审查人和被审查人有共同的参照物CI 脚本在代码推送到远端时自动跑一遍基础门禁把明显问题挡在合并之前。这个选型的优势很直接接入成本低不需要迁移现有代码托管平台不需要团队成员学新工具规则是纯文本文件改起来快可以随着团队经验积累持续迭代。劣势也有就是不像一体化平台那样有现成的 Web 界面统计报表也得自己写。但对小团队来说这个取舍是值得的。2. open-code-review 核心功能拆解从安装到首次运行2.1 项目结构与快速安装项目结构走的是少即是多的路线核心就三个目录open-code-review/ ├── bin/ │ └── ocr # 主命令入口脚本 ├── rules/ │ ├── default.yml # 内置规则集 │ └── custom.example.yml # 自定义规则示例 ├── templates/ │ ├── pr_description.md # PR 描述模板 │ ├── review_checklist.md # 审查清单模板 │ └── comment_suggestion.md # 评论建议模板 └── ci/ ├── check.sh # CI 环境下运行的检查脚本 └── install-hooks.sh # git hook 安装脚本安装方式也保持了轻量风格只需要把脚本放到 PATH 里或者直接用绝对路径调用git clone 你的仓库地址/open-code-review.git cd open-code-review make install # 验证是否安装成功 ocr --version如果不想全局安装也可以只把ci/install-hooks.sh复制到目标项目里执行这样 open-code-review 就变成目标仓库自己的 pre-commit 钩子团队其他人不需要额外装任何东西。2.2 核心配置解读审查规则是怎么工作的open-code-review 的核心配置是一个 YAML 文件支持放在项目根目录或~/.config下。内置的default.yml长这样# .open-code-review.yml rules: - name: 禁止调试遗留 pattern: console\\.(log|debug)|debugger;|print\\(.*\\) paths: [src/**, app/**] severity: error message: 调试代码不能进入主干请移除后再提交 - name: 魔法数字警示 pattern: (?!\\w)(?:[2-9]|1[0-9])\\d{2,}(?!\\w) paths: [src/**] severity: warn message: 出现看起来像魔法数字的常量建议抽成命名常量 - name: TODO 必须关联工单 pattern: TODO(?!\\s*#\\d) paths: [**/*.py, **/*.js, **/*.ts] severity: warn message: TODO 需要带上工单号否则无人跟进每条规则有五个字段理解起来很直观name是规则名会在输出报告里显示方便定位是哪个规则命中。pattern是正则表达式这是规则的核心匹配到就算命中。正则支持标准的 Perl 风格语法。paths是路径过滤可以用通配符限制规则作用在哪些文件上。比如纯前端项目就不用去扫 Python 的print。severity分error和warn两级。error会直接导致检查不通过相当于硬门禁warn只是提示让审查人重点关注。message是给开发者的提示信息写得越具体、越有建设性人家越愿意改。运行的时候工具会递归遍历当前代码库按路径过滤规则、逐个文件做正则匹配最后汇总成一份报告。正则匹配看似简单但因为规则是可配置的实际能覆盖的场景非常广——调试遗留代码、密钥硬编码、危险函数调用、文件权限问题、跨语言的不安全写法都可以通过配置正则来扫描。2.3 一次典型的审查过程长什么样在已经安装好的项目里执行一次本地检查输出大概是这样$ ocr check [open-code-review] 开始扫描... ✓ 通过: src/utils/format.js ✓ 通过: src/services/api.js ✗ 命中: src/pages/demo.js (第 12 行) 规则: 禁止调试遗留 级别: error 说明: 调试代码不能进入主干请移除后再提交 ✗ 命中: src/utils/request.js (第 88 行) 规则: 魔法数字警示 级别: warn 说明: 出现看起来像魔法数字的常量建议抽成命名常量 扫描完成: 2 处命中, 其中 1 处 error, 1 处 warn 检查未通过, error 级问题需要先修复第一次跑完团队里几个老哥还挺惊讶这脚本还能把我们自己都忘了的console.log找出来其实原理一点都不神秘就是设定好的正则逐文件扫但正因为规则是显式的、可维护的它比人脑记忆靠谱得多。ocr check是本地跑全量扫描。另外还有两个常用子命令ocr diff commitA commitB只扫两个提交之间的差异适合审查人快速定位新增代码里的问题ocr report生成一份 Markdown 格式的审查报告可以直接贴到 PR 的评论里让讨论有据可依。3. 实操环节接入团队工作流的关键配置3.1 对接 Git 托管平台分支保护与 PR 模板工具本身不依赖特定平台但真正跑起来的流程还是得靠 Git 托管平台的分支保护和 PR/MR 机制来兜底。这里分享一套我们验证过的小团队配置。分支保护设置三个硬性要求第一主干分支禁止直接推送任何改动必须走 PR/MR第二至少需要 1 个人 approve 才能合并而且 PR/MR 的发起人不能 approve 自己的代码防止自己审自己的盲区第三CI 检查必须通过。这三条对齐之后流程的安全性有了基本保障。PR 描述模板是很多人忽略但价值极高的环节。我们现在的模板长这样## 这个 PR 解决什么问题 !-- 一句话说清楚不要只写修复 bug要写清楚修复了登录页在弱网条件下报错的问题 -- ## 变更概述 - [ ] 新增功能xxx - [ ] 缺陷修复xxx - [ ] 重构优化xxx - [ ] 测试补充xxx ## 影响范围 !-- 改动了哪些模块会影响哪些调用方需要同步更新文档吗 -- ## 自测记录 - [ ] 本地用例通过 - [ ] 已补充/更新相关测试 - [ ] 对照 open-code-review 审查清单逐项检查过别小看这个模板。它迫使开发者提交前先想清楚变更的边界也让审查人一目了然地知道这次改动动的是什么。很多马拉松式审查的根源就是 PR 描述写得太含糊审查人得自己翻代码猜意图一来二去就不想看了。3.2 审查清单模板的编写要点open-code-review 的另一个核心资产是templates/review_checklist.md。这份清单不是让人逐条打勾的形式主义而是给审查人提供一套可执行的检查路径。我们的清单分成五类检查类别检查项验证方式正确性边界条件是否处理到位对照输入范围跑一遍极端用例安全性用户输入是否可信尝试构造异常输入看会不会崩可读性命名是否表意不看注释能否理解这段逻辑一致性是否遵循团队规范对照规范文档逐条核对性能是否有明显低效点看循环内有没有冗余操作写清单有个关键心得每一项都必须写验证方式而不是只写检查项。比如检查性能这个条目没有任何可操作性换成人话应该是看在循环内是否有数据库查询、HTTP 调用等 IO 操作。有了具体的验证方式新手也能照着执行而不会一脸茫然地不知道怎么检查性能。清单本身也是要迭代的。每在线上出一次事故、每在审查中发现一类新问题就补一条进去。反过来如果某条规则连续几个月都没命中过就可以考虑删掉或降级避免清单变成无人看的墙纸。3.3 自动门禁让机器先过滤 80% 的低级问题open-code-review 的自动检查分两层一层在开发者本地一层在 CI。本地层主要是 pre-commit 钩子通过ci/install-hooks.sh一键安装。每次git commit之前自动执行ocr check --staged只检查暂存区里的文件命中error级规则就拦截提交。这一层能把调试代码、敏感信息误提交这类低级问题挡在出门之前开发者当场就能改成本最小。CI 层跑的是ci/check.sh在推送分支或开 PR 时触发。这一层跑的规则可以比本地更严比如要求TODO 必须关联工单这类规则本地检查容易放宽CI 里必须严格执行。CI 检查的结果直接关联到分支保护不通过就不允许合并。两层搭配的好处是快问题在本地解决慢问题在 CI 统一把守。我见过有些团队把所有检查都堆到 CI结果开发者本地不装钩子每次推送都被 CI 打回来回几个 commit效率低得让人崩溃。正确做法是让本地和 CI 各司其职而不是互相替代。4. 常见问题与排查技巧实录4.1 误报过多审查工具被当成狼来了open-code-review 刚上线时我们踩过一个坑默认规则集里有一条扫描 TODO 注释的规则要求TODO 必须带工单号。结果存量代码里有几十个不带工单号的 TODOCI 一跑直接红一片团队瞬间就炸了。排查思路不是删规则而是分三步走。第一步把规则级别从error降成warn先不阻塞流程只做提示第二步花一个迭代把存量问题清理掉第三步存量清零后把级别升回error杜绝新增。这个案例给我们的教训是任何自动检查工具上线都要先跑存量评估。先在本地全量跑一遍统计命中数量和类型再决定哪些规则直接开启、哪些规则降级过渡。工具如果第一天就给人添麻烦后面就很难推下去。4.2 审查意见提了没人改怎么办审查评论最怕两种形态一种是这段代码不行重构一下这种没有具体方案的另一种是A 有问题B 也有问题C 可能也有问题这种没有优先级的。前者让人不知道怎么改后者让人不知道从哪改起。open-code-review 的templates/comment_suggestion.md就是专门解决这个问题的。每条审查评论必须包含三要素问题定位具体到文件和行号、影响描述不修会怎样、改进建议给出可执行的方案。举一个好评论和坏评论的对比坏评论这个查询太慢了能不能优化下好评论第 42 行这里在循环内调用了findById每次迭代都要打一次数据库数据量大时会产生 N1 查询。建议先把要查的 id 一次性批量查回来在内存里做个映射量大的时候能快一个量级。需要我给个示例吗第二条评论看起来费点字但对被审查者来说是巨大的时间节省。我还有个实操技巧评论尽量用提问而非命令的语气。这个地方为什么需要强一致比这里必须改成强一致更容易引发有效讨论也更符合开放审查的调性。4.3 审查拖太久流程反而成了负担没有节奏的审查是流程死亡的第一大原因。我们现在的经验是给审查设一个隐性的 SLA工作日 24 小时内必须有至少一位审查人给出首轮反馈72 小时内PR/MR 要么合并要么明确阻塞原因。实现上靠两个机制。一是ocr report生成的报告里会标注 PR/MR 的开龄打开天数每周五全组过一遍对齐哪些是真正难处理的问题、哪些是纯粹被遗忘的。二是把大 PR 拆小。我见过太多巨型 PR——3000 行改动塞进去谁看了都头大。规范是尽量控制在 300~500 行以内大的改动拆成多个有独立意义的里程碑 PR。这里给一张排查速查表是我们踩坑之后整理的症状可能原因排查步骤检查结果和本地不一致规则版本不一致确认 CI 用的分支和本地一致检查rules/是否有未提交变更钩子没生效hook 权限没开检查.git/hooks/pre-commit是否存在且有执行权限正则误伤匹配范围过宽先缩小paths范围再考虑调整 pattern审查没人响应描述不清、改动过大用模板重写 PR 描述把大 PR 拆小5. 让代码审查真正产生价值的三个习惯5.1 把审查结论沉淀为团队规范工具能拦截低级问题但真正让团队长期受益的是审查中讨论出来的那些共识。比如我们曾经在审查中反复争论错误处理风格争了几次之后终于把结论固化成了规范业务代码只处理本该处理的错误出乎意料的异常统一向上抛由全局兜底处理。这条规范写进团队 Wiki 之后审查时再也不用围绕同一个话题反复拉锯。操作路径很简单每次审查中出现了这条规则值得长期遵守的结论就把它写进规范文档同时看能不能转成 open-code-review 的一条新规则。规范是给人看的规则是给机器扫的两条线都要走。这样审查中的好想法不会流失而是沉淀成团队的方法论资产。5.2 关注审查本身的质量而不是数量有段时间我盯审查覆盖率盯得很紧想着只要有 PR 就必须有人 approve后来发现纯粹追求这个数字意义不大。一个谁都没仔细看就随手 approve 的 PR覆盖率是 100%质量是 0。倒不如引导团队看更有意义的指标平均首轮响应时间验证快慢、单条评论的具体率验证评论质量的粗糙代理、合并后缺陷逃逸率验证审查效果。我建议每个迭代拿出来一起看一次不是搞问责而是看趋势。如果平均首轮响应时间越来越长说明审查节奏需要调整如果缺陷逃逸率居高不下说明清单和规则需要加强。数据不是为了考核谁而是为了发现流程里最需要补的地方。5.3 保持工具和流程的轻量最后分享一个真实体会代码审查工具最怕越做越重。open-code-review 走到现在我只往里面加了两类东西一类是确认有效的正则规则另一类是团队讨论后沉淀的清单模板。凡是加上觉得挺好但说不出解决什么问题的功能一律砍掉。流程也一样。每次想加新的检查项、新的审批环节时先问自己一句加上它团队成员的日常负担增加多少换来的是什么如果答案不清晰就不要加。一套靠负担堆出来的流程最后一定会被团队用脚投票推翻只有让审查变轻松的流程才会被真正坚持下来。我在实际用过一段时间后还有个额外发现当你把规则清单和审查标准明明白白摆在所有人面前时新人的上手速度会快很多。他们不用再靠猜来理解这个团队看重什么风格、哪些坑不能踩看一眼清单就清楚了。也许这就是开放的代码审查最有价值的地方——它把每个人脑子里的隐性知识变成了团队共有的显性资产。