代码审查是团队研发流程里最容易被吐槽却最不该被取消的一个环节。有人觉得它拖慢交付节奏有人把它当成“走个过场”也有人因为一句“这里再改改”反复来回好几天。本文不讨论“要不要审查”而是把重点放在“如何终结低效的传统代码审查方式”。在 AI Engineer 这个新角色逐渐进入团队的今天我们可以用规则、脚本、模型能力把审查流程重做一遍让机器先干活让人类只看最关键的部分。1. 代码审查为什么需要“终结”1.1 代码审查原本要解决什么问题代码审查Code Review是指开发者在代码合并到主分支之前邀请其他成员对代码进行检查的过程。它的价值可以拆成四层缺陷发现提前拦截潜在的逻辑错误、空指针、资源泄漏、并发问题。规范统一让提交的代码符合团队编码规范便于长期维护。知识传递在审查过程中新人和团队之间完成经验流动。安全防线避免把密钥、越权接口、危险 SQL 等高风险内容直接带上线。这个设计本身没有问题。问题在于很多团队把“代码审查”等同于“人肉阅读全部 diff”导致审查变成一件高成本、低收益、充满主观博弈的事情。1.2 传统代码审查的低效点在哪我见过不少团队的实际流程是开发者在 MR 里 几个同事同事抽空打开几百行 diff从缩进、命名、注释一路点评到代码风格。结果就是审查时间被大量消耗在低级问题上。空行、命名、格式这类问题机器一眼就能识别却需要人去逐行指出。审查质量依赖个人经验和耐心。有人看得细有人扫一眼就通过标准不统一。知识瓶颈明显。核心模块通常由少数几个“老手”掌握新人不敢改老手忙不过来。反馈周期长。如果审查者当天在开会代码就要等好几个小时甚至隔天才能合并。形式化审查泛滥。为了不被阻塞团队成员倾向于互相快速点通过审查名存实亡。这些问题的本质不是“代码审查没用”而是“把所有审查工作都压在人身上”的模式已经不适合现代研发节奏。我们需要把它终结然后换一套分层处理的方式。1.3 AI Engineer 给代码审查带来了什么新变量AI Engineer 并不只是一个“会调用大模型的程序员”。它的核心能力是理解模型的行为边界并把模型嵌入到真实工程流程里。在代码审查场景下AI Engineer 可以做的事情包括把静态规则类检查交给确定性工具处理比如 ESLint、Ruff、Checkstyle、SpotBugs。把需要语义理解的检查交给大模型处理比如“这段事务会不会超时”“这个缓存失效策略是否遗漏了更新路径”。把“审查人”的角色重新定义人类只负责设计决策、架构评估、业务逻辑正确性机器负责琐碎重复项。所以本文说的“终结代码审查”准确理解是终结掉那种依靠人来逐行检查的审查方式用一个“自动化优先 人工聚焦”的新审查体系替代。2. 新的代码审查体系自动化优先人工聚焦2.1 分层审查模型把代码审查拆成三层每一层用不同的执行者层级审查内容执行者目标L1 格式与静态规则缩进、命名、未使用变量、简单 bug 模式构建工具、Lint、静态分析消灭人为纠错L2 语义与安全安全漏洞、异常处理、并发风险、资源释放AI 辅助检查 自动化脚本降低漏审率L3 设计与业务逻辑架构合理性、接口设计、业务规则正确性人工审查聚焦高价值判断这个模型的关键在于并不是取消人工审查而是把人工审查的范围压缩到 L3。L1 和 L2 的问题如果可以被自动化拦截就不应该出现在评审页面上。2.2 代码审查的“左移”原则左移Shift Left原本是测试领域的概念意思是尽早发现问题、降低修复成本。代码审查同样可以左移与其等提交 MR 后让同事指出问题不如在本地编码阶段就通过工具暴露问题。一个典型的左移链路编辑器实时提示 → commit 前 hook 检查 → push 后 CI 自动检查 → MR 门禁检查 → 人工聚焦审查每一步越早修复成本越低。当这个链路完整跑通之后人工审查对象的 diff 已经被过滤掉大量低级噪音评审效率会明显提升。2.3 AI 在代码审查里到底能审什么这里需要准确理解大模型在代码审查中的边界。它能做得很好的从一段代码里推断出可能的异常路径比如把 JSON 解析、外部调用、空集合遍历放在一起时可能出现什么风险。根据上下文判断代码是否符合常见设计模式。生成对 diff 的通俗解释减少审查者的阅读成本。检查测试覆盖是否触及核心分支。它做得不好的无法全面了解业务口径比如“这个 discount 字段到底是不是允许为空”必须看业务规则。无法理解团队内部某些历史包袱比如“这段代码为什么这么绕因为底层老系统只支持这样”。会存在误报和漏报这一点无法完全消除。所以 AI 审查的角色定位是“高密度过滤器和解释器”而不是“最终裁决者”。3. 环境准备与工具链选择3.1 先确定你的技术栈下面给出的方案不绑定特定语言但示例会围绕一个 Node.js 项目展开同时兼容 JavaScript/TypeScript。如果你的项目是 Python、Java、Go思路完全一致只需要替换对应的 Lint 和静态分析工具。版本方面需要根据项目实际调整。本文示例以常见环境为例重点演示配置思路不要求版本严格一致。建议在动手前先确认以下信息Node.js 版本示例使用 18 常见特性包管理器示例使用 npm代码托管平台示例使用 GitHub Actions 作为 CI 载体其他平台可参照改造3.2 工具链分四类第一类是格式和 Lint 检查工具。JavaScript 生态常用 ESLintPython 生态常用 Ruff 或 Flake8Java 生态常用 Checkstyle。这些工具负责 L1 层。第二类是静态分析工具。比如 JavaScript 生态的 SonarQube、CodeQLJava 生态的 SpotBugs。它们能识别更复杂的 bug 模式偏 L1 到 L2 之间。第三类是 AI 辅助审查服务。这类服务既能基于本地规则也能基于大模型判断语义问题。选择时优先考虑公司内部部署的模型服务或通过合规渠道接入的 AI 能力避免把源代码直接发送到不可控的外部接口。第四类是流程编排工具。GitHub Actions、GitLab CI、Jenkins 都可以承担这一层拉取代码、执行脚本、输出报告、阻塞合并。3.3 示例项目结构为了方便理解我设计了一个最小的项目结构code-review-demo/ ├── .github/ │ └── workflows/ │ └── code-review.yml ├── scripts/ │ ├── ai_review.py │ └── local_review.sh ├── src/ │ ├── order.js │ └── utils.js ├── test/ │ └── order.test.js ├── .eslintrc.json ├── .prettierrc.json ├── package.json └── README.md这个结构里src 是业务代码test 是测试scripts 放审查相关脚本.github/workflows 放 CI 流程。3.4 安装依赖在项目根目录执行npm init -y npm install eslint prettier eslint-plugin-security --save-dev如果希望更快也可以使用 antfu 等社区预设配置。但为了清晰展示原理这里不引入过多抽象层。4. 完整实战把代码审查流程改造成自动化体系接下来我们分五步把一个传统的纯人工代码审查流程改造成“机器先审、人只审重点”的半自动流程。4.1 第一步配置 Lint 与格式化规则先创建.eslintrc.json配置基础规则和安全插件{ root: true, env: { node: true, es2021: true }, extends: [ eslint:recommended, plugin:security/recommended ], parserOptions: { ecmaVersion: latest, sourceType: module }, rules: { no-unused-vars: warn, no-undef: error, security/detect-object-injection: warn, security/detect-non-literal-fs-filename: warn } }再创建.prettierrc.json{ semi: false, singleQuote: true, trailingComma: all, printWidth: 100 }然后在package.json里加入脚本{ scripts: { lint: eslint \src/**/*.js\ \test/**/*.js\, format:check: prettier --check \src/**/*.js\ \test/**/*.js\, format:write: prettier --write \src/**/*.js\ \test/**/*.js\ } }这里为什么要单独拆format:check和format:write因为 CI 里只允许做检查不允许直接改写代码本地开发则希望通过一条命令自动修复格式。4.2 第二步编写本地提交前检查脚本在scripts/local_review.sh中把 Lint 和测试串起来#!/bin/bash echo 执行 ESLint 检查 npm run lint if [ $? -ne 0 ]; then echo ❌ Lint 检查未通过请先修复代码风格问题 exit 1 fi echo 执行格式检查 npm run format:check if [ $? -ne 0 ]; then echo ❌ 格式检查未通过请先执行 npm run format:write exit 1 fi echo 执行单元测试 npm test if [ $? -ne 0 ]; then echo ❌ 单元测试失败 exit 1 fi echo ✅ 本地检查全部通过给脚本添加执行权限chmod x scripts/local_review.sh这一步完成后开发者可以在提交代码之前先跑一遍完整检查避免把明显问题推到 MR 阶段。4.3 第三步编写 AI 辅助审查脚本AI 辅助审查脚本的作用是把 MR 中的关键变更发送给内部模型服务让模型基于规则提示风险点。为了避免和具体厂商绑定下面给出一个抽象示例核心是“传入 diff 文本返回结构化审查建议”。你只需要把API_URL和鉴权方式替换成团队实际使用的内部服务即可。创建scripts/ai_review.py#!/usr/bin/env python3 # -*- coding: utf-8 -*- AI 辅助代码审查脚本示例 作用接收一个 diff 文件路径调用内部 LLM 服务输出结构化审查建议。 import json import sys from typing import Any import requests # 这里的地址应替换为团队内部部署的模型服务地址鉴权方式按实际接口调整 API_URL http://your-internal-model-service/v1/review API_TOKEN replace-with-your-token def load_diff(diff_path: str) - str: with open(diff_path, r, encodingutf-8) as f: return f.read() def call_review_api(diff_text: str) - dict[str, Any]: headers { Content-Type: application/json, Authorization: fBearer {API_TOKEN}, } payload { model: code-review-ai, messages: [ { role: system, content: ( 你是一名资深代码审查工程师。请对给定的 diff 进行审查。 重点关注安全隐患、异常处理、性能风险和逻辑错误。 不要关注格式类问题。 请按以下 JSON 格式返回 {risks:[{level:high|medium|low,file:...,line:1,reason:...}]} ), }, {role: user, content: diff_text}, ], temperature: 0.2, max_tokens: 2000, } resp requests.post(API_URL, headersheaders, jsonpayload, timeout60) resp.raise_for_status() data resp.json() # 假设返回结构为 data[choices][0][message][content] content data[choices][0][message][content] try: return json.loads(content) except json.JSONDecodeError: return {risks: [], raw: content} def format_report(result: dict[str, Any]) - str: risks result.get(risks, []) if not risks: return ✅ AI 审查未发现明显的高风险问题。 lines [ AI 审查发现以下风险, ] for risk in risks: lines.append( f- [{risk.get(level, unknown)}] {risk.get(file, unknown)} f:{risk.get(line, ?)} {risk.get(reason, )} ) return \n.join(lines) def main() - int: if len(sys.argv) 2: print(用法: python scripts/ai_review.py diff-file) return 1 diff_path sys.argv[1] diff_text load_diff(diff_path) result call_review_api(diff_text) print(format_report(result)) return 0 if __name__ __main__: sys.exit(main())需要说明的是这个脚本强烈依赖内部模型服务的接口定义。如果你的接口返回结构不一样只需调整call_review_api中的解析逻辑。4.4 第四步编写 CI 流程中的代码审查工作流在.github/workflows/code-review.yml中定义 MR 触发流程。这个流程做四件事安装依赖、执行 Lint、执行测试、生成 diff 并调用 AI 审查。name: Code Review Automation on: pull_request: types: [opened, synchronize, reopened] push: branches: [main] jobs: review: runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkoutv4 - name: Setup Node.js uses: actions/setup-nodev4 with: node-version: 18 cache: npm - name: Install dependencies run: npm ci - name: Run ESLint run: npm run lint - name: Run Prettier check run: npm run format:check - name: Run unit tests run: npm test - name: Generate diff id: diff run: | git diff origin/main...HEAD /tmp/pr.diff || true echo diff_size$(wc -l /tmp/pr.diff) $GITHUB_OUTPUT - name: Run AI review if: steps.diff.outputs.diff_size ! 0 run: | pip install requests python scripts/ai_review.py /tmp/pr.diff这个 workflow 的关键设计点有两个。第一使用npm ci保证依赖安装的确定性。第二AI 审查只会在 diff 非空时执行避免无 diff 时的空跑。如果你的代码平台是 GitLab可以改成.gitlab-ci.yml写法核心逻辑相同。4.5 第五步人工聚焦审查清单自动化能过滤掉低级问题但 L3 层设计评审仍然需要人。为了让这一层更高效可以准备一份精简版审查清单放在项目的CODE_REVIEW_CHECKLIST.md中# 代码审查清单人工聚焦项 ## 设计合理性 - [ ] 变更是否符合当前架构方向 - [ ] 是否引入了不必要的新依赖 - [ ] 接口命名和参数设计是否清晰 ## 业务正确性 - [ ] 核心业务流程是否覆盖正常、异常、边界三条路径 - [ ] 并发场景下是否有数据竞争风险 - [ ] 结果是否符合产品需求文档 ## 安全边界 - [ ] 是否校验了外部输入 - [ ] 是否可能在日志中打印敏感信息 - [ ] 权限控制是否在服务端完成而不是依赖前端隐藏 ## 可维护性 - [ ] 是否需要补充注释来记录业务背景 - [ ] 是否有重复代码可以复用已有公共方法 - [ ] 变更是否对测试用例进行了同步补充人工审查者看到 MR 时只需要按这份清单核对不需要再从头看到尾。5. 常见问题与排查思路在实际落地过程中难免遇到各种问题。下面整理了几个高频场景。问题现象常见原因解决思路ESLint 报错太多开发者不愿意跑老项目历史遗留问题多规则过严先分阶段开启规则用--quiet只显示 error历史文件可加忽略清单本地检查通过CI 却失败本地 Node 版本和 CI 不一致在.nvmrc中锁定版本并在 CI 中安装对应版本AI 审查结果不稳定模型 temperature 过高提示词不明确降低 temperature约束输出 JSON 格式添加 few-shot 示例AI 审查总是误报缺少项目背景上下文在系统提示词中补充项目架构说明或只对增量 diff 审查人工审查还是被琐碎讨论占据自动化门禁没挡住低质量提交在 CI 里把 Lint 和格式检查设置为 hard block不允许合并同事仍然习惯“快速通过”流程没有形成正向循环量化指标比如“AI 发现的安全问题数 人工发现的设计问题数”定期复盘排查时建议按“先复现、后定位、再修复”的顺序。比如 CI 失败先在本地运行同一套命令看是否能复现AI 误报先检查提示词里是否缺少项目说明。6. 最佳实践与工程建议6.1 让规则成为“门禁”而不是“建议”很多团队的 Lint 规则虽然配置了但只在本地提示不阻塞合并最终效果等同于无效。建议把 L1 层问题做成硬性门禁未通过不能合并。这样做的价值不在于惩罚开发者而在于把人的注意力真正留给设计问题。6.2 审查结果要可追溯无论使用脚本还是 AI 服务审查结果都应该落在 MR 评论区或流水线日志里而不是只发送到某个人的私聊窗口。这样做的原因是当未来出现问题需要回溯时我们可以知道“当时的自动化审查有没有提示过风险”。6.3 AI 提示词要注入项目上下文AI 审查效果好坏一大半取决于提示词。举个简单例子系统提示当前项目是一个电商订单系统使用 Node.js MongoDB。已知约束 - 订单金额必须使用整数分存储 - 优惠券逻辑在 order.js 中 - 禁止在 try-catch 中吞掉异常这段上下文可以显著降低误报。建议团队的 AI Engineer 把项目内已知业务约束整理成 stable prompt 文件随代码仓库一起管理。6.4 注意代码和数据安全边界涉及使用 AI 服务进行代码审查时必须确认代码所在环境是否合规。不要把包含商业机密、敏感配置、个人信息的源码直接发送到外部服务。建议选择企业内部部署模型或者在数据脱敏后再调用外部接口。6.5 不要一刀切取消人工审查“终结代码审查”的真实目标是终结低效环节而不是取消质量防线。特别是涉及资金、权限、核心链路的变更必须保留至少一名熟悉业务的人做最终确认。越是关键的模块人工聚焦审查越是不可替代。6.6 建立持续反馈闭环自动化流程不是配置完就结束。建议每月分析一次数据CI 阶段拦截了多少问题。AI 审查发现了哪些问题哪些是误报。人工审查里还有多少低价值讨论。把这个结果反馈到规则配置和提示词优化里流程就会持续变好。7. 总结与下一步学习方向代码审查不会消失消失的应该是“人肉逐行盯格式”的过时方式。本文给出的完整路线是用 ESLint、Prettier 等工具接管格式和静态规则用 AI 脚本接管语义层面的风险扫描用 CI 流程把检查变成门禁最后一小部分设计决策交给人工聚焦处理。如果你想进一步深入建议按下面几个方向学习熟悉你所在技术栈的 Lint 和静态分析工具体系理解规则怎么配置、怎么渐进落地。学习 GitHub Actions 或 GitLab CI 的流水线编写把审查动作变成可复用的 workflow。研究大模型提示词工程特别是如何让模型稳定输出结构化 JSON。在团队里推行“分层审查”的文化机器负责琐碎人负责判断。给团队一个具体的小目标这个季度把风格类讨论从 MR 里清零下个季度把安全类误报率降到可接受范围。一步步走下去代码审查才能从“研发流程的负担”重新变成“质量防线的核心”。如果本文对你有些帮助可以先收藏备用。等你在自己项目里跑通这套流程之后再用实际数据检验一下“终结低效审查”是否值得。