open-code-review:从零搭建自动化代码评审体系
1. 从标题说起open-code-review 到底在解决什么问题第一次看到 open-code-review 这个标题我脑子里蹦出来的第一个念头是这不就是把代码评审这件事从“人盯人”变成“工具盯人”吗但仔细一琢磨事情远没有这么简单。代码评审Code Review这件事在任何一个有规模的研发团队里都是绕不开的环节它既是质量守门员又是知识传播的渠道还是团队协作的润滑剂。可现实情况是绝大多数团队的代码评审都做得不怎么样——要么流于形式要么变成吵架现场要么因为节奏太慢拖垮了整个迭代周期。open-code-review 这个标题里的“open”我理解有两层意思。第一层是“开放的”意味着这套评审机制或者工具是开源的、可定制的、不绑定特定平台的第二层是“公开的”意味着评审过程是透明的所有人都能看到谁在什么时候对哪段代码提出了什么意见以及这些意见最终是怎么被处理的。这两层含义叠加在一起指向的是一个核心诉求让代码评审这件事变得可追溯、可度量、可改进。那它到底能做什么我把它拆成三个层面来看。最基础的层面它是一个自动化检查工具能在代码提交的时候自动跑一遍静态分析、风格检查、单元测试覆盖率检测把那些低级问题挡在人工评审之前。中间层面它是一个评审流程管理平台能自动分配评审人、追踪评审状态、统计评审时长、生成评审报告。最高层面它是一个质量度量系统能通过评审数据反推代码质量的趋势发现团队协作中的瓶颈甚至预测哪些模块更容易出问题。适合谁来参考我觉得三类人最应该关注。第一类是技术负责人或者架构师他们需要一套可落地的方案来规范团队的评审流程第二类是一线开发者他们想知道怎么让自己的代码更快通过评审怎么在评审中提出有价值的意见第三类是工具链工程师他们需要把评审工具集成到现有的 CI/CD 流水线里让整个研发流程更顺畅。我见过太多团队在代码评审上踩坑了。有的团队把评审当成走过场点个“同意”就完事结果线上事故频发有的团队评审标准不统一同一个人写的代码张三评审说没问题李四评审说一堆问题搞得开发者无所适从还有的团队评审周期太长一个 PR 挂了一周没人理最后只能强行合并评审形同虚设。open-code-review 要解决的就是这些实实在在的痛点。2. 整体设计与思路拆解为什么这样设计评审流程2.1 评审左移把问题挡在合并之前代码评审最核心的设计思路就是“左移”——把质量检查的环节尽量往前移。传统模式下代码写完、合并、部署到测试环境测试同学发现问题再打回来这个循环太长了。open-code-review 的思路是在代码提交的那一刻就开始介入通过预提交钩子pre-commit hook跑一轮快速检查包括代码格式、静态分析、敏感信息扫描等。这一步能在几秒钟内完成开发者还没离开工位就能收到反馈修改成本极低。我实测下来预提交钩子能拦掉大约六成到七成的低级问题。什么叫低级问题比如缩进不一致、变量命名不符合规范、console.log 没删干净、硬编码的密钥、明显的空指针风险。这些问题如果流到人工评审阶段评审人得花时间指出来开发者得花时间改一来一回至少半小时没了。用工具自动拦掉省下来的时间可以花在真正需要人类判断的逻辑设计、架构合理性、边界条件处理上。但这里有个坑要注意预提交钩子不能太重。我见过有的团队在 pre-commit 阶段跑完整的单元测试套件结果每次提交要等两三分钟开发者烦得不行最后集体绕过钩子。正确的做法是分层pre-commit 只跑秒级检查commit-msg 阶段检查提交信息格式pre-push 阶段跑单元测试和集成测试CI 阶段跑完整的质量门禁。每一层各司其职不要让任何一层承担它不该承担的责任。2.2 评审自动化让机器做机器擅长的事open-code-review 的第二个设计思路是“自动化优先”。人工评审应该聚焦在机器做不了的事情上比如业务逻辑是否正确、架构设计是否合理、代码可读性是否达标、是否有更好的实现方案。而那些机器能做的事——格式检查、静态分析、重复代码检测、圈复杂度计算、测试覆盖率统计——全部交给工具。我一般会配置这样一套自动化检查清单代码风格用 Prettier 或者 Black 这类格式化工具统一处理静态分析用 ESLint、Pylint、SonarQube 这类工具跑安全扫描用 Semgrep 或者 CodeQL 这类工具查依赖漏洞用 Dependabot 或者 Snyk 这类工具监控。这些工具跑出来的结果会以评论的形式自动贴到 PR 上评审人一眼就能看到哪些是机器已经确认没问题的哪些是需要人工判断的。这里有个经验之谈自动化检查的规则不要一次性全开。我刚开始搞的时候把 ESLint 的所有规则都打开了结果一个 PR 跑出来两百多条警告开发者直接崩溃了。正确的做法是分批启用规则先开最基础的错误级别规则等团队适应了再逐步加警告级别规则最后再加风格建议级别的规则。每加一批规则都要给团队一个缓冲期让大家有时间调整代码习惯。2.3 评审度量用数据驱动流程改进第三个设计思路是“度量驱动”。没有度量就没有改进代码评审这件事尤其如此。open-code-review 会收集一系列关键指标评审响应时间从 PR 创建到第一个人回复的时间、评审完成时间从 PR 创建到最终合并的时间、评审意见数量、评审意见采纳率、每个评审人的平均评审量、代码变更规模分布等。这些数据能说明很多问题。比如评审响应时间中位数超过 4 小时说明团队的评审节奏有问题可能需要设置轮值评审人制度比如某个模块的评审意见数量远高于其他模块说明这个模块的代码质量或者设计复杂度有问题需要重点关注比如某个评审人的意见采纳率特别低可能是他的评审标准太严苛或者表达方式有问题需要沟通调整。我踩过的一个坑是一开始只看评审完成时间觉得只要 PR 能在一两天内合并就行。后来发现有的 PR 虽然合并得快但评审意见很少基本上是“点同意”就过了。这种“快速通过”其实比“慢速通过”更危险因为问题被隐藏了。所以后来我加了一个指标叫“有效评审率”计算方式是有至少一条实质性评论的 PR 数量除以总 PR 数量。这个指标能反映出评审是不是真的在发生。3. 核心细节解析与实操要点从零搭建评审体系3.1 评审规则的制定什么该管什么不该管搭建评审体系的第一步是制定评审规则。规则不能太松太松了等于没有也不能太严太严了开发者会想办法绕过。我的经验是规则应该聚焦在“影响可维护性和正确性”的事情上而不是个人风格偏好。具体来说我会把评审规则分成三个层级。第一层是“必须修改”级别包括逻辑错误、安全漏洞、性能问题、缺少必要的测试、破坏向后兼容性的改动。这些问题一旦发现PR 必须修改后才能合并。第二层是“建议修改”级别包括命名不够清晰、注释缺失、代码重复、可以简化的复杂逻辑。这些问题评审人会提出来但开发者可以选择不改只要给出合理的理由。第三层是“仅供参考”级别包括个人风格偏好、替代实现方案、未来可能的优化方向。这些问题不影响合并只是作为讨论的起点。注意规则制定后一定要写成文档并且在团队内达成共识。我见过太多团队因为评审标准不统一而产生矛盾根本原因就是没有把规则显性化。文档不需要很长一页纸就够了关键是要让每个人都知道什么情况下该提什么问题。3.2 评审人的选择谁适合评审谁的代码评审人的选择是个技术活。选对了评审效率高、质量好选错了要么评审人看不懂代码要么评审人和开发者互相看不顺眼。我的做法是结合“代码所有权”和“负载均衡”两个原则来分配评审人。代码所有权是指每个模块都有相对固定的负责人这些人对模块的历史背景、设计决策、已知问题最了解评审起来最有发言权。但光靠代码所有权不行因为有的人会变成瓶颈所有相关 PR 都堆到他那里。所以还要加上负载均衡系统自动统计每个评审人当前待评审的 PR 数量优先分配给负载轻的人。实际操作中我会设置一个评审人池每个 PR 自动从池子里选 2 到 3 个评审人。选择逻辑是至少一个来自代码所有权列表至少一个来自负载最轻的评审人列表。这样既能保证评审质量又能避免某个人成为瓶颈。如果某个 PR 超过 24 小时没有人评审系统会自动提醒评审人超过 48 小时会自动升级给技术负责人。3.3 评审意见的表达怎么说才能让人接受评审意见的表达方式直接影响评审效果。同样一个问题说“你这里写错了”和说“这个地方我有点疑惑能不能解释一下为什么这样处理”效果完全不同。前者容易引发防御心理后者更容易开启对话。我总结了一个“评审意见三段式”的表达框架。第一段描述观察到的现象“我看到这里用了递归来实现深度可能达到几千层。”第二段说明潜在的影响“在极端情况下可能会导致栈溢出。”第三段提出建议或者提问“有没有考虑过用迭代的方式来实现或者加一个深度限制”这个框架的好处是它把“批评”变成了“讨论”把“你错了”变成了“我们一起看看”。还有一个细节评审意见要具体到行不要泛泛而谈。说“这个函数写得不好”没有意义说“这个函数的圈复杂度有 15建议拆成三个小函数”才有意义。open-code-review 这类工具通常支持行级评论一定要用起来让每条意见都能精确定位到代码。3.4 评审节奏的控制多快算快多慢算慢评审节奏是个容易被忽视但极其重要的因素。太快了评审人可能没仔细看就点了同意太慢了开发者等得心焦可能会强行合并或者放弃修改。我的经验值是小 PR少于 200 行变更应该在 4 小时内完成评审中 PR200 到 500 行应该在 24 小时内完成大 PR超过 500 行应该拆成多个小 PR 来评审。为什么是 200 行和 500 行这两个阈值因为根据我的观察评审人在一次评审中能有效处理的代码量大约是 200 到 400 行。超过这个量注意力会下降漏掉问题的概率会显著上升。所以我会在 CI 里加一个检查如果 PR 的变更行数超过 500 行自动打上“需要拆分”的标签并提醒开发者考虑拆分。提示拆分 PR 有个技巧可以按“重构”和“功能”分开。先提交一个纯重构的 PR把代码结构调整好评审通过后再提交功能变更的 PR。这样每个 PR 的意图都很清晰评审起来也更快。4. 实操过程与核心环节实现一步步搭建评审流水线4.1 环境准备与工具选型搭建 open-code-review 体系的第一步是选工具。工具选型要考虑三个因素团队的技术栈、现有的 CI/CD 平台、团队的规模。小团队5 人以下用 GitHub 或者 GitLab 自带的评审功能就够了配合一些轻量级的自动化检查工具。中等团队5 到 20 人可能需要引入专门的评审管理工具比如 Reviewable 或者 Phabricator。大团队20 人以上通常需要自建或者深度定制评审系统因为通用工具很难满足复杂的权限管理和流程定制需求。我以最常见的 GitHub 生态为例来说明具体配置。首先需要在仓库里添加几个配置文件。第一个是.github/CODEOWNERS用来定义代码所有权# 默认评审人 * tech-lead # 前端代码由前端团队评审 /src/frontend/ frontend-team # 后端 API 由后端团队评审 /src/api/ backend-team # 数据库迁移文件必须由 DBA 评审 /migrations/ dba-team第二个是.github/pull_request_template.md用来规范 PR 的描述## 变更类型 - [ ] 新功能 - [ ] Bug 修复 - [ ] 重构 - [ ] 文档更新 ## 变更描述 简要说明这个 PR 做了什么为什么要做 ## 测试情况 说明跑了哪些测试结果如何 ## 自查清单 - [ ] 代码已经过本地格式化 - [ ] 新增代码有对应的单元测试 - [ ] 没有提交敏感信息 - [ ] 相关文档已更新第三个是 CI 配置文件以 GitHub Actions 为例name: Code Review Checks on: pull_request: branches: [main, develop] jobs: lint: runs-on: ubuntu-latest steps: - uses: actions/checkoutv3 - name: Run linter run: | npm install npm run lint test: runs-on: ubuntu-latest steps: - uses: actions/checkoutv3 - name: Run tests run: | npm install npm run test -- --coverage security: runs-on: ubuntu-latest steps: - uses: actions/checkoutv3 - name: Run security scan uses: returntocorp/semgrep-actionv1 with: config: p/ci这套配置跑下来每个 PR 会自动触发三个检查代码风格检查、单元测试和覆盖率检查、安全扫描。检查结果会以评论的形式贴到 PR 上评审人一眼就能看到哪些检查通过了哪些没通过。4.2 评审流程的自动化配置工具装好了接下来要配置评审流程的自动化。核心目标是让 PR 从创建到合并的每一步都有明确的规则和自动化的推进机制。第一步是自动分配评审人。GitHub 原生支持基于 CODEOWNERS 的自动分配但功能比较基础。如果需要更复杂的分配逻辑可以用 GitHub Actions 配合 API 来实现。比如下面这个 Action会在 PR 创建时自动从评审人池里选两个负载最轻的人// .github/workflows/auto-assign-reviewer.js const { Octokit } require(octokit/rest); module.exports async ({ github, context }) { const octokit new Octokit({ auth: process.env.GITHUB_TOKEN }); const prNumber context.payload.pull_request.number; const repo context.repo; // 获取评审人池 const reviewers [alice, bob, carol, dave]; // 获取每个人的待评审 PR 数量 const workloads await Promise.all( reviewers.map(async (reviewer) { const { data: prs } await octokit.pulls.list({ ...repo, state: open, per_page: 100, }); const count prs.filter((pr) pr.requested_reviewers?.some((r) r.login reviewer) ).length; return { reviewer, count }; }) ); // 选负载最轻的两个人 workloads.sort((a, b) a.count - b.count); const selected workloads.slice(0, 2).map((w) w.reviewer); await octokit.pulls.requestReviewers({ ...repo, pull_number: prNumber, reviewers: selected, }); };第二步是设置评审超时提醒。我一般会配置两个提醒节点PR 创建后 12 小时无人评审自动在 PR 上评论提醒24 小时无人评审自动在团队频道发消息提醒。这个可以用 GitHub Actions 的 schedule 触发器来实现也可以用专门的提醒工具。第三步是合并前的质量门禁。在 PR 合并之前必须满足以下条件至少两个评审人点了“同意”、所有 CI 检查通过、没有未解决的评审意见、PR 描述完整。这些条件可以在仓库设置里的 branch protection rules 里配置也可以用 GitHub Actions 自定义更复杂的逻辑。4.3 评审数据的收集与可视化评审流程跑起来之后下一步是收集数据并可视化。数据是改进的依据没有数据就只能凭感觉。我一般会收集以下几类数据指标名称计算方式目标值说明评审响应时间PR 创建到第一条评论的时间 4 小时反映团队的响应速度评审完成时间PR 创建到合并的时间 24 小时反映整体评审效率有效评审率有实质评论的 PR / 总 PR 80%反映评审是否真的在发生意见采纳率被采纳的意见 / 总意见60%-80%太低说明意见质量差太高说明评审太宽松平均 PR 规模变更行数的中位数 300 行反映 PR 拆分情况评审人负载每人每周评审的 PR 数5-15 个太低说明分配不均太高说明负担过重这些数据可以用 GitHub Actions 定期抓取存到数据库里然后用 Grafana 或者 Metabase 做可视化。我一般会做一个评审健康度看板每周自动生成报告发到团队频道。看板上用红黄绿三色标识每个指标的状态绿色表示达标黄色表示接近阈值红色表示需要关注。提示数据收集要注意隐私边界。只收集与评审流程相关的数据不要收集个人的代码行数、提交次数这类容易引发焦虑的指标。评审数据是用来改进流程的不是用来考核个人的。4.4 评审文化的建设从制度到习惯工具和流程都搭好了最后一步也是最难的一步让评审成为团队的文化习惯。我见过很多团队工具配置得很完善但评审还是做不起来根本原因是文化没跟上。建设评审文化我会从三个方面入手。第一是领导带头。技术负责人要亲自参与评审认真写评审意见及时回复别人的意见。领导的态度决定了团队的态度如果领导自己都不认真评审下面的人更不会当回事。第二是正向激励。定期评选“最佳评审意见”把那些发现了重要问题、提出了建设性建议的评审意见拿出来分享让大家看到好的评审是什么样的。第三是持续改进。每个月开一次评审复盘会讨论上个月的评审数据找出问题调整规则优化流程。我踩过的一个坑是一开始太急于求成想在一个月内把评审体系建起来结果规则定得太细流程搞得太复杂开发者怨声载道。后来调整了策略先跑最小可用的流程只做最基本的自动化检查和人工评审等大家适应了再逐步加规则、加工具。整个过程花了大概三个月才算是真正跑顺了。5. 常见问题与排查技巧实录5.1 评审流于形式怎么办这是最常见的问题。表现是PR 创建后很快就有人点“同意”但没有任何实质性评论或者评审人只关注格式问题不关注逻辑问题或者评审意见都是“LGTM”Looks Good To Me但代码合并后 bug 频出。排查思路先看数据。如果有效评审率低于 50%说明评审确实流于形式。然后分析原因。可能的原因有评审人太忙没时间仔细看、评审人看不懂代码、评审人觉得提意见没用、评审标准不清晰。针对不同原因采取不同措施。太忙的话调整负载看不懂的话换更熟悉代码的人来评审觉得没用的话要建立意见反馈机制让评审人看到自己的意见被采纳标准不清晰的话把规则写得更具体。我的经验是解决这个问题的关键是“让评审人看到价值”。我会定期统计每个评审人提出的意见被采纳的情况然后在团队里公开表扬那些提出了重要意见的人。同时我也会让开发者主动感谢评审人比如在 PR 合并后回复一句“谢谢这个边界条件确实没考虑到”。这些小小的正反馈积累起来评审文化就慢慢建立起来了。5.2 评审周期太长怎么破评审周期长的表现是PR 创建后几个小时甚至几天没人理开发者催了又催最后只能强行合并。这个问题在小团队里尤其常见因为每个人都很忙评审优先级总是排在最后。排查思路先看评审响应时间的中位数和分布。如果中位数超过 8 小时说明问题比较严重。然后看是所有人都慢还是特定的人慢。如果是个别人慢可能是负载分配不均如果是所有人都慢可能是流程设计有问题。解决这个问题我会采取几个措施。第一是设置评审 SLA服务级别协议比如“工作时间内 4 小时内必须响应”。第二是引入轮值评审人制度每天指定一个人专门负责当天的评审其他事情可以放一放。第三是设置自动提醒PR 创建后 2 小时、4 小时、8 小时分别提醒一次。第四是如果某个 PR 超过 24 小时没人评审自动升级给技术负责人由技术负责人指定人评审或者自己评审。5.3 评审意见引发冲突怎么处理评审意见引发冲突的表现是评审人和开发者就某个问题争论不休谁也说服不了谁最后不欢而散。这种情况虽然不常见但一旦发生对团队氛围的伤害很大。排查思路先看冲突的性质。如果是技术观点分歧比如“用递归还是用迭代”这种冲突其实是好事说明大家在认真思考。如果是沟通方式问题比如“你这里写得太烂了”这种冲突就需要干预。如果是标准不统一比如“上次这样写你说可以这次又说不行”这种冲突说明规则需要明确。处理技术观点分歧我的做法是如果争论超过三个回合还没有结论就升级到技术负责人或者架构师来裁决。裁决的原则是“以项目整体利益为准”而不是“谁对谁错”。同时我会把这类分歧记录下来作为后续制定规则的参考。处理沟通方式问题我会私下和评审人沟通提醒他注意表达方式用“提问”代替“断言”。处理标准不统一问题我会把相关规则写进文档并且在团队会议上同步。5.4 常见问题速查表问题现象可能原因排查方法解决措施评审响应慢评审人太忙、分配不均查看评审人负载数据调整分配算法、设置轮值制度评审意见少评审人不认真、标准不清查看有效评审率明确规则、正向激励、领导带头评审周期长流程复杂、PR 太大查看 PR 规模分布拆分 PR、简化流程、设置 SLA评审冲突多标准不统一、沟通方式差分析冲突案例统一规则、培训沟通技巧自动化检查太慢检查项太多、工具太重查看 CI 耗时分层检查、并行执行、缓存依赖开发者绕过评审流程太繁琐、不认同价值查看绕过记录简化流程、解释价值、领导示范5.5 独家避坑技巧第一个技巧评审规则要“先松后紧”。刚开始搞评审的时候规则越少越好只拦最严重的问题。等团队适应了评审这件事再逐步加规则。我见过有的团队一上来就搞几十条规则结果开发者觉得评审就是找茬抵触情绪很大。第二个技巧评审意见要“对事不对人”。说“这个函数有问题”而不是“你有问题”。说“这里可能会空指针”而不是“你怎么又忘了判空”。语言上的细微差别对团队氛围的影响很大。第三个技巧评审数据要“用来看趋势不是用来考核”。评审数据可以用来发现流程问题但不能用来考核个人绩效。一旦评审数据和绩效考核挂钩评审就会变味大家会为了数据好看而评审而不是为了质量而评审。第四个技巧评审工具要“轻量优先”。不要一上来就搞一套复杂的评审系统先用 GitHub 或者 GitLab 自带的评审功能跑起来等确实有需求了再引入更复杂的工具。工具越复杂维护成本越高团队的学习成本也越高。第五个技巧评审文化要“从上到下”。技术负责人如果不认真评审下面的人就不会认真。所以我会建议技术负责人每周至少花两个小时在评审上并且把评审意见写得详细、具体、有建设性。领导的行为是最好的示范。6. 评审体系的持续演进6.1 从人工评审到智能辅助评审体系跑顺之后下一步可以考虑引入智能辅助。比如用静态分析工具自动识别常见的代码坏味道用机器学习模型预测哪些代码变更更容易引入 bug用自然语言处理技术自动生成评审意见的草稿。这些技术目前还不是很成熟但可以作为辅助手段减轻评审人的负担。我试过用一些代码分析工具来自动生成评审意见效果参差不齐。对于格式问题、明显的逻辑错误、安全漏洞工具的表现很好基本能替代人工。但对于架构设计、业务逻辑、可读性这些需要上下文理解的问题工具还差得远。所以我的策略是机器能做的全部交给机器机器做不了的才让人来做。这样评审人可以把精力集中在真正需要人类判断的事情上。6.2 从单点工具到研发流程集成评审体系不应该是一个孤立的环节而应该和整个研发流程深度集成。比如需求管理工具里的需求 ID 可以自动关联到相关的 PRCI/CD 流水线里的部署记录可以关联到对应的评审记录监控系统里的告警可以追溯到引入问题的代码变更和评审记录。这种端到端的集成能让问题定位更快也能让评审的价值更直观地体现出来。我在一个项目里做过这样的集成每个 PR 的描述里必须填写关联的需求 IDCI 流水线会自动检查这个需求 ID 是否存在、是否已经排期、是否已经开发完成。如果需求 ID 不存在或者状态不对PR 就不能合并。这个检查看起来很简单但效果很好它确保了每个代码变更都有明确的业务目的避免了“为了改代码而改代码”的情况。6.3 从团队实践到组织标准当一个团队的评审体系跑成熟之后可以考虑把它推广到整个组织。推广的关键是“标准化”和“可配置化”。标准化是指评审的基本流程、核心指标、质量门禁要统一不能每个团队一套。可配置化是指具体的规则、工具、阈值可以根据团队的特点来调整不能一刀切。我参与过一次组织级的评审标准制定最大的体会是标准要“抓大放小”。核心的流程和质量门禁必须统一比如“所有代码变更必须经过评审”“所有 PR 必须通过 CI 检查”“评审响应时间不超过 4 小时”。但具体的工具选择、规则细节、指标阈值可以留给团队自己决定。这样既能保证基本的质量水平又能尊重团队的差异性。6.4 我个人的一些体会搞了这么多年的代码评审我最大的体会是评审不是目的质量才是。评审只是手段之一而且不是唯一的手段。单元测试、集成测试、静态分析、灰度发布、监控告警这些都是保证质量的手段。评审的价值在于它能发现那些自动化手段发现不了的问题比如设计缺陷、逻辑漏洞、可维护性问题。另一个体会是评审要“适度”。过度评审和评审不足一样有害。过度评审会让开发者感到不被信任会拖慢开发节奏会增加不必要的沟通成本。我见过有的团队要求每个 PR 至少三个人评审结果一个简单的文案修改也要等三个人点头效率极低。评审的力度应该和代码变更的风险成正比高风险变更严格评审低风险变更快速通过。最后一个体会是评审要“持续改进”。没有一套评审体系是完美的每个团队的情况都在变化评审体系也要跟着变。我一般会每季度做一次评审体系的复盘看看哪些规则需要调整哪些工具需要更换哪些指标需要重新设定。评审体系不是建好就完了它是一个需要持续维护和优化的系统。提示如果你刚开始搞代码评审不要追求一步到位。先跑起来再优化。先解决“有没有”的问题再解决“好不好”的问题。我见过太多团队在准备阶段花了太多时间结果还没开始就放弃了。先做一个最小可用的版本让评审这件事在团队里发生然后再慢慢改进。