咕嘟火锅后厨有一条铁规矩:任何新菜想上招牌菜单,必须先由首席试吃官阿敏尝一口。这道规矩源于一次惨痛教训——老陈研发的酸汤鱼惊艳了所有人,直接上了菜单,结果三天内收到三十条投诉:鱼刺没处理干净。后厨连夜返工、赔礼道歉,老陈蹲在灶台边叹气:“要是上桌前有人帮我尝一口就好了。” 从那天起,阿敏的筷子成了菜单的守门员。这道“上桌前试吃”的工序,搬到软件工程里,就是代码审查(Code Review)。 代码审查,指工程师写完代码后,先不直接合入主干,而是请另一位同事在合并前仔细读一遍这段变更,找出问题、提出建议。它像一道安全闸门,让缺陷在用户(客人)发现之前,就被同事(试吃官)拦下来。这门手艺看似简单,背后却藏着类型选择、审查标准、流程设计、团队文化一整棵知识树。

岗位关联

对 AI 从业者而言,代码审查是 AI 工程化落地时的日常协作基本功。懂它,你写出的模型代码不仅能跑,还能被团队信任、被同事接力维护——这是从“能写代码”到“能交付系统”的分水岭。

目录
  1. 可视化演示
  2. 为何要审
  3. 审查类型
  4. 审查对象
  5. 审查流程
  6. 审查原则
  7. 常见陷阱
  8. 工具与自动化
  9. 团队文化
  10. AI 应用场景
  11. Python 演示
  12. 常见误区
  13. 面试题

可视化演示

动态展示PR从提交经CI检查、人工审查到修改/合并的完整流程,切换正式/非正式/ML专项/AI驱动四种审查类型,观察评论反馈与通过率差异。

本节配有交互动效(进入视口后自动加载,约 3KB)。

为何要审

阿敏的筷子就是代码审查的化身。每当主厨老陈想往“招牌菜单”(主干分支)加菜,必须先夹一筷子给阿敏尝尝。这规矩源于一场事故:那道酸汤鱼味道惊艳却鱼刺未净,三天三十条投诉,后厨信誉崩塌。老陈这才明白——让问题在客人嘴里爆炸之前被同事发现,是代价最小的止损点。

代码审查(Code Review)就是代码世界的“上桌前试吃”。工程师写完代码,不直接合入主干,而是请另一位同事在合并前仔细读一遍这段变更,找问题、提建议。它像一道安全闸门,把质量问题拦截在用户手上之前。

技术展开:为什么有人觉得“我自己测过了,还要人审?”因为缺陷发现得越晚,修复成本越高。软件工程的经典统计数据给出了一条残酷曲线:需求阶段修复缺陷花 1 份成本,设计阶段 6 份,编码阶段 30 份,测试阶段 240 份。用公式表示:

审查的意义还不止省钱。阿敏每次试吃不只尝味道,还会边尝边跟帮厨解释“这花椒该下多少”——代码审查同样在传播知识:新人对系统约定、历史坑位、架构意图的理解,一半来自看文档,一半来自被审查时的评论。它也在统一规范:全店咸淡标准一致,团队代码风格才不四分五裂;它更是一道质量门禁:菜单上每道菜都有保障,主干上的每段代码都有人背过书。

阿敏的筷子挡下了鱼刺,也把老陈的手艺悄悄传给了整个后厨。审查既是闸门,又是管道——拦住缺陷,也输送经验。

C修复C引入=10Δt\frac{C_{\text{修复}}}{C_{\text{引入}}} = 10^{\Delta t}
意思是:缺陷每拖过一个阶段,修复成本大约翻 10 倍。今天省下的“审查时间”,明天要用数十倍的返工来还。
  1. 修复成本$C_{\text{修复}}$ 表示缺陷在某个阶段被发现时,从发现问题到解决完毕的总投入,包括返工改码、重新测试、来回沟通的成本。
  2. 引入成本$C_{\text{引入}}$ 表示缺陷刚被写出来的那一刻就发现并修掉,需要的最小成本,通常只是一次局部修改。
  3. 阶段间隔$\Delta t$ 表示缺陷从引入阶段到被发现阶段之间跨过了几个阶段;每跨一个阶段,成本约乘 10。

审查类型

试吃有不同排场。有时阿敏炒菜时顺手夹老陈锅里的一口菜,边炒边聊;有时周末闭店,全店围桌正式品评新锅底;有时阿敏不在店里,老陈把菜装盒留样,贴张纸条请她晚上点评;还有时只是让熟客尝一口,点头就上。

