incremental-implementation

incremental-implementation

热门

增量交付变更。适用于实现任何涉及多个文件的特性或变更。当你即将一次性编写大量代码,或某个任务感觉太大而无法一步完成时使用。

7.7万Star
0Fork
更新于 2026/7/3
SKILL.md
readonly只读
name
incremental-implementation
description

增量交付变更。适用于实现任何涉及多个文件的特性或变更。当你即将一次性编写大量代码,或某个任务感觉太大而无法一步完成时使用。

增量实现

概述

以薄垂直切片的方式构建——实现一小块,测试它,验证它,然后扩展。避免一次性实现整个特性。每个增量应使系统处于可工作、可测试的状态。这是使大型特性可管理的执行纪律。

何时使用

  • 实现任何多文件变更
  • 根据任务分解构建新特性
  • 重构现有代码
  • 任何你想在测试前编写超过约100行代码的时候

何时不使用: 单文件、单函数变更,且范围已经很小。

增量循环

┌──────────────────────────────────────┐
│                                      │
│   实现 ──→ 测试 ──→ 验证 ──┐         │
│       ▲                           │  │
│       └───── 提交 ◄─────────────┘  │
│              │                       │
│              ▼                       │
│          下一个切片                  │
│                                      │
└──────────────────────────────────────┘

对于每个切片:

  1. 实现 最小的完整功能块
  2. 测试 —— 运行测试套件(如果没有测试则编写一个)
  3. 验证 —— 确认切片按预期工作(测试通过、构建成功、手动检查)
  4. 提交 —— 用描述性消息保存进度(参见 git-workflow-and-versioning 了解原子提交指南)
  5. 进入下一个切片 —— 继续前进,不要重新开始

切片策略

垂直切片(首选)

构建一条贯穿整个栈的完整路径:

切片 1: 创建任务(数据库 + API + 基本 UI)
    → 测试通过,用户可以通过 UI 创建任务

切片 2: 列出任务(查询 + API + UI)
    → 测试通过,用户可以看到他们的任务

切片 3: 编辑任务(更新 + API + UI)
    → 测试通过,用户可以修改任务

切片 4: 删除任务(删除 + API + UI + 确认)
    → 测试通过,完整的 CRUD 完成

每个切片交付可工作的端到端功能。

契约优先切片

当后端和前端需要并行开发时:

切片 0: 定义 API 契约(类型、接口、OpenAPI 规范)
切片 1a: 根据契约实现后端 + API 测试
切片 1b: 根据匹配契约的模拟数据实现前端
切片 2: 集成并端到端测试

风险优先切片

先处理风险最高或最不确定的部分:

切片 1: 证明 WebSocket 连接有效(最高风险)
切片 2: 在已证明的连接上构建实时任务更新
切片 3: 添加离线支持和重连

如果切片 1 失败,你会在投入切片 2 和 3 之前发现它。

实现规则

规则 0:简单优先

在编写任何代码之前,问:“最简单可行的方法是什么?”

编写代码后,对照以下检查点进行审查:

  • 能否用更少的行数完成?
  • 这些抽象是否值得其复杂性?
  • 高级工程师看到这个会不会说“你为什么不直接...”?
  • 我是在为假设的未来需求构建,还是为当前任务?
简单性检查:
✗ 为单个通知使用带有中间件管道的通用 EventBus
✓ 简单的函数调用

✗ 为两个相似组件使用抽象工厂模式
✓ 两个直接的组件加上共享工具函数

✗ 为三个表单使用配置驱动的表单构建器
✓ 三个表单组件

三行相似的代码胜过过早的抽象。先实现朴素、明显正确的版本。只有在通过测试证明正确性后才进行优化。

规则 0.5:范围纪律

只触及任务所需的内容。

不要:

  • “清理”你变更旁边的代码
  • 重构你未修改文件中的导入
  • 删除你不完全理解的注释
  • 添加规范中没有的特性,因为它们“看起来有用”
  • 在你只读取的文件中现代化语法

如果你注意到任务范围之外值得改进的地方,记下来——不要修复它:

