prompt-engineering-development-methodologies
提示词工程中的三大开发方法论:TDD、SDD 与 Subagent-Driven Development
当我们把 AI Agent 当作"开发者"来使用时,传统软件工程中的方法论并没有过时——它们以一种新的形态重新出现在了提示词工程中。本文介绍三种在 AI Agent 工作流中被系统化实践的开发方法论。
一、为什么 AI Agent 需要开发方法论?
你可能有过这样的体验:让 AI 帮你写一个功能,它一口气生成了几百行代码,看起来很完整,但跑起来到处是 bug。你让它修,它改了 A 又破了 B。几轮下来,上下文窗口塞满了,AI 开始"失忆",重复犯错。
问题不在模型能力,而在于缺乏流程约束。
人类开发者也一样——没有流程的天才程序员,产出的代码质量不如遵循流程的普通程序员。AI Agent 更是如此:它没有长期记忆,没有直觉,没有"代码品味"。它需要的是精确的流程指令来约束每一步行为。
这就是提示词工程中开发方法论的价值:用 prompt 定义流程,让 AI Agent 像一个训练有素的工程师一样工作。
二、Test-Driven Development(测试驱动开发)
核心铁律
没有失败的测试 → 不写生产代码
这条规则在传统 TDD 中就存在,但在 AI Agent 的语境下被执行得更加严格。原因很简单:AI 特别擅长"事后补测试"——它能看着已有代码写出完美通过的测试,但这些测试什么也证明不了。
红-绿-重构循环
整个 TDD 流程是一个不断重复的小循环:
RED(写失败测试)→ 验证失败 → GREEN(写最小实现)→ 验证通过 → REFACTOR(重构)→ 下一轮
每一步都有明确的验证要求:
RED 阶段:写一个最小的测试,描述期望行为。只测一件事,名字要清晰。
// ✅ 好的测试
test('rejects empty email', async () => {
const result = await submitForm({ email: '' });
expect(result.error).toBe('Email required');
});
// ❌ 坏的测试
test('validation works', async () => { /* 测了三件事 */ });
验证 RED:必须运行测试,确认它失败了,而且是因为功能缺失而失败(不是拼写错误)。这一步绝对不能跳过——如果测试一写就通过,说明你在测试已有行为,测试本身有问题。
GREEN 阶段:写最简单的代码让测试通过。不多写一行,不提前优化,不"顺手"加功能。
// ✅ 刚好够用
function submitForm(data: FormData) {
if (!data.email?.trim()) {
return { error: 'Email required' };
}
}
// ❌ 过度工程
function submitForm(data: FormData, options?: {
validators?: Validator[];
onError?: (e: Error) => void;
// YAGNI...
}) { }
验证 GREEN:运行测试,确认通过,且没有破坏其他测试。
REFACTOR:在测试全绿的保护下清理代码——消除重复、改善命名、提取辅助函数。不添加新行为。
AI Agent 语境下的特殊规则
传统 TDD 中,"先写了代码再补测试"只是不推荐。在 AI Agent 的 prompt 中,这被定义为硬性违规:
先写了代码再补测试?删掉代码,重来。
不是"留着参考",不是"改改就行"。删除意味着删除。
为什么这么极端?因为 AI 一旦看到已有实现,就会不自觉地让测试去适配实现,而不是让实现去满足测试。测试变成了"验证我写了什么"而不是"定义我该写什么"。
常见借口与反驳
| AI(或人类)的借口 | 现实 |
|---|---|
| "太简单不需要测试" | 简单代码也会出 bug,测试只需 30 秒 |
| "我先探索一下再 TDD" | 可以探索,但探索完必须丢掉,从 TDD 重新开始 |
| "先写后测效果一样" | 后写的测试回答"代码做了什么",先写的测试回答"代码该做什么"——本质不同 |
| "删掉 X 小时的工作太浪费" | 沉没成本谬误。保留无法信任的代码才是真正的浪费 |
| "TDD 太教条了" | TDD 就是务实:提交前发现 bug 比生产环境调试快得多 |
实战例子:用 TDD 给 AI 写一个 URL 短链接生成器
假设我们要让 AI Agent 实现一个 shortenUrl 函数。来看看有 TDD 和没有 TDD 的区别。
❌ 没有 TDD 的对话(典型翻车现场):
你:帮我写一个 URL 短链接生成函数
AI:好的!这是完整实现:
(一口气生成 200 行代码,包含 Base62 编码、数据库存储、
碰撞检测、过期时间、自定义短码、访问统计……)
你:我只需要一个简单的哈希函数啊……
AI:抱歉!让我重写:
(又生成 150 行,方向还是不对)
你:算了,测试也帮我补一下吧
AI:(看着自己写的代码,写出完美通过的测试)
✅ All 12 tests passed!
你:(上线后发现空字符串没处理,特殊字符会崩溃)
✅ 有 TDD 的对话(受控推进):
你:用 TDD 帮我实现一个 shortenUrl 函数
AI:好的,从第一个测试开始。
--- RED ---
我先写一个最基本的测试:
test('generates a short code for a valid URL', () => {
const result = shortenUrl('https://example.com');
expect(result).toHaveLength(8);
expect(result).toMatch(/^[a-zA-Z0-9]+$/);
});
运行测试:
$ npm test
FAIL: shortenUrl is not defined ✅ 预期的失败
--- GREEN ---
写最小实现让测试通过:
import { createHash } from 'crypto';
function shortenUrl(url: string): string {
return createHash('sha256')
.update(url)
.digest('base62')
.slice(0, 8);
}
运行测试:
$ npm test
PASS ✅
--- 下一轮 RED ---
现在测试边界情况——空字符串:
test('throws error for empty URL', () => {
expect(() => shortenUrl('')).toThrow('URL is required');
});
运行测试:
$ npm test
FAIL: Expected error but none was thrown ✅ 预期的失败
--- GREEN ---
function shortenUrl(url: string): string {
if (!url?.trim()) throw new Error('URL is required');
// ...
}
$ npm test
PASS ✅(两个测试都通过)
--- 下一轮 RED ---
测试相同 URL 应该生成相同短码:
test('same URL produces same short code', () => {
const a = shortenUrl('https://example.com');
const b = shortenUrl('https://example.com');
expect(a).toBe(b);
});
$ npm test
PASS ✅(天然满足,因为用了哈希——这说明测试验证了设计假设)
注意这个过程的节奏:每一轮只前进一小步,每一步都有验证。AI 不会跑偏去写访问统计、过期时间这些没人要求的东西。
关键对比:
| 维度 | 没有 TDD | 有 TDD |
|---|---|---|
| 第一次输出 | 200 行,功能过多 | 10 行,刚好够用 |
| 边界情况 | 上线后才发现 | 第二轮测试就覆盖了 |
| 返工次数 | 多次推倒重来 | 零返工,持续前进 |
| 信心来源 | AI 说"应该没问题" | 测试全绿 |
TDD 在提示词工程中的意义
TDD 不只是一种测试策略,它是约束 AI 行为的最有效手段之一:
- 防止过度生成:每次只写一个测试,AI 被迫小步前进
- 提供验证锚点:每一步都有可运行的验证,不依赖 AI 的"自信"
- 强制设计思考:先写测试意味着先想清楚接口长什么样
- 防止回归:已有测试保护已有功能,AI 改 A 不会悄悄破坏 B
三、Spec-Driven Development(规格驱动开发)
如果说 TDD 约束的是"怎么写代码",那 Spec-Driven Development 约束的是"写什么代码"。
核心理念
在写任何代码之前,先把要做的事情想清楚、写清楚、审清楚。
这听起来像常识,但在 AI Agent 的实践中,最常见的失败模式恰恰是:用户说了一句话,AI 就开始写代码。结果写了 500 行才发现方向错了。
Spec-Driven Development 把"从想法到代码"拆成了三个有明确门禁的阶段:
阶段一:Brainstorming(头脑风暴 → 设计规格)
这是整个流程的起点,也是最容易被跳过的一步。prompt 中用了一个硬门禁来防止这种情况:
在你呈现设计并获得用户批准之前,不要调用任何实现技能、写任何代码、搭建任何项目。无论项目看起来多简单,都适用。
流程:
探索项目上下文
↓
逐个提问(每次只问一个,优先选择题)
↓
提出 2-3 种方案 + 权衡分析 + 推荐
↓
分段呈现设计,逐段获得用户确认
↓
写成设计文档(spec)
↓
自审查(占位符?矛盾?歧义?范围?)
↓
用户审查通过
↓
进入下一阶段
几个关键设计决策:
- 每次只问一个问题:避免信息过载,让对话自然推进
- 必须提出多种方案:防止 AI 锁定第一个想到的方案
- YAGNI 原则贯穿始终:不需要的功能在设计阶段就砍掉,而不是写完再删
- 大项目先拆分:如果一个项目包含多个独立子系统,先拆成子项目,每个子项目走独立的 spec → plan → implementation 循环
设计文档保存为 docs/superpowers/specs/YYYY-MM-DD-<topic>-design.md,提交到 git。这不是形式主义——它让设计决策可追溯、可审查。
阶段二:Writing Plans(写实现计划)
设计规格回答"做什么",实现计划回答"怎么做"。
这一步的核心假设很有意思:
假设执行计划的工程师对我们的代码库零了解,且品味存疑。记录他们需要知道的一切。
这个假设完美适配 AI Agent 的特点——它确实对你的代码库没有长期记忆,确实需要被精确告知每一步该做什么。
计划的粒度极细,每一步 2-5 分钟:
### Task 1: 用户验证模块
**Files:**
- Create: `src/validators/email.ts`
- Test: `tests/validators/email.test.ts`
- [ ] **Step 1: 写失败测试**
(附完整测试代码)
- [ ] **Step 2: 运行测试验证失败**
Run: `npm test tests/validators/email.test.ts`
Expected: FAIL with "function not defined"
- [ ] **Step 3: 写最小实现**
(附完整实现代码)
- [ ] **Step 4: 运行测试验证通过**
Run: `npm test tests/validators/email.test.ts`
Expected: PASS
- [ ] **Step 5: 提交**
git commit -m "feat: add email validation"
注意:计划中包含完整代码,不是"添加验证逻辑"这种模糊描述。包含精确命令和预期输出。这样执行者(无论是 AI 还是人)不需要做任何判断,只需要按步骤执行。
计划写完后,还有一个审查环节——派遣一个专门的审查子代理来检查计划文档的质量。
阶段三:执行
计划完成后,提供两种执行方式:
- Subagent-Driven(推荐):每个任务派遣独立子代理,带两阶段审查
- Inline Execution:在当前会话中按批次执行,设置检查点
为什么 Spec-Driven 在提示词工程中特别重要?
- 对抗 AI 的"急于动手"倾向:AI 模型天然倾向于直接给出解决方案。Spec-Driven 用流程强制它先思考
- 减少返工:设计阶段发现问题的修复成本接近零,代码阶段发现问题的修复成本是指数级的
- 让人类保持控制权:每个阶段都有人类审批门禁,AI 不会自作主张跑偏
- 可追溯性:设计文档 → 实现计划 → 代码,每一步都有文档记录
实战例子:用 Spec-Driven 构建 URL 短链接服务
同样是"URL 短链接"这个需求,来看 Spec-Driven 的完整过程。
阶段一:Brainstorming 对话实录
你:我想做一个 URL 短链接服务
AI:我先了解一下项目上下文。
(检查项目文件、技术栈、已有代码……)
这个服务是面向内部团队还是公开使用?
A) 内部工具(公司内部分享链接)
B) 公开服务(类似 bit.ly)
C) 嵌入到现有产品中的功能模块
你:A,内部工具
AI:短链接需要支持过期吗?
A) 不需要,永久有效
B) 需要,可设置过期时间
C) 默认 30 天,可选永久
你:A,永久就行
AI:存储方案你有偏好吗?
A) SQLite(简单,单机部署)
B) PostgreSQL(团队已有实例的话)
C) Redis(纯内存,速度快但需要持久化配置)
你:B,我们已经有 PG 了
AI:好的,我来提出几种方案。
方案一(推荐):哈希截断
- 用 SHA256 哈希 URL,取前 8 位作为短码
- 优点:简单、确定性(相同 URL 相同短码)、无需计数器
- 缺点:理论上有碰撞可能(概率极低)
- 碰撞处理:检测到碰撞时追加一位
方案二:自增 ID + Base62
- 数据库自增 ID,转 Base62 编码
- 优点:绝对无碰撞,短码更短
- 缺点:短码可预测(安全性略低),需要数据库序列
方案三:随机生成
- 随机生成 8 位字符串
- 优点:不可预测
- 缺点:需要碰撞检测,相同 URL 会生成不同短码
我推荐方案一。内部工具不需要担心短码可预测性,
哈希截断最简单且相同 URL 天然去重。
你:同意方案一
AI:我来分段呈现设计。
【架构】
- 单个 Express 服务,两个端点:
POST /shorten → 接收长 URL,返回短码
GET /:code → 重定向到原始 URL
- PostgreSQL 存一张表:urls(code, original_url, created_at)
- code 列加唯一索引
这部分看起来对吗?
你:对的
AI:【错误处理】
- 无效 URL → 400 Bad Request
- 短码不存在 → 404 Not Found
- 重复 URL → 返回已有短码(幂等)
这部分呢?
你:可以
AI:设计确认完毕,我来写 spec 文档。
生成的 spec 文档(简化版):
# URL 短链接服务设计规格
**目标:** 内部团队使用的 URL 短链接服务
**架构:** Express + PostgreSQL,哈希截断生成短码
## 端点
### POST /shorten
- 输入:{ url: string }
- 输出:{ code: string, shortUrl: string }
- 规则:SHA256 哈希取前 8 位,相同 URL 返回相同短码
- 错误:空 URL → 400,无效 URL → 400
### GET /:code
- 成功:302 重定向到原始 URL
- 错误:短码不存在 → 404
## 数据模型
- urls 表:code (PK, varchar(8)), original_url (text), created_at (timestamp)
## 不做的事情
- ❌ 访问统计
- ❌ 自定义短码
- ❌ 过期时间
- ❌ 用户认证
注意最后的"不做的事情"——这是 YAGNI 原则的体现,明确排除了 AI 可能"顺手"加上的功能。
阶段二:Writing Plans 生成的实现计划(节选):
# URL 短链接服务实现计划
> **For agentic workers:** Use superpowers:subagent-driven-development
**Goal:** 实现内部 URL 短链接服务
**Tech Stack:** TypeScript, Express, PostgreSQL, Jest
---
### Task 1: 短码生成函数
**Files:**
- Create: `src/utils/generateCode.ts`
- Test: `tests/utils/generateCode.test.ts`
- [ ] Step 1: 写失败测试
test('generates 8-char alphanumeric code', () => {
const code = generateCode('https://example.com');
expect(code).toHaveLength(8);
expect(code).toMatch(/^[a-zA-Z0-9]+$/);
});
- [ ] Step 2: 运行测试验证失败
Run: `npx jest tests/utils/generateCode.test.ts`
Expected: FAIL - generateCode is not defined
- [ ] Step 3: 写最小实现
import { createHash } from 'crypto';
export function generateCode(url: string): string {
return createHash('sha256').update(url).digest('hex').slice(0, 8);
}
- [ ] Step 4: 运行测试验证通过
- [ ] Step 5: 提交
### Task 2: URL 验证函数
(类似结构……)
### Task 3: 数据库迁移脚本
(类似结构……)
### Task 4: POST /shorten 端点
(类似结构……)
### Task 5: GET /:code 端点
(类似结构……)
对比:有 Spec-Driven 和没有 Spec-Driven
| 维度 | 直接让 AI 写代码 | Spec-Driven |
|---|---|---|
| 第一次输出 | 500 行代码,含访问统计、用户认证等没人要的功能 | 一份 spec 文档,明确做什么和不做什么 |
| 方向错误的发现时间 | 写完代码后 | 第一轮对话中 |
| 返工成本 | 推倒重来 | 改几行 spec |
| 人类控制感 | "AI 在做什么?" | 每一步都确认过 |
四、Subagent-Driven Development(子代理驱动开发)
这是三者中最具"AI 原生"特色的方法论。它解决的是一个传统软件工程中不存在的问题:AI Agent 的上下文窗口是有限的,而且会随着对话推进而退化。
核心问题
当你让一个 AI Agent 连续执行 10 个任务时,会发生什么?
- 上下文窗口逐渐被历史对话填满
- Agent 开始"忘记"早期的约定
- 后面的任务质量明显下降
- 不同任务的上下文互相干扰
核心方案
每个任务一个全新的子代理 + 两阶段审查 = 高质量、快速迭代
主控制器(你的主会话)负责协调,但不负责实现。每个任务派遣一个全新的子代理,它拥有:
- 隔离的上下文:不继承主会话的历史
- 精确的信息:由主控制器精心构造,只包含这个任务需要的内容
- 明确的职责:实现、测试、提交、自审查
完整流程
读取计划,提取所有任务
↓
┌─────────────── 逐任务循环 ───────────────┐
│ │
│ 派遣实现者子代理(带完整任务文本+上下文) │
│ ↓ │
│ 实现者有疑问?→ 回答后重新派遣 │
│ ↓ │
│ 实现者完成:编码 → 测试 → 提交 → 自审查 │
│ ↓ │
│ 派遣规格审查子代理 │
│ ↓ │
│ 规格合规? │
│ ❌ → 实现者修复 → 重新审查(循环) │
│ ✅ ↓ │
│ 派遣代码质量审查子代理 │
│ ↓ │
│ 质量合格? │
│ ❌ → 实现者修复 → 重新审查(循环) │
│ ✅ → 标记完成,下一个任务 │
│ │
└───────────────────────────────────────────┘
↓
全局最终审查
↓
完成
三种角色的子代理
实现者(Implementer):接收任务文本和上下文,编码、测试、提交。它会返回四种状态:
| 状态 | 含义 | 处理方式 |
|---|---|---|
| DONE | 完成 | 进入规格审查 |
| DONE_WITH_CONCERNS | 完成但有顾虑 | 评估顾虑后决定 |
| NEEDS_CONTEXT | 缺少信息 | 补充信息,重新派遣 |
| BLOCKED | 无法完成 | 换模型/拆任务/上报人类 |
规格审查者(Spec Reviewer):只检查一件事——代码是否完全匹配规格。不多不少。多了(加了规格没要求的功能)要删,少了(漏了规格要求的功能)要补。
代码质量审查者(Code Quality Reviewer):检查代码质量——命名、结构、魔法数字、错误处理等。
两阶段审查的顺序不能颠倒:先确认做对了,再确认做好了。
模型选择策略
不是所有任务都需要最强的模型。按复杂度选择,节省成本和时间:
| 任务特征 | 模型选择 |
|---|---|
| 1-2 个文件,规格清晰,机械性实现 | 便宜快速的模型 |
| 多文件协调,集成逻辑 | 标准模型 |
| 架构决策,设计判断,审查 | 最强模型 |
关键红线
- 不要并行派遣多个实现子代理——它们会产生代码冲突
- 不要跳过任何审查——规格审查和质量审查都不能省
- 不要让子代理自己去读计划文件——由主控制器提供完整文本,避免浪费子代理的上下文
- 不要忽略子代理的提问——先回答,再让它继续
- 审查发现问题 → 修复 → 重新审查——不能跳过重新审查
为什么这是"AI 原生"的方法论?
传统软件工程中没有"上下文窗口"的概念,也没有"派遣一个全新的开发者来做每个任务"的实践。Subagent-Driven Development 是专门为 AI Agent 的特性设计的:
- 解决上下文退化:每个子代理都是全新的,不受历史对话污染
- 利用 AI 的可复制性:人类开发者不能被"复制",但 AI Agent 可以随时创建新实例
- 精确的信息控制:主控制器决定每个子代理看到什么,不看到什么
- 自动化质量门禁:审查也由 AI 完成,但通过角色分离保证客观性
实战例子:用 Subagent-Driven 执行 URL 短链接服务的计划
继续上面的例子。实现计划有 5 个任务,现在用 Subagent-Driven 来执行。
主控制器的工作(你的主会话):
主控制器:读取计划,提取 5 个任务的完整文本。
创建 TodoWrite 追踪进度。
========== Task 1: 短码生成函数 ==========
主控制器 → 派遣实现者子代理,附带:
- Task 1 的完整文本(包含所有步骤和代码)
- 项目技术栈信息(TypeScript, Jest)
- 相关文件路径
实现者子代理:
"开始实现。没有疑问,直接开始。"
[RED] 写了 generateCode.test.ts
[验证] $ npx jest → FAIL ✅
[GREEN] 写了 generateCode.ts
[验证] $ npx jest → PASS ✅
[自审查] 代码简洁,测试覆盖充分
[提交] git commit -m "feat: add generateCode utility"
状态:DONE
主控制器 → 派遣规格审查子代理,附带:
- Task 1 的规格文本
- 实现者的提交内容
规格审查者:
✅ 规格合规
- 生成 8 位字符 ✓
- 使用 SHA256 ✓
- 相同输入相同输出 ✓
- 没有多余功能 ✓
主控制器 → 派遣代码质量审查子代理
代码质量审查者:
✅ 通过
- 函数职责单一 ✓
- 命名清晰 ✓
- 无魔法数字(8 可以接受,因为 spec 明确定义)✓
主控制器:Task 1 完成 ✅
========== Task 2: URL 验证函数 ==========
主控制器 → 派遣新的实现者子代理
(注意:这是一个全新的子代理,不是 Task 1 的那个)
实现者子代理:
"在开始之前——spec 说'无效 URL 返回 400',
但没有定义什么算'有效 URL'。
是只检查格式(有 http/https 前缀),
还是需要验证域名可解析?"
状态:NEEDS_CONTEXT
主控制器:
"只检查格式——必须以 http:// 或 https:// 开头,
不需要验证域名。"
主控制器 → 重新派遣实现者子代理(附带补充的上下文)
实现者子代理:
[实现完成,测试通过,提交]
状态:DONE
主控制器 → 派遣规格审查子代理
规格审查者:
❌ 问题发现:
- 缺失:没有处理空字符串的情况(spec 说"空 URL → 400")
- 多余:加了对 URL 长度上限 2048 的检查(spec 没要求)
主控制器 → 让实现者修复
实现者子代理:
- 删除了长度检查
- 添加了空字符串处理
[提交]
主控制器 → 重新派遣规格审查子代理
规格审查者:
✅ 规格合规
主控制器 → 派遣代码质量审查子代理
代码质量审查者:
⚠️ 建议:
- 正则表达式 /^https?:\/\/.+/ 可以提取为命名常量
主控制器 → 让实现者修复
实现者子代理:
const VALID_URL_PATTERN = /^https?:\/\/.+/;
[提交]
代码质量审查者(重新审查):
✅ 通过
主控制器:Task 2 完成 ✅
========== Task 3-5: 类似流程 ==========
(省略)
========== 全部完成 ==========
主控制器 → 派遣最终审查子代理(审查整体实现)
最终审查者:
✅ 所有端点实现完整
✅ 测试覆盖充分
✅ 代码风格一致
✅ 可以合并
这个例子展示了几个关键点:
-
Task 2 中实现者提问了——它发现 spec 有歧义,主动要求澄清,而不是自己猜测。这比写完代码再发现方向错了要好得多。
-
规格审查者发现了两个问题——一个是漏了(空字符串),一个是多了(长度限制)。这正是规格审查的价值:不多不少,严格匹配 spec。
-
每个子代理都是全新的——Task 2 的实现者不知道 Task 1 发生了什么,它只看到主控制器精心构造的上下文。这保证了它不会被无关信息干扰。
-
审查循环直到通过——规格审查发现问题 → 修复 → 重新审查 → 通过,然后才进入代码质量审查。不跳步。
对比:单会话执行 vs Subagent-Driven
| 维度 | 单会话连续执行 5 个任务 | Subagent-Driven |
|---|---|---|
| Task 5 的质量 | 明显下降(上下文污染) | 与 Task 1 一样高 |
| 发现 spec 歧义 | 可能忽略,自己猜 | 主动提问 |
| 多余功能 | 容易"顺手"加上 | 规格审查会拦截 |
| 主会话上下文 | 被 5 个任务的细节塞满 | 只保留协调信息,保持轻量 |
五、三者如何协同工作
这三种方法论不是互相替代的,而是组成了一条完整的流水线:
想法
↓
Brainstorming → 设计规格(Spec) ← Spec-Driven
↓
Writing Plans → 实现计划 ← Spec-Driven
↓
Subagent 逐任务执行 ← Subagent-Driven
↓ ↑
TDD 循环(红-绿-重构) ← Test-Driven(贯穿始终)
↓
两阶段审查 ← Subagent-Driven
↓
交付
每种方法论在不同层面提供保障:
| 方法论 | 保障层面 | 核心问题 |
|---|---|---|
| Spec-Driven | 需求与设计 | "我们在做正确的事吗?" |
| Test-Driven | 行为与正确性 | "代码做了它该做的事吗?" |
| Subagent-Driven | 执行与质量 | "每个任务都被高质量地完成了吗?" |
六、实践启示
对提示词工程师的启示
- 流程比模型重要:一个遵循严格流程的普通模型,产出质量往往优于一个没有流程约束的顶级模型
- 约束是赋能:看似"限制"AI 的规则(先写测试、先写设计、不能跳过审查),实际上是在帮助它产出更好的结果
- 角色分离是关键:让同一个 Agent 既写代码又审查代码,效果远不如分成不同角色
对 AI 产品设计的启示
- 上下文管理是核心挑战:Subagent-Driven Development 的存在本身就说明了这一点
- 人类应该在关键节点保持控制:设计审批、计划审批、最终审查——这些门禁不应该被自动化掉
- 小步快跑优于大步流星:2-5 分钟的任务粒度看似过细,但对 AI Agent 来说恰到好处
对传统软件工程的启示
这些方法论并非凭空发明,而是传统软件工程实践在 AI 时代的进化:
- TDD 的红-绿-重构循环没有变,但"删掉先写的代码"这条规则被强化了
- 设计文档的价值没有变,但"每次只问一个问题"的交互模式是新的
- 代码审查的价值没有变,但"派遣专门的审查 Agent"是新的实践
核心不变的是:好的软件需要好的流程。变化的是:流程的执行者从人变成了 AI,所以流程需要被定义得更加精确和不可绕过。
七、新手快速上手指南
如果你刚接触这些方法论,不需要一次全部掌握。按以下顺序逐步实践:
第一周:只练 TDD
从最简单的函数开始。给 AI 的 prompt 只需要加一句话:
用 TDD 实现这个功能。每次只写一个测试,
运行验证失败后再写实现,运行验证通过后再写下一个测试。
练习素材:
- 一个字符串反转函数
- 一个邮箱格式验证函数
- 一个简单的计算器(加减乘除)
观察点:AI 是否真的先写了测试?是否验证了失败?是否只写了最小实现?
第二周:加入 Spec-Driven
在写代码之前,先让 AI 和你做一轮设计对话:
在写任何代码之前,先帮我做设计。
每次只问我一个问题,提出 2-3 种方案让我选择。
设计确认后再开始写代码。
练习素材:
- 一个 TODO 应用的后端 API
- 一个 Markdown 转 HTML 的工具
- 一个简单的博客系统
观察点:AI 是否在提问阶段就帮你发现了没想到的问题?最终实现是否比"直接写"更贴合需求?
第三周:尝试 Subagent-Driven
如果你的工具支持子代理(如 Kiro CLI),尝试把一个 3-5 个任务的计划用 Subagent-Driven 执行:
用 Subagent-Driven Development 执行这个计划。
每个任务派遣独立子代理,完成后先做规格审查,再做代码质量审查。
观察点:子代理的输出质量是否比在同一个会话中连续执行更稳定?审查是否发现了你没注意到的问题?
常见新手误区
| 误区 | 正确做法 |
|---|---|
| "TDD 太慢了,我先写完再补测试" | 补的测试什么也证明不了。慢就是快。 |
| "需求很简单,不需要 spec" | 越简单越容易跳过思考。5 分钟的 spec 能省 2 小时的返工。 |
| "让一个 AI 从头做到尾就行" | 上下文会退化。任务多的时候,后面的质量一定下降。 |
| "审查太麻烦,跳过吧" | 审查是发现问题成本最低的环节。跳过审查 = 把问题留给用户。 |
| "AI 说没问题就没问题" | AI 的自信不等于正确。只有测试通过和审查通过才算数。 |
本文基于 Superpowers 提示词工程体系中的 TDD、Writing Plans、Brainstorming 和 Subagent-Driven Development 等 skill 文件整理而成。这些 skill 定义了一套完整的、可在 AI Agent 中实践的开发方法论。