代码审查也有四种常见的形态,按“同步/异步”与“正式/轻量”两个维度区分。正式评审会(Fagan 式走查)是多人围读、逐行过稿,适合核心模块重构;结对审查是两个人坐在一起,一个写一个实时看,反馈最快;异步工具审查通过 PR/代码托管平台的评论区进行,是当下最常见的形态,不受时空限制;轻量走查则是小改动快速过目,适合文档修正、配置调整这类低风险变更。

技术展开:选哪种形态,本质是在算一笔投入产出账。每轮审查投入的时间是一份成本,产出的价值是“提前拦住缺陷所省下的修复成本”。衡量公式:

由此得到一个实用决策:家常小炒不必兴师动众,招牌重构必须全员试吃。低风险、低影响的小变更用轻量异步审查;高风险、大范围的核心改动上正式评审会。审查的形式要跟风险匹配,否则要么浪费资源,要么形同虚设。

ROI=Ndefects×Cfix_savedTreview\text{ROI} = \frac{N_{\text{defects}} \times C_{\text{fix\_saved}}}{T_{\text{review}}}
分子是抓到缺陷的数量乘每个缺陷省下的钱,分母是审查耗时。ROI 越高,这次试吃越值得。
  1. 检出缺陷数$N_{\text{defects}}$ 是本次审查实际抓到的缺陷个数,包括逻辑错误、边界漏洞、安全隐患。
  2. 单位节省成本$C_{\text{fix\_saved}}$ 是平均每个缺陷因为早发现而省下的返工成本,越接近引入阶段价值越大。
  3. 审查总耗时$T_{\text{review}}$ 是所有参与者投入审查的工时总和,代表这次审查的机会成本。

审查对象

试吃到底尝什么?阿敏有自己的流程:第一口确认味道对不对(逻辑正确),第二口故意放凉再尝(边界情况),第三口拨开每一片叶子看有没有异物(安全),最后看一眼摆盘是否赏心悦目(可读性)。

代码审查的“味觉清单”同样是四类。逻辑正确性:这段代码在正常输入下是否做了该做的事?边界与异常:数组越界、空值、超时、并发竞态——线上事故十有八九发生在“正常路径之外”;性能与安全:有没有隐藏的 O(n²) 循环、硬编码的密钥、不校验的输入;可读可维护:三个月后的同事(甚至三个月后的你自己)能否读懂这段代码?

技术展开:边界之所以要重点查,是因为它最容易被作者忽略——作者通常按“快乐路径”写代码,但系统 90% 的崩溃发生在“没有人预料到”的分支上。审查时可以用一个视角辅助评估:

阿敏会刻意把汤放凉再尝一口,因为她知道“烫嘴时尝不出腥味”。审查者也要用同样的怀疑精神去看代码:主动问“如果这行输入不是预期值会怎样”——把关注点从“正常能跑”挪到“异常也扛得住”。

Coveragebranch=NcoveredNbranches\text{Coverage}_{\text{branch}} = \frac{N_{\text{covered}}}{N_{\text{branches}}}
这是分支覆盖率:审查或测试到底关照了代码中多少个条件分支。它能帮你意识到“我还有哪些路没走到”。
  1. 已覆盖分支$N_{\text{covered}}$ 是指在审查推演或测试执行时,真正走到的 if/else/switch 分支数量。
  2. 全部分支$N_{\text{branches}}$ 是这段代码中所有条件分支的总数。
  3. 覆盖率含义比值越接近 1,说明审查对分支的关照越周全;如果只有 60%,那剩下的 40% 分支就是事故高发区。

审查流程

一块新豆腐要上菜单,得走完一条固定流水线:帮厨小陈提报新菜(提交变更)→ 阿敏排期试吃(指派审查者)→ 意见写在后厨白板上(评论讨论)→ 老陈调整配方(迭代修改)→ 阿敏点头,菜名才正式上菜单(批准合入)。

在代码世界里,这条流水线就是一次 Pull Request(PR)的审查生命周期。第一步是提交变更:作者把改动打包成 PR,附上说明“我改了什么、为什么改、影响什么”。第二步是指派与等待:系统或负责人指派审查者,审查者要在承诺时间内给出反馈。第三步是讨论与迭代:审查者逐行评论,作者逐条回复或修改,双方像试吃与回锅一样循环。第四步是批准与合入:问题清零、审查者批准,代码才允许进入主干。

