第2节:规范驱动开发SDD,让AI永远在轨道上
AI编程企业级实战
上一节:第1节:一个人的架构师,Claude Code是你的团队
本节:第2节:规范驱动开发SDD,让AI永远在轨道上
下一节:待更新
带过团队的人,大多都有一个很深的体会:你脑子里想得再清楚,只要没有落成明确的文字,对方做出来的东西,往往就会和你想的不一样。
但如果你给了接口文档、数据模型、命名规范、错误码定义,交付质量通常就会立刻上一个台阶。
Claude Code 也是一样。它很强,但它不会读心。你不告诉它规则,它就会自己“脑补”出一套做法,而且每次写出来还可能都不一样。
这就是我们接下来要讲的规范驱动开发 SDD。
一句话概括:先定规范,再让 AI 按规范执行,而不是一上来就让它直接写代码。
规范不是一次性指令,而是一套体系
很多人已经发现了一个规律:给 Claude Code 的指令越清晰,输出质量就越高。
但这里有一个很容易被忽略的问题:你在某一次对话里补充得再详细,那些要求也只对那一次对话有效。
比如我在做模型提供商管理时,曾经把要求写得很细:
实体叫 Provider,不要加前缀或后缀。
返回格式统一。
使用 Result 包装。
错误码按模块分段。
不要引入设计模式。
于是 Claude Code 输出得很干净,命名统一,格式规范,结构也足够简洁。
但过了一段时间,当我开始做 Agent 模块时,指令里没有再重复这些规范,只写了“实现 CRUD 接口”。我以为它会记得,结果并不会。
单看每一段代码,也许都不是 bug,功能甚至是完整的。但一旦放到同一个项目里,就会出现两套风格:命名规则不同,返回格式不同,前端要适配两种响应结构,后续维护时也要先重新理解“这个模块到底遵循哪套规矩”。
问题出在哪里?
不是 Claude Code “忘了”,而是它根本没有看到。它没有长期记忆,每次新对话,本质上都是重新开始。
所以,我们需要让规范被稳定记录下来,并且在每次工作时都能自动进入上下文。只有这样,Claude Code 才能在不同模块、不同阶段下,始终沿着同一套规则工作。
这就是 SDD 和“写好提示词”之间的本质区别。
写好提示词,是一次性的技巧;SDD 是贯穿整个项目生命周期的方法论。
SDD 的完整工作流
1. 先定规范
规范并不一定复杂。真正有用的规范,往往就集中在几个最容易让 AI 跑偏的地方。
命名规范
如果你不约束命名,每个模块都可能长得不一样。实体类要不要加前缀,字段用驼峰还是下划线,接口路径用单数还是复数,这些它每次都要“猜”,而且每次可能猜得都不一样。
实体类使用大驼峰命名,不加前缀和后缀,例如 Provider、Agent、ChatMessage。
字段使用小驼峰命名,例如 apiKey、baseUrl、modelName。
接口路径统一为 /api/v1/{资源复数名}。
接口规范
如果你不约束返回格式,问题会更明显。有的接口返回 { "code": 200, "data": {...} },有的返回 { "error": "not found" },还有的直接返回 ResponseEntity。前端一接这种接口,适配成本会立刻上升。
所有接口统一返回 Result,格式为 { code, message, data }。
列表字段为空时返回空数组 [],不要返回 null。
分页参数统一使用 page 和 pageSize。
page 从 1 开始,pageSize 默认值为 20。
错误码规范
如果错误码没有统一规则,项目很快就会乱掉。有人直接用 HTTP 状态码,有人用自定义字符串,也有人随手写个数字。更糟的是,不同模块的错误码可能还会撞号,你根本分不清 2001 到底表示 Provider 的“网络超时”,还是 Agent 的“模型不存在”。
错误码统一使用四位数字。
按模块分段:
1000-1999 为通用模块。
2000-2999 为 Provider 模块。
3000-3999 为 Agent 模块。
4000-4999 为 Chat 模块。
5000-5999 为 MCP 模块。
设计原则
这部分往往是最关键的。
Claude Code 的训练数据里有大量“最佳实践”代码,所以它天然倾向于做得很“完整”:工厂模式、策略模式、三层抽象、接口隔离,能上的都想上。
但对于一个几十人使用的内部平台来说,很多设计模式并不是资产,反而是负担。
不引入不必要的设计模式,除非有明确要求。
不做过度抽象,一层能解决的问题,不要拆成两层。
不引入技术栈之外的新依赖,如有需要先确认。
这几块内容加在一起,可能也就一页纸。
但“有规范”和“没规范”之间的差距,常常不是一点点,而是从“勉强可用”到“稳定可维护”的差距。
2. 让 AI 按规范执行
规范写好之后,下达任务时要明确引用它。
不是说“帮我做个 Agent CRUD”,而是说:
按照 CLAUDE.md 中的规范,实现 Agent 的 CRUD 接口。
这句话的重点,不只是“按照规范”这四个字。
因为 CLAUDE.md 已经在上下文里,Claude Code 理论上是能看到的。真正重要的是,这句话在提醒它:这次不要按你自己的默认经验发挥,而要优先服从项目规范。
有了 CLAUDE.md 之后,你再回到 Agent 模块这个场景:
实体类会叫 Agent,而不是 AgentConfig,因为规范写了“不加前缀后缀”。
返回格式会统一走 Result,因为规范写了“统一返回结构”。
错误码会从 3000 段开始,因为规范写了“按模块分段”。
它不会随手加上 Builder 模式,因为规范写了“不引入不必要的设计模式”。
同样是一个 AI,有规范体系和没有规范体系,最终输出的一致性会完全不同。
3. 由人验证输出
有了规范之后,review 的效率会明显提升。
因为你不再是漫无目的地看代码,而是在对着一份清单逐项核查:
命名是不是按规范来的?
返回格式是否统一?
有没有引入你明确禁止的设计模式?
错误码是否落在当前模块对应的分段里?
规范的价值,就在于它把 review 从“主观判断”变成了“客观核查”。
这个转变对效率的提升非常大。你不需要每次都重新思考“这里应该怎么写”,因为标准已经提前定好了。
4. 持续迭代规范
在验证输出的过程中,你一定会不断发现规范还没覆盖到的地方。
这太正常了。没有人能在第一版规范里就把所有情况都想全。
关键不在于“一开始就写得完美”,而在于每次发现缺口时,都及时把它补上。
每次 AI 跑偏,不要只改代码。先停下来问自己:它为什么会跑偏?是不是因为规范没覆盖到?如果是,就补上一条。
一旦这条规则被写进 CLAUDE.md,后续所有对话都会受到约束。你不需要反复在同一个问题上来回纠正。
它跑偏一次,你补一条;以后在这个点上,它大概率就不会再跑偏。
什么样的规范才真正有用?
具体,而不是模糊
没用的规范是这样的:
代码要简洁。
Claude Code 对“简洁”的理解,和你未必一样。它可能觉得“工厂模式 + 策略接口”就是一种很简洁的抽象。
真正有用的规范应该像这样:
不引入不必要的设计模式(工厂、策略、观察者等),除非明确要求。每个功能都用最简单、最直接的方式实现。
这句话几乎没有歧义,它能明确知道:工厂模式这类设计,默认不能上。
再比如,下面这句也很空:
接口要规范。
而真正有效的写法是:
所有接口统一返回 Result,格式为 { code, message, data }。错误码统一为四位数字,并按模块分段。
判断标准其实很简单:Claude Code 看到这条规范之后,是否还需要“猜”你的意思?如果还需要猜,那它就还不够具体。
有优先级,不要贪多
规范并不是越多越好。
太多了,Claude Code 也处理不过来。上下文窗口是有限的,塞进太多规则,反而会稀释真正重要的那几条。
我的原则是:AI 反复跑偏的地方写细,不容易跑偏的地方少写。
比如:
“文件编码使用 UTF-8”,Claude Code 一般不会搞错,不值得占太多篇幅。
“Controller 不写业务逻辑”,这是它经常犯错的地方,就必须明确写出来。
你的注意力,应该放在它真正容易出错的地方。
要写规则,也要写原因
这一点,是我在做 Agent 模块时踩过坑之后才真正意识到的。
在做 Agent 工具列表更新时,我在指令里写了“不要全量删除再全量插入”。Claude Code 第一版还是这么做了,因为它并不理解,为什么这样不行。
后来我补了一句解释:
全量删除再插入,会导致并发场景下 Agent 瞬间失去所有工具关联。如果此时正好有对话在读取工具列表,就会拿到空列表。
第二版,它就改成了差异比对的方式。
这说明一件事:对于涉及工程权衡的规范,不能只告诉 Claude Code “不要这样做”,还要告诉它“为什么不能这样做”。
只有理解了约束背后的原因,它才能在类似场景里举一反三,而不是机械执行。
当然,也不是每条规范都需要解释。
像“实体类不加前缀”这种规则,照做就行,不需要展开说明。但像“不破坏已有接口契约”“不要全量删除再插入”这种涉及系统行为和工程判断的规则,一旦补上原因,Claude Code 的遵循度通常会明显提升。
规范也需要分层管理
最后再说一下规范的组织方式。
随着项目推进,规范会越来越多。如果不分层管理,后面一定会乱。
全局规范
写在 CLAUDE.md 里,整个项目通用。
比如命名规则、接口格式、错误码体系、设计原则、行为约束。这类规范通常在项目初期就应该定下来,后面改动不会太频繁,它们就是整个项目的地基。
模块规范
针对某个模块单独定义。
比如 Provider 模块有自己的接口契约,对话模块有自己的数据流定义,工作流模块有自己的节点类型规范。这类内容可以写在模块目录下,也可以在模块启动开发前单独补充。
任务规范
这是每次给 Claude Code 下达具体任务时的临时补充说明。
比如:
这次不需要分页。
这次异常要区分三种情况。
这次要用差异比对,不要全量替换。
这类规则通常是阶段性的,不一定需要沉淀成长期文档,但在当前任务里依然非常重要。
说到底,SDD 不是让你写更多规范,而是让你把那些真正关键、真正会反复影响交付质量的规则,沉淀成一套稳定可复用的工作方式。
当规范稳定下来之后,Claude Code 才不会每次都从“猜你的想法”开始,而是会一直沿着你设定好的轨道持续前进。