注意到但未触及:
- src/utils/format.ts 有一个未使用的导入(与此任务无关)
- auth 中间件可以使用更好的错误消息(单独的任务)
→ 需要我为这些创建任务吗?

规则 1:一次只做一件事

每个增量只改变一个逻辑上的东西。不要混合关注点:

糟糕: 一个提交同时添加新组件、重构现有组件并更新构建配置。

良好: 三个独立的提交——每个变更一个。

规则 2:保持可编译

每个增量之后,项目必须能构建,且现有测试必须通过。不要在切片之间让代码库处于损坏状态。

规则 3:不完整特性的特性开关

如果某个特性尚未准备好给用户使用,但你需要合并增量:

// 进行中工作的特性开关
const ENABLE_TASK_SHARING = process.env.FEATURE_TASK_SHARING === 'true';

if (ENABLE_TASK_SHARING) {
  // 新的共享 UI
}

这允许你将小增量合并到主分支,而不会暴露未完成的工作。

规则 4:安全默认值

新代码应默认采用安全、保守的行为:

// 安全:默认禁用,选择加入
export function createTask(data: TaskInput, options?: { notify?: boolean }) {
  const shouldNotify = options?.notify ?? false;
  // ...
}

规则 5:易于回滚

每个增量应可独立回退:

  • 添加性变更(新文件、新函数)易于回退
  • 对现有代码的修改应最小且集中
  • 数据库迁移应有对应的回滚迁移
  • 避免在一个提交中删除某些内容并在同一提交中替换它——将它们分开

与智能体协作

当指示智能体增量实现时:

“让我们从计划中实现任务 3。

先从数据库模式变更和 API 端点开始。
暂时不要碰 UI —— 我们将在下一个增量中处理。

实现后,运行 `npm test` 和 `npm run build` 以验证
没有破坏任何东西。”

明确说明每个增量的范围和不包括的内容。

增量检查清单

每个增量后,验证:

  • [ ] 变更只做了一件事,并且完整地完成了
  • [ ] 所有现有测试仍然通过(npm test
  • [ ] 构建成功(npm run build
  • [ ] 类型检查通过(npx tsc --noEmit
  • [ ] 代码检查通过(npm run lint
  • [ ] 新功能按预期工作
  • [ ] 变更已提交,并附有描述性消息

注意: 在可能影响某个验证命令的变更后运行该命令。成功运行后,除非代码已更改,否则不要重复相同的命令——在未更改的代码上重新运行不会增加任何信息。

常见合理化借口

合理化借口 现实
“我最后再一起测试” 错误会累积。切片 1 中的错误会使切片 2-5 都出错。测试每个切片。
“一次性做完更快” 感觉更快,直到某些东西坏了,而你无法在 500 行变更中找到原因。
“这些变更太小,不值得单独提交” 小提交是免费的。大提交隐藏错误并使回滚痛苦。
“我稍后再添加特性开关” 如果特性不完整,它就不应该对用户可见。现在就添加开关。
“这个重构很小,可以包含进来” 重构与特性混合会使审查和调试都更困难。分开它们。
“让我再运行一次构建命令以确保” 成功运行后,除非代码已更改,否则重复相同命令不会增加任何信息。在后续编辑后再次运行,而不是作为 reassurance。

红旗警示

  • 编写了超过 100 行代码而未运行测试
  • 单个增量中包含多个不相关的变更
  • “让我也快速添加这个”的范围扩展
  • 跳过测试/验证步骤以加快速度
  • 增量之间构建或测试失败
  • 大量未提交的变更累积
  • 在第三个用例要求之前就构建抽象
  • 触及任务范围之外的文件,“既然我在这里”
  • 为一次性操作创建新的工具文件
  • 连续两次运行相同的构建/测试命令,中间没有代码变更

验证

完成一个任务的所有增量后:

  • [ ] 每个增量都经过单独测试和提交
  • [ ] 完整测试套件通过
  • [ ] 构建干净
  • [ ] 特性按规范端到端工作
  • [ ] 没有未提交的变更残留

参见

每个增量的验证是局部检查。在宣布任务完成之前,应用项目范围的“完成定义”作为最终关卡,这是每个增量无论任务如何都必须达到的常设标准。参见 references/definition-of-done.md