技术展开:流程效率可以用“审查速率”度量,即单位时间能有效处理多少行新增代码:

这套流程的价值在于强制顺序:菜单上永远不会出现没尝过的菜,主干上也永远不会出现没审过的代码。每个环节都留痕,出了事故也能倒查“当初是谁批准、当初有没有人提出过风险”。

vreview=LaddedTreviewv_{\text{review}} = \frac{L_{\text{added}}}{T_{\text{review}}}
行业经验是 200-400 行/小时左右最合适。超过 500 行/小时,审查者基本沦为一目十行的“盖章机”。
  1. 新增代码行数$L_{\text{added}}$ 是该 PR 实际新增的代码行数,不含删除和移动。
  2. 审查耗时$T_{\text{review}}$ 是审查者读完并评论这些代码花费的总时间。
  3. 速率含义$v_{\text{review}}$ 表示每小时真正有效复核的代码量,是衡量审查“是否在走马观花”的哨兵指标。

审查原则

阿敏之所以能当十年首席试吃官,靠的不是舌头刁,而是“食德”。她从不因为讨厌香菜就否定整锅汤;不揪着摆盘上的一粒芝麻说一个钟头;当天端来的菜当天评完;她从不说“这菜不行”,而是说“这菜如果再炖十分钟会更好”。

这套食德翻译成代码审查的术语,就是四条黄金原则。小步快跑:PR 尽量控制在 200-400 行以内,小变更容易审得透,大变更必然审不透。对事不对人:评论只针对代码事实,“这里存在越界风险”而不是“你怎么又写 Bug”。及时响应:48 小时内给反馈,作者趁热迭代,积压会摧毁整条流水线。双向负责:作者有责任解释设计意图,审查者有责任尊重合理判断——不是谁职位高谁说了算。

技术展开:为什么“及时”和“小步”如此重要?因为人的注意力是快速衰减的稀缺资源。审查超过一定时长后,专注度按指数下滑:

阿敏每次只尝四五道菜,中间起身喝口茶、让味蕾休息一下。小步、及时、克制,才能让审查长期可持续。一次大而全的“马拉松式审查”,表面热闹,实际后半程全是无效点头。

A(t)=A0⋅e−t/τA(t) = A_0 \cdot e^{-t/\tau}
一开始你目光如炬,一小时后眼皮打架。所以审查要“少量多次”,每次都在注意力黄金期完成。
  1. 初始注意力$A_0$ 是刚开始审查时的专注水平,默认设定为 1。
  2. 衰减系数$\tau$ 决定注意力下降的快慢,单位与时间 $t$ 一致,经验值约 60-90 分钟。
  3. 指数衰减$e^{-t/\tau}$ 表示专注度随时间按指数滑落,而不是线性下降——后半小时的效率断崖式下跌。

常见陷阱

阿敏也有失手的时候。周末赶着打烊,她夹一筷子就点头“可以上架”——这就是橡皮图章式审查。或者她尝着酸汤鱼,突然兴致大发,建议老陈重新设计整个菜单体系——这叫范围蔓延。还有一次,她为了一片香菜叶的形状跟帮厨争论了两小时,结果主菜的咸淡反而没尝出来——细节偏执。更常见的是她出差一周攒了三十道菜没评,后厨出菜节奏全乱——积压拖延。

这四大陷阱在代码审查里尤其致命。橡皮图章式(rubber stamp)指不细读代码直接批准,它最危险,因为它让你误以为“有人把关了”;范围蔓延指在审查中借机塞入与本次变更无关的重构、需求甚至个人偏好;细节偏执指在缩进、命名、括号换行这类风格问题上无限争论,消耗团队情绪;积压拖延则让代码长期游离在主干之外,合并冲突越来越严重,作者也越来越没耐心等。

技术展开:橡皮图章有多普遍?可以用一个哨兵指标近似度量:

试吃若只是走个过场,鱼刺迟早卡在客人喉咙里。橡皮图章比不做审查更危险,因为它制造了“已把关”的虚假安全感。破局之道是给审查设一个最低质量线——比如“零理解不批准,至少能复述这段代码的逻辑”。

Rrubber=Nquick_approveNtotalR_{\text{rubber}} = \frac{N_{\text{quick\_approve}}}{N_{\text{total}}}
快速批准(几乎没花时间就通过)的 PR 数占比。如果这个比率一路走高,说明审查制度正在空转。
  1. 快速批准数$N_{\text{quick\_approve}}$ 指审查耗时极短(例如不足 5 分钟)就批准的 PR 数量。
  2. 审查总数$N_{\text{total}}$ 是同一周期内所有完成审查的 PR 数量。
  3. 比率含义$R_{\text{rubber}}$ 越接近 1,审查水分越大;越接近 0,说明每个变更都被认真对待过。

工具与自动化

阿敏的舌头再灵敏,也有疲于奔命的一天。于是老陈在后厨加装了设备:油温计测中心温度、pH 试纸测汤底酸碱度、金属探测仪筛异物。仪器先过一遍,阿敏再上舌头。机器负责“明显问题”,人负责“微妙判断”。

代码审查同样需要这种“仪器先行”。在人工审查之前,CI 流水线(持续集成)已经把一批机械性检查跑完了:静态检查扫描代码风格和明显的反模式;单元测试验证函数行为;构建系统确认代码能编译打包。这些自动化检查挡掉 80% 的“低级问题”,让人工审查者把脑力留给真正需要人类判断的地方。

技术展开:一个现代化团队的合入门禁,是“自动 + 人工”的串联闸门,用逻辑语言描述就是四项同时成立:

更进一步,AI 辅助审查工具已经能像“金属探测仪”一样自动标记可疑改动:疑似硬编码密钥、越界风险、不恰当的异常吞噬。自动化挡沙,人类审玉——机器把沙子筛掉,阿敏才有时间去细细品味那块玉的雕工。

Gate=Sstatic∧Tunit∧Bbuild∧Rhuman\text{Gate} = S_{\text{static}} \land T_{\text{unit}} \land B_{\text{build}} \land R_{\text{human}}
只有静态检查通过、测试全绿、构建成功、人工批准四个条件同时满足,PR 才能合入。任一项不满足,门禁不开。
  1. 静态检查$S_{\text{static}}$ 是代码风格、重复代码、明显缺陷扫描等自动检查是否通过,值为真或假。
  2. 单元测试$T_{\text{unit}}$ 是自动化测试套件是否全部绿灯,防止行为回归。
  3. 构建与人工$B_{\text{build}}$ 是构建是否成功;$R_{\text{human}}$ 是最后一位人类审查者是否批准。
  4. 与运算$\land$ 是逻辑“且”,四项必须同时为真,门禁才放行。

团队文化

阿敏要退休了。老陈最担心的事,不是没人会尝菜,而是后厨没人敢开口。这些年他见过太多团队:老师傅高高在上,新人端出菜来只敢说“随便做做,大家随便吃吃”——菜还没尝,心先凉了。

代码审查的生死线,同样不在技巧,而在氛围。一个心理安全的团队里,新人敢在评论里说“我不懂这块,为什么这样设计?”,老师傅也敢自曝“这模块我三年前写的,现在看也是个坑”。审查不是考试,是共同打磨——这就是“建设性批评”的真义:对代码提意见,永远附带替代方案,绝不带人身评价。而代码所有权(code ownership)意味着每个模块都有明确的责任人牵头把关,但不是私有领地不让人碰;持续改进则要求团队定期复盘:审查平均耗时多久?哪类问题总是漏掉?我们的机制该不该调整?

技术展开:安全感难以直接画在图上,但可以用一个哨兵指标近似观察:

当每个人都会主动对同事说“帮我校对一下这段逻辑”,阿敏的筷子就不再只属于一个人,而是成了整支后厨共同的习惯。文化不是把仪式挂墙上,而是让每个人都愿意把菜端出来让人尝。

Ssafety=NquestionNblame+1S_{\text{safety}} = \frac{N_{\text{question}}}{N_{\text{blame}} + 1}
团队讨论里“为什么”式的好奇提问次数,除以“你怎么又”式的指责次数。比值越高,氛围越安全。
  1. 提问次数$N_{\text{question}}$ 是讨论中出现的好奇型提问数量,如“为什么要这么设计?”“这个场景我没考虑过,你怎么看?”
  2. 指责次数$N_{\text{blame}}$ 是出现攻击型语句的次数,如“这代码写得真烂”“这都能写错”。加 1 是防止除零。
  3. 安全指数$S_{\text{safety}}$ 越高说明团队越敢暴露真实问题,审查流越顺畅,缺陷漏网越少。

AI 应用场景

场景 1:AI 审查机器人当“金属探测仪”

阶段:质量保障与交付门禁

解决的问题:人工审查者每次都要花大量时间扫雷式地找“硬编码密钥、调试打印残留、越界风险”这类低级问题,既枯燥又容易漏。利用 AI 在 PR 提交后分钟级完成首轮自动化扫描,把可疑行标注出来。

具体案例:某金融科技公司引入 AI 审查助手,每次 PR 提交后先自动扫描 token 泄漏与敏感信息,命中时直接拦截并生成修改建议;人工审查者只需处理 AI 标记的“可疑清单”加上自己读代码的判断。上线半年,合入后线上事故率下降约 40%。

场景 2:开源社区的异步审查协作

阶段:协作与知识共享

解决的问题:开源项目成员分布在全球多个时区,无法同步开会;同时贡献者水平参差,需要一套纯粹依赖文字评论的审查流程来沉淀知识。

具体案例:Kubernetes 项目里,每次 PR 都需要至少两位维护者 approve 并打上 LGTM 标签才能合入。审查者用评论逐行提问,贡献者逐条回复;这些评论记录本身成为新人学习项目约定的教科书。

场景 3:新人通过被审查快速成长

阶段:人才培养与组织学习

解决的问题:新人入职后对系统约定、边界惯例一无所知,仅靠看文档吸收率极低;而代码审查中的具体评论,能让他们在真实的代码上下文中获得即时反馈。

具体案例:一位新同学第一次提交“查询订单接口”的 PR,审查者评论“这里没考虑上游超时,超时后要不要降级?”他顺着评论理解了公司整套超时治理和降级方案。三个月后他已经能在审查别人的 PR 时给出同样的提醒。

Python 演示

python46 行
class ReviewBot:    """模拟一位代码审查助手:按小步快跑原则检查 PR"""     def __init__(self, max_lines=200):        self.max_lines = max_lines        self.pr_list = []        self._check_count = 0     def check_pr(self, pr_id, diff_text, author):        self._check_count += 1        lines = diff_text.strip().splitlines()        added = [ln for ln in lines if ln.startswith('+') and not ln.startswith('+++')]        problems = []        if len(added) > self.max_lines:            problems.append('改动超过 {} 行,建议拆分为多个小 PR'.format(self.max_lines))        for ln in added:            s = ln[1:].strip()            if 'print(' in s:                problems.append('发现调试打印: ' + s[:40])            if 'TODO' in s or 'FIXME' in s:                problems.append('发现遗留标记: ' + s[:40])            for kw in ('password', 'token', 'secret'):                if kw in s.lower():                    problems.append('发现疑似敏感信息: ' + s[:40])        ok = len(problems) == 0        self.pr_list.append({'id': pr_id, 'author': author, 'ok': ok, 'problems': problems})        return ok, problems     def summary(self):        passed = sum(1 for pr in self.pr_list if pr['ok'])        total = len(self.pr_list)        return '共审查 {0} 个 PR,通过 {1} 个,通过率 {2:.0%}'.format(            total, passed, passed / total if total else 0)  if __name__ == '__main__':    bot = ReviewBot(max_lines=50)    demo_prs = {        'PR-101': ('小明', '+def login(user, pwd):\n+    print("debug")\n+    return check(user, pwd)'),        'PR-102': ('小红', '+def logout(user):\n+    session.clear(user)\n+    return True'),        'PR-103': ('小刚', '+TOKEN = "sk-123456"\n+def call_api():\n+    return fetch(TOKEN)'),    }    for pr_id, (author, diff) in demo_prs.items():        ok, problems = bot.check_pr(pr_id, diff, author)        print(pr_id, '通过' if ok else '需修改', problems)    print(bot.summary())
目的:用不到 50 行实现一个迷你“审查机器人”,模拟代码审查中最基础的三道检查:变更规模门禁、调试残留扫描、敏感信息拦截。
  1. added = [ln for ln in lines if ln.startswith('+') and not ln.startswith('+++')]从 diff 文本里过滤出真正“新增的代码行”,这是审查者要重点看的部分。
  2. if len(added) > self.max_lines:小步快跑原则落地:改动行数超阈值就建议拆分 PR。
  3. if 'print(' in s:把调试打印当嫌疑犯抓出来,这是低级但高频的漏网问题。
  4. for kw in ('password', 'token', 'secret')敏感信息扫描,对应“工具与自动化”一节里的金属探测仪。
  5. ok = len(problems) == 0只要发现问题就判“需修改”,模拟人工审查的否决逻辑。
  6. passed = sum(1 for pr in self.pr_list if pr['ok'])统计通过率,监控团队审查质量的哨兵指标。

常见误区

误区“同事写了一段我看不太懂的代码,但既然他敢交上来,应该没问题。我直接点 Approve 算了,又省时间又给人情。”

正解橡皮图章式批准不是人情,是失职。代码审查的本质是“多人分担风险”,你的 Approve 意味着“我理解这段变更并认为它没问题”。没读懂却批准,等于把风险原封不动推给下游。更合理的做法是评论“这部分我不熟,请作者补充解释”或指定熟悉该模块的同事来审,而不是假装看懂了。老陈宁可等阿敏回来再上菜,也不想让没尝过的菜上菜单。

为何常见:怕得罪人、怕显得自己水平低、想快速结束任务,都是人性弱点;加上多数平台不统计“快速批准”的质量,让人产生了“没人会发现”的错觉。

误区“一个功能改了二十个文件,等全部做完一起提交一次审完,省得来回打断思路。”

正解大 PR 恰恰是审查质量的杀手。人的注意力按指数衰减(A(t)=A₀e^{-t/τ}),超过 400 行的变更审到后面基本在走神。大 PR 还会让审查者望而生畏,拖到积压,形成恶性循环。正确姿势是“小步快跑”:把功能拆成多个逻辑闭环的小 PR,每个 200-400 行,审查者在注意力黄金期内一次审完。就像阿敏每次只尝四五道菜,而不是攒一桌满汉全席一次性点评。

为何常见:人们容易用“写代码的效率”来度量“交付效率”,忽略了等待时间、返工成本都藏在大 PR 的延迟里。

误区“CI 全绿、审查者也 Approve 了,这段代码肯定没问题,可以放心部署了。”

正解代码审查是“概率性地找错”,不是“形式化证明”。它靠的是人类注意力的抽样,注定会漏掉并发竞态、极端数据分布下的问题。审查通过只代表“在几位工程师的认知范围内没有发现明显问题”。所以要保留自动化测试、灰度发布、监控告警这些后续防线——审查是门禁,不是保险箱。

为何常见:人脑天然喜欢“确定性”的结论,绿勾、Approve 标签会给大脑一个“完成”的信号,从而放松警惕。

误区“我刚入职三个月,别人的代码我都看不懂,还是等成了大牛再参与审查吧。”

正解新人参与审查恰恰是成长最快的方式。审查时你不一定要挑逻辑错,可以问“为什么要这样设计”“这个函数是干嘛的”——这些提问会迫使作者重新梳理设计,也让你快速了解系统。代码审查的文化本就建立在心理安全感之上:好奇型提问(N_question)越多,团队越健康。新人那句“我不懂”,往往能帮团队发现“文档缺失”“命名歧义”这些资深者已经麻木的问题。

为何常见:把“审查”误解为“挑错表演”,以为只有水平更高的人才有资格评论,忽视了审查的双向学习属性。

误区“人家都评论了,我不改就是不配合。全听他的,这样总没错了吧?”

正解代码审查是“双向负责”,不是“单人裁决”。作者对代码的上下文理解通常更深,若认为审查意见不合理,应该给出依据并说明理由;审查者也可能误判。健康的讨论是“作者解释 → 审查者重新判断 → 达成共识”。如果一味屈从,代码设计会被“评论最多的人”主导,而非“最合理的方案”主导。老陈也驳回阿敏的提议——因为她不懂火候,他懂。

为何常见:权力距离感和怕冲突心理让人倾向于“服从权威”,忽略了审查本质是平等的技术讨论。

面试题

Q1. 代码审查最核心的目标是什么?

单选题 · easy

  • A.尽早发现并修复缺陷← 正确答案
  • B.展示审查者的技术能力
  • C.控制团队成员的提交权限
  • D.用人工检查替代自动化测试

答案:A。代码审查的核心是尽早发现缺陷,因为修复成本随阶段指数增长。B 把审查当个人秀是典型误区;C 是权限管理,与审查无关;D 方向相反,审查与自动化测试互补而非替代。

Q2. “橡皮图章式审查”指什么?

单选题 · easy

  • A.对代码细节逐行严格核对
  • B.不细读代码就批准变更← 正确答案
  • C.使用电子印章签署代码
  • D.只审查修改过的动态模块

答案:B。橡皮图章(rubber stamp)指审查者没有真正理解代码就快速点击批准,像盖章一样走过场。它比不审查更危险,因为制造了“已把关”的错觉。A 是认真审查的反面,C 是字面误解,D 与图章无关。

Q3. 小步快跑原则推荐的单次审查规模是?

单选题 · mid

  • A.尽可能大以提升复用效率
  • B.200-400 行以内最理想← 正确答案
  • C.跟代码总量保持同比例
  • D.只限制文件的修改个数

答案:B。小步快跑原则建议每次 PR 控制在 200-400 行左右,这与注意力衰减规律一致:超过该规模,审查者后半程效率断崖式下跌。A 是反面,C、D 没有依据。

Q4. 审查速率公式 v=L/T 中,T 表示什么?

单选题 · mid

  • A.变更新增的代码行数
  • B.本次发现的缺陷数目
  • C.本次审查花费的时间← 正确答案
  • D.代码仓库总文件数量

答案:C。v=L/T 中的 L 是新增代码行数,T 是审查耗时,v 表示每小时有效复核的代码量。行业经验 200-400 行/小时合适,超过 500 行/小时意味着审查可能流于形式。A 是 L,B、D 与该公式无关。

Q5. 成本倍增模型中,编码阶段引入的缺陷拖到发布后修复,成本约为编码阶段的多少倍?

单选题 · extreme

  • A.大约是五倍
  • B.大约是三十倍
  • C.大约是一百倍
  • D.大约是二百四十倍← 正确答案

答案:D。经典成本曲线为需求 1 : 设计 6 : 编码 30 : 测试 240。编码阶段发现修掉要 30 份成本,拖到发布后往往要到 240 份,约 8 倍甚至更高。答案 D 对应经典的“测试阶段”数值——这条曲线是“为何要审”一节的核心论据。

Q6. 异步工具审查的优点有哪些?

多选题 · mid

  • A.不受地理与时间限制← 正确答案
  • B.审阅记录自动留存← 正确答案
  • C.面对面沟通效率提升
  • D.强制所有人参与评审

答案:AB。异步审查通过 PR 平台进行,评论记录天然留痕、可追溯,也允许分布在不同时区的成员随时参与。C 是同步结对审查的优点;D 是流程制度问题,与异步工具本身无关。

Q7. 下列哪些属于 CI 门禁可自动执行的检查?

多选题 · hard

  • A.静态代码规范扫描← 正确答案
  • B.构建与单元测试集合← 正确答案
  • C.合并冲突自动修复
  • D.人脑综合设计合理性

答案:AB。静态扫描和单元测试/构建都能在流水线里全自动执行,这就是“仪器先于舌头”的一环。C 的冲突修复需要人判断语义,不能自动修;D 属于人类审查者(R_human)的职责,自动化做不了。

Q8. 结对审查中两个人的角色是什么?

单选题 · easy

  • A.开发者和项目经理
  • B.写代码者和实时检查者← 正确答案
  • C.测试工程师和运维人员
  • D.产品经理和架构设计师

答案:B。结对审查里一个人敲代码,另一个人实时盯着逻辑、边界、风格,边写边审,反馈最快。项目经理、产品经理通常不参与实时编码审查;测试和运维的角色在结对中并不固定。

Q9. 一条好的审查评论应该具备哪些特征?

多选题 · mid

  • A.只提问题不给建议
  • B.引用具体代码行证据← 正确答案
  • C.对人不对事的批评
  • D.给出替代实现方案← 正确答案

答案:BD。好评论对事不对人,引用具体行号并给出替代方案,让作者能立刻理解并行动。A 只指出问题不帮人改进,体验差;C 是“建设性批评”的反面,会摧毁心理安全感。

Q10. 代码审查中“双向负责”原则的含义是什么?

单选题 · mid

  • A.作者必须全盘接受意见
  • B.审查者独享最终决定权
  • C.作者与审查者共同维护质量← 正确答案
  • D.由主管强制拍板定论

答案:C。双向负责指作者有责任解释设计意图、捍卫合理方案,审查者有责任尊重上下文、给出依据充分的判断,双方共同对最终合入的质量负责。A 是盲目服从,B 是一言堂,D 是行政命令,都与审查的平等讨论本质相悖。