团队实践
这一课你将能做到
- 用 CODEOWNERS 文件实现「谁写的代码谁负责审」的自动化分配
- 设计团队的 Review SLA 并监控执行(首响时间、合并时长、PR 大小分布)
- 处理「新人不敢审」「资深审不过来」「跨团队互审」等典型组织问题
为什么要学
Code Review 做到最后是组织问题,不是技术问题。技术工具(CI、Lint、Checklist)解决的是「怎么审」;团队实践解决的是「谁来审、多久审完、审不动怎么办」。
人话:你配置了再好的工具,如果没人知道该找谁审、PR 挂一周没人看、新人不敢点 Approve,review 文化就死了。
先建立图像
团队 Review 健康度仪表盘
分配机制 时效指标 参与广度
├─ CODEOWNERS 自动分配 ├─ 首响时间 < 24h ├─ 全员参与(不只资深)
├─ 负载均衡(轮流) ├─ 合并周期 < 48h ├─ 新人也敢审
└─ 紧急通道(hotfix) ├─ PR 大小中位数 < 300 行 └─ 跨团队互审
目标状态:
「任何 PR 提交后 24h 内有人开始审,
48h 内有结论,作者知道该找谁」
跟着做
步骤 1:配置 CODEOWNERS
.github/CODEOWNERS:
# 全局兜底:任何文件改动都至少通知这两个人
* @zhangsan @lisi
# 后端核心模块:资深后端审
/src/main/java/com/example/course/ @backend-senior
/src/main/java/com/example/payment/ @backend-senior @wangwu
# 数据库迁移:必须 DBA 审
/src/main/resources/db/migration/ @dba-team
# 前端
/web/ @frontend-team
/web/components/payment/ @frontend-team @zhaoliu
# 基础设施:DevOps 审
/Dockerfile @devops-team
/k8s/ @devops-team
/.github/workflows/ @devops-team
# 文档:任何人都可以审,但至少一人
*.md @zhangsan @lisi
规则:
- 后面的规则覆盖前面的(越具体越优先)
- 文件被改动时,对应的 owner 自动被加为 reviewer
- 可以配置「必须 owner approve 才能合并」(Branch protection → Require review from Code Owners)
步骤 2:配置 Review 负载均衡
避免「所有 PR 都找同一个资深」:
# .github/workflows/assign-reviewer.yml
name: Auto Assign Reviewer
on:
pull_request:
types: [opened]
jobs:
assign:
runs-on: ubuntu-latest
steps:
- uses: actions/github-script@v7
with:
script: |
// 从 CODEOWNERS 解析候选人,按当前 open PR 数排序,选负载最低的
const reviewers = ['zhangsan', 'lisi', 'wangwu'];
const { data: openPRs } = await github.rest.pulls.list({
owner: context.repo.owner,
repo: context.repo.repo,
state: 'open'
});
const load = {};
reviewers.forEach(r => load[r] = 0);
openPRs.forEach(pr => {
pr.requested_reviewers.forEach(r => {
if (load[r.login] !== undefined) load[r.login]++;
});
});
const selected = reviewers.reduce((a, b) =>
load[a] <= load[b] ? a : b
);
await github.rest.pulls.requestReviewers({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: context.issue.number,
reviewers: [selected]
});
步骤 3:定义并监控 SLA
团队 SLA 约定(写进 Wiki + 入职培训):
1. 首响时间:PR 提交后 24h(工作日)内必须有 reviewer 评论
2. 合并周期:从提交到合并 < 48h(排除周末)
3. PR 大小:新增 + 删除行数 < 400 行
4. 超时处理:超过 48h 没人审,作者可以在群里 @ 任何人
5. 紧急通道:[HOTFIX] 前缀的 PR 可以 1 人 approve 即合并,
但必须 24h 内补正式 review
监控:用 GitHub API 或第三方工具(如 LinearB、Swarmia)拉数据:
# 拉取最近 30 天的 PR 数据
gh api graphql -f query='
{
repository(owner: "myorg", name: "myrepo") {
pullRequests(last: 100, states: MERGED) {
nodes {
number
createdAt
mergedAt
additions
deletions
reviews(first: 10) {
nodes {
createdAt
state
}
}
}
}
}
}'
- 首响时间 = 第一个 review 评论时间 - PR 创建时间
- 合并周期 = 合并时间 - 创建时间
- PR 大小 = additions + deletions
本周 Review 健康度
- 平均首响时间:18h(目标 < 24h)✓
- 平均合并周期:36h(目标 < 48h)✓
- PR 大小中位数:280 行(目标 < 400)✓
- 超 48h 未合并 PR:3 个(需关注)
- #234: 支付模块重构(1200 行,建议拆分)
- #236: 新人提交,reviewer 未响应(已介入)
- #239: 依赖外部团队接口(已协调)
步骤 4:解决「新人不敢审」
新人:我经验不够,不敢给意见,还是等资深来审吧。
结果:所有 PR 都堆在资深身上,资深 burnout,新人成长慢。
策略:
1. 新人先做「学习性 review」——只看不 approve,评论里提问
(「这里的 @Transactional 是怎么生效的?」)
2. 给新人分配「低风险 PR」——文档、测试、简单 CRUD
3. 资深做「二次确认」——新人 approve 后,资深快速过一遍
(5 分钟),没问题就合并
4. 明确告诉新人:「你审出问题我负责,你漏审了我兜底」
——降低心理压力
5. 每月 review 分享会:资深讲解「我是怎么审这个 PR 的」,
新人学习思路
步骤 5:解决「资深审不过来」
资深每天审 10 个 PR,每个 PR 平均 30 分钟,一天 5 小时没了。
结果:资深开始敷衍(LGTM),review 质量下降。
策略:
1. 分层审查:
- 低风险 PR(< 100 行,非核心模块):中级工程师即可
- 中风险 PR(100-400 行,核心模块):资深必须审
- 高风险 PR(> 400 行,支付/订单等):资深 + 架构师双审
2. 时间盒:
- 资深每天固定 2 个 1 小时的 review 时段
- 其他时间不看 PR,专注编码
3. 授权:
- 培养 2-3 个中级工程师成为「模块 owner」
- 模块 owner 可以 approve 自己模块的 PR
4. 减少无效 PR:
- 鼓励作者先自测(CI 全绿、本地验证)
- 拒绝「我写完就提了,没看代码」的 PR
步骤 6:跨团队互审
场景:前端团队改了后端 API 的调用方式,需要后端审。
策略:
1. CODEOWNERS 配置跨团队 owner:
/web/api/course.ts @frontend-team @backend-liaison
2. 指定「接口联络人」:
每个团队指定 1 人作为接口 liaison,负责跨团队 review
3. 契约优先:
- OpenAPI / GraphQL schema 文件必须双方 approve
- 契约变更提前在 RFC 讨论,而不是 PR 阶段才吵架
4. 定期同步:
- 每周 30 分钟「接口对齐会」,双方同步最近的接口变更
讲清楚要点
- CODEOWNERS 是「责任到人」的自动化:改了什么文件,谁必须审,机器说了算,不靠人记。
- SLA 必须监控:定了 SLA 但不监控,等于没定。每周看数据,超时的 PR 要有人跟进。
- 新人参与是文化问题:不是「新人能力不够」,而是「团队没给新人参与的路径」。从「学习性 review」开始,逐步授权。
- 资深是稀缺资源:不能让资深成为瓶颈。分层审查、时间盒、授权模块 owner,三个手段组合使用。
- 跨团队互审靠契约:OpenAPI / GraphQL schema 是双方的「合同」,合同变更必须双方同意。
你可能会懵的地方
-
CODEOWNERS 会不会让 owner 成为瓶颈?
会,如果 owner 只有一个人。解法:每个模块至少配 2 个 owner;owner 休假时指定 backup;非核心模块不强制 owner approve。
-
SLA 会不会导致 reviewer 敷衍?
会,如果只考核「时间」不考核「质量」。解法:SLA 只是「最低要求」,质量靠 Checklist + CI + 定期抽查保证。同时给 reviewer 足够的时间盒,而不是「随时待命」。
-
新人 review 漏了问题,线上出事故,算谁的?
算团队的,不是新人的。Review 是团队活动,不是个人责任。如果团队让新人独自承担高风险 PR 的 review 责任,是团队流程有问题。
-
跨团队 review 意见不一致怎么办?
契约优先:OpenAPI schema 是合同,双方必须遵守。如果是「实现细节」的分歧,由实现方决定。如果是「接口设计」的分歧,升级到架构师或技术委员会。
-
小团队(3-5 人)需要 CODEOWNERS 吗?
不需要。直接在群里喊一声就行。CODEOWNERS 是给「不知道该找谁审」的中大型团队用的。小团队的重点是 SLA 和「别让一个人审所有 PR」。
错法对照
| 错法 | 问题 | 正解 |
|---|
| 所有 PR 都找资深审 | 资深 burnout | 分层审查 + 授权模块 owner |
| 定了 SLA 但不监控 | SLA 形同虚设 | 周报展示数据,超时跟进 |
| 新人只看不审 | 新人成长慢,资深累死 | 学习性 review → 低风险授权 → 资深兜底 |
| 跨团队 review 靠口头 | 接口变更没人知道 | CODEOWNERS + 联络人 + 契约文件 |
| PR 挂一周没人审 | 作者失去信心 | SLA + 超时提醒 + 群里 @ 机制 |
卡点急救
-
资深请假一周,PR 堆积:提前指定 backup reviewer;非核心 PR 可以由中级工程师审;紧急 PR 远程联系资深。
-
新人不敢点 Approve:明确告诉新人「你 approve 后我会快速过一遍,有问题我兜底」;前 10 次 review 由资深陪同(结对 review)。
-
跨团队 PR 卡住:双方在群里 @ 各自的接口联络人;联络人 30 分钟内响应;如果联络人也无法解决,升级到双方 tech lead。
面试常问
-
怎么设计团队的 Code Review 流程?
四层:① 分配机制(CODEOWNERS 自动分配 + 负载均衡);② 时效约定(SLA:24h 首响 / 48h 合并);③ 质量控制(Checklist + CI + 分层审查);④ 文化建设(新人培养 + 正面反馈 + 定期回顾)。最好带一个「我们当时遇到 XX 问题,用 YY 方案解决」的具体例子。
-
怎么平衡「review 质量」和「review 速度」?
不矛盾。PR 越小,质量越高、速度越快。手段:① 控制 PR 大小(< 400 行);② CI 前置(不过 CI 不审);③ 分层审查(低风险 PR 中级工程师审);④ 时间盒(资深每天固定 2 小时 review)。
-
怎么培养新人的 review 能力?
三步:① 学习性 review——新人只评论提问,不 approve;② 低风险授权——分配文档/测试/简单 CRUD 的 PR 给新人;③ 资深兜底——新人 approve 后资深快速过一遍。配合「每月 review 分享会」让资深讲解思路。
自测三问
- CODEOWNERS 文件的作用是什么?规则匹配的优先级是怎样的?
- 为什么说「定了 SLA 但不监控等于没定」?
- 团队里资深工程师成为 review 瓶颈,有哪些解法?
小结一句话
团队实践的核心是「让正确的行为成为默认行为」——CODEOWNERS 自动分配、SLA 监控时效、分层审查保护资深、新人路径保证传承。
延伸
- GitHub CODEOWNERS 文档
- 《Accelerate》(Nicole Forsgren)—— 工程效能的四个关键指标
- 《Team Topologies》(Matthew Skelton)—— 团队结构与协作模式
- 下一课:综合练习——Review 本站 PR 模拟。