engineering-small-prs

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Engineering Small PRs

小PR工程实践

Small PRs are easier to review thoroughly, safer to merge, easier to roll back, and less likely to waste work if the direction changes. "Small" means conceptually focused and self-contained, not merely a low line count.
Adapted from Google Engineering Practices Documentation, especially "Small CLs." Source: https://google.github.io/eng-practices/review/developer/small-cls.html. License: CC-BY 3.0.
小PR更易于全面评审,合并更安全,回滚更简单,且在方向变更时浪费的工作量更少。这里的“小”指的是概念上聚焦且独立完整,而非仅仅是代码行数少。
本文改编自谷歌工程实践文档,尤其是《小型CL》章节。来源:https://google.github.io/eng-practices/review/developer/small-cls.html。许可证:CC-BY 3.0。

Definition of a Good Small PR

优质小PR的定义

A good PR:
  • Makes one self-contained change.
  • Includes the tests needed to validate that change.
  • Leaves the system working after merge.
  • Gives reviewers enough context in the PR, description, existing code, or earlier reviewed PRs.
  • Is not so tiny that the behavior cannot be understood. A new API usually needs at least one usage in the same PR.
  • Separates large refactors from behavior changes unless the cleanup is very local.
Reviewers may reasonably reject a PR solely because it is too large to review well.
优质的PR需满足:
  • 仅做出一项独立完整的变更。
  • 包含验证该变更所需的测试。
  • 合并后系统仍能正常运行。
  • 在PR、描述、现有代码或已评审的早期PR中为评审者提供足够的上下文。
  • 不会过于琐碎以至于无法理解其行为。新API通常需要在同一个PR中至少包含一处使用示例。
  • 将大型重构与行为变更分离,除非清理工作非常局部化。
评审者完全可以仅因PR过大难以有效评审而拒绝它。

Splitting Workflow

拆分流程

  1. Name the final outcome in one sentence.
  2. List independent behavior changes, refactors, schema/config changes, tests, and docs.
  3. Identify dependencies that must land earlier.
  4. Choose split strategies from the section below.
  5. Build a merge sequence where every PR keeps the build green.
  6. Add context notes so reviewers understand how each PR fits into the larger work.
  7. For risky or unavoidable large changes, get reviewer consent before sending the PR.
  1. 用一句话描述最终成果。
  2. 列出独立的行为变更、重构、架构/配置变更、测试和文档。
  3. 识别必须优先落地的依赖项。
  4. 从下方章节选择拆分策略。
  5. 构建一个合并序列,确保每个PR都能保持构建成功。
  6. 添加上下文说明,让评审者理解每个PR在整体工作中的定位。
  7. 对于高风险或无法拆分的大型变更,在发送PR前需获得评审者同意。

Split Strategies

拆分策略

  • Preparatory tests first: add missing tests around existing behavior before risky refactors.
  • Refactor first: move, rename, extract, or simplify code without changing behavior.
  • Vertical slices: deliver one small user-visible or API-visible behavior end-to-end.
  • Horizontal slices: add shared interfaces, protocol definitions, or adapters only when paired with a real first usage in the same PR or a clearly linked dependent PR already under review.
  • File or owner groups: split files by reviewer expertise when the changes are otherwise self-contained.
  • Config separately: keep rollout configuration, experiments, or deployment wiring separate from code when rollback timing differs.
  • Generated or mechanical changes separately: isolate trusted automated rewrites from hand-written logic.
  • Deletions separately when useful: removing dead code can be a compact, easy-to-review PR.
  • 先做预备测试:在进行高风险重构前,为现有行为添加缺失的测试。
  • 先重构:在不改变行为的前提下,移动、重命名、提取或简化代码。
  • 垂直切片:端到端交付一个小型的用户可见或API可见的功能。
  • 水平切片:仅在同一PR中包含实际首次使用,或已有明确关联且正在评审的依赖PR时,才添加共享接口、协议定义或适配器。
  • 按文件或负责人分组:当变更本身独立完整时,根据评审者的专业领域拆分文件。
  • 配置分离:当回滚时机不同时,将发布配置、实验或部署相关代码与业务代码分离。
  • 自动生成或机械变更分离:将可信的自动重写代码与手写逻辑隔离开。
  • 必要时单独删除代码:移除死代码可以形成一个简洁、易于评审的PR。

Migration Safety

迁移安全

For schema, data, API, or infrastructure migrations, prefer an expand/contract sequence:
  1. Expand: add backward-compatible schema/API/config support without removing old behavior.
  2. Dual path: write or read both paths only when needed, with observability for divergence.
  3. Backfill: migrate existing data with progress tracking, retry behavior, and validation.
  4. Cut over: switch traffic or callers after validation proves both paths are safe.
  5. Contract: remove old schema, code paths, flags, and compatibility shims in a cleanup PR.
Each migration PR should state deployment order, rollback behavior, validation signal, and what must not happen until the next PR lands.
对于架构、数据、API或基础设施迁移,优先采用“扩展/收缩”序列:
  1. 扩展:添加向后兼容的架构/API/配置支持,不移除旧行为。
  2. 双路径:仅在必要时同时读写新旧路径,并添加差异观测能力。
  3. 回填:迁移现有数据,包含进度跟踪、重试机制和验证。
  4. 切换:在验证确认双路径安全后,切换流量或调用方。
  5. 收缩:在清理PR中移除旧架构、代码路径、标志和兼容性垫片。
每个迁移PR都应说明部署顺序、回滚行为、验证信号,以及在下一个PR落地前禁止执行的操作。

Output Template

输出模板

markdown
undefined
markdown
undefined

Goal

目标

[Final outcome]
[最终成果]

Proposed PR Sequence

拟议PR序列

#PRPurposeDepends OnTestsReviewer Notes
1Add characterization tests for ...Protect existing behavior before refactorNone......
2Extract ... without behavior changePrepare smaller implementation1......
3Implement ... vertical sliceUser-visible behavior2......
序号PR内容目的依赖项测试评审者说明
1为...添加特征测试重构前保护现有行为......
2提取...且不改变行为为后续实现做准备1......
3实现...垂直切片用户可见功能2......

Migration Safety

迁移安全

  • Expand/contract phase:
  • Backfill/validation:
  • Observability:
  • Rollback:
  • 扩展/收缩阶段:
  • 回填/验证:
  • 观测能力:
  • 回滚方案:

Build Safety

构建安全

  • Each PR keeps:
  • Rollback notes:
  • 每个PR需保持:
  • 回滚说明:

Large-Change Risk

大型变更风险

  • What could not be split:
  • Reviewer consent needed:
undefined
  • 无法拆分的内容:
  • 需评审者同意:
undefined

Heuristics

启发式方法

  • Prefer a PR that is smaller than you think necessary; reviewers rarely object to focused changes.
  • If a PR spreads a small logical change across many files, treat it as larger than the line count suggests.
  • If the reviewer needs substantial future context to understand the PR, the sequence is probably missing an earlier preparatory PR or a better description.
  • If you cannot split the PR, make it extra easy to review: stronger tests, clearer description, explicit risk, and prior reviewer agreement.
  • PR应比你认为的更小;评审者很少会对聚焦的变更提出异议。
  • 如果一个PR将一个小的逻辑变更分散到多个文件中,则应将其视为比代码行数所显示的更大。
  • 如果评审者需要大量未来上下文才能理解PR,那么序列可能缺少一个早期的预备PR或更清晰的描述。
  • 如果无法拆分PR,则需让其更易于评审:更强的测试、更清晰的描述、明确的风险说明,以及事先获得评审者的同意。

Common Mistakes

常见错误

  • Mixing broad formatting changes with functional logic.
  • Landing a new abstraction with no real usage.
  • Creating a stacked sequence where intermediate PRs break the build.
  • Hiding risky behavior change inside a "refactor" PR.
  • Waiting for one PR to merge before starting the next when a safe stacked workflow is available.
  • 将大范围格式变更与功能逻辑混合。
  • 落地一个没有实际使用场景的新抽象。
  • 创建的堆叠序列中,中间PR会导致构建失败。
  • 在“重构”PR中隐藏高风险的行为变更。
  • 当可以安全使用堆叠工作流时,却等待一个PR合并后再开始下一个。