Spec Coding实操:改一个单词为何牵出500行代码文档?
2026/9/8 7:26:03 网站建设 项目流程

最近处理一个需求,让我对“Spec Coding”有了完全不一样的理解:产品经理只是想把系统里所有面向终端用户的“用户”统一改成“客户”这一个单词,结果AI配合现有规格文档,最终产出了将近500行代码文档。一开始我也觉得夸张,但把变更过程完整过了一遍之后,我意识到这才是AI辅助开发该有的样子——文档不再是文档,而是代码的另一种存在形式。

这篇文章想聊清楚三件事:Spec Coding到底是什么,为什么改一个单词会牵出500行的文档,以及如果你想在自己项目里落地这套玩法,有哪些可以直接照抄的步骤和必须避开的坑。适合对AI编程感兴趣、被“AI写代码很爽但需求变更很痛”困扰过、或者想提升团队需求传达效率的人。

1. 起因:把“用户”改成“客户”,一个单词怎么会带出500行文档

1.1 需求看起来真的很小

当时的需求背景不复杂。业务侧把合作方统称为“客户”,而系统里大量文案、字段、接口注释还在用“用户”。产品提了个变更单:把面向终端用户的“用户”统一改成“客户”。

放到传统开发流程里,这基本就是一个“全局替换+回归测试”的小活。多数人会直接打开IDE,Ctrl+Shift+H,把所有“用户”换成“客户”,跑一遍测试,然后提交代码。

但在Spec Coding工作流里,事情不是这么走的。因为规格文档里每一个术语都不是孤立存在的。就拿“用户”这个词来说,它在规格仓库里至少出现在这些位置:

  • 领域事件名称:比如UserCreated
  • 数据库字段注释:比如created_by_user_id
  • API错误消息:比如USER_NOT_FOUND
  • 权限角色描述:比如普通用户
  • 测试用例里的actor:比如当用户登录系统时
  • 示例数据和数据字典
  • 状态机描述里的主体定义

一个单词改了,这些位置必须全部同步改,否则规格内部就出现语义分裂,测试驱动会失败,代码也会产生坏味道。这就是为什么AI最后产出了500行文档——它不是想炫技,而是在规格约束下做一次完整的语义迁移。

1.2 传统改法与Spec Coding改法的岔路口

传统方式处理这种变更,最大的问题是:没人能证明“改全了”。全局替换只能处理字符串完全一致的情况,但“用户”和“客户”在代码里可能以不同的形态出现,比如userUserUSERuser_idend_user,一旦人工筛选,漏掉几乎是必然的。

我见过太多线上事故是这样发生的:界面文案改成了“客户”,但订单导出的Excel表头还是“用户”;异常日志里一半写user,一半写customer,排查问题的人被误导了三小时。

Spec Coding的思路是反过来的:先认账,再干活。它承认“一个单词的变更一定会波及其他产物”,所以把所有的引用关系显式记录在文档里,然后让AI基于这些文档做影响分析和逐项修改。两种方式的对比非常明显:

维度传统改法Spec Coding改法
修改对象直接改代码文件先改规格,再投影到代码/测试/文档
怎么验证改全了靠测试用例覆盖率规格一致性检查+测试双保险
需求追溯散落在commit message里在impact-analysis里全量记录
单个词变更成本看着低,但漏改风险高看着高,但每处修改都可追踪
部门协作价值几乎为零产品、开发、测试读同一份文档

说白了,传统方式追求的是“这次改完就行”,Spec Coding追求的是“这次改完,下次还能改得起”。

2. Spec Coding的本质:AI写的不是代码,是可执行的需求投影

2.1 先分清楚:让AI写代码,和让AI写规格,境界完全不同

很多朋友对AI编程的理解是这样的:把需求描述扔给AI,AI生成几十行代码,你复制粘贴,跑通就完事。这没错,但这只是“AI辅助编码”,离Spec Coding还有一段距离。

Spec Coding,全称可以理解为Specification Coding,也就是规格驱动编码。它强调的不是“让AI帮你写实现”,而是“让AI先把需求变成一份精确、结构化、可验证的规格文档,再让规格文档自动投影出代码、测试用例、接口契约和其他派生文档”。

举一个生活化的类比。普通AI编程就像你直接告诉装修工人“我要一个原木色餐桌”,工人凭经验给你做出来。Spec Coding则是:你先请设计师画一套完整的施工图,图纸上标明尺寸、材质、连接方式、承重标准,然后工人照着图纸施工。餐桌最后一个螺丝松了,你知道一定是图纸哪一步出了问题,而不是靠猜。

对应到开发里,好处就非常明显:

  • 需求可追溯:每行代码都能找到它对应的规格条目。
  • 测试可验证:验收标准在写代码之前就定义好了。
  • 代码可解释:AI不会突然给你来一段“野路子”写法。
  • 变更可评估:改一个单词的影响范围,会在动手之前就被文档化。

2.2 三层投影:行为、契约、验证

我在实践里习惯把Spec Coding的投影分成三层,AI的所有产出都在这个框架里规规矩矩地运行。

第一层是行为投影。这层描述系统“应该做什么”。最典型的载体是用户故事和Gherkin场景文件。举例:

场景:客户查看自己的订单状态 假如 客户 “张三” 已登录系统 当 张三打开订单详情页 那么 页面展示当前订单的state字段 并且 state字段的取值来自订单状态机

第二层是契约投影。这层描述系统“对外以什么结构交互”。OpenAPI、JSON Schema、数据库表结构,都属于契约层。AI会根据行为投影生成或更新这些接口定义,保证对外通信的一致性。

第三层是验证投影。这层把行为投影和契约投影进一步转成自动化测试。AI生成测试骨架、断言逻辑、测试数据,确保最终代码确实满足规格。

这三层之间保持单向依赖:行为投影决定契约投影,契约投影决定验证投影。日常开发里AI一般会一次性产出,但真正出问题的时候,我们永远是回过去改最上游的行为投影,然后在让AI逐层刷新下游,而不是直接去改一个TestCase里的魔法数字。

3. 动手实操:用AI做一次“改一个单词”的Spec Coding变更

3.1 准备一个规格仓库:让“文档”先于代码

这一节我会用一个具体例子演示。假设系统里有一个订单状态模块,原来的规格里用STATUS表示“状态”,现在产品要求全部改成STATE,理由是业务方已经统一术语,后续还要对接外部系统,必须消除歧义。

第一步是建立规格仓库目录。我们的做法是每个业务能力模块一个目录,里面至少包含六类文件:

specs/ 0001-order-status/ README.md # 模块说明与最新变更摘要 terminology.md # 术语表 domain-model.md # 领域模型与状态机描述 api-contract.yaml # OpenAPI接口契约 features/ order-lifecycle.feature # Gherkin行为场景 tests/ # 由spec生成的测试骨架 adr/ 0003-rename-status-to-state.md # 架构决策记录

这套目录的好处是,AI拿到之后能在几秒钟内建立一个“完整上下文快照”。它知道这个模块有哪些领域概念、对外暴露什么接口、行为场景长什么样、历史上做过哪些决策。这一切就是它后续修改的依据。

如果项目还没有这种规格仓库,建议不要急着让AI写代码,先让AI生成一份最小规格,哪怕只覆盖一个核心业务动作,也要先建立“文档先于代码”的纪律。否则Spec Coding就是空中楼阁。

3.2 关键提示词与AI产出拆解

当需求变更进来,我会给AI发一个明确的变更指令,而不是模糊地说“帮我把STATUS改成STATE”。实测下来,下面的提示词模板效果最稳定:

你现在是规格驱动开发引擎。 需求变更:将订单状态模块中的术语 STATUS 改为 STATE。 原因:统一业务口径,消除与外部系统交互时的语义歧义。 范围:仅限 specs/0001-order-status/ 目录。 任务: 1. 审查该目录下的所有文件,定位所有出现 STATUS 的位置。 2. 生成 impact-analysis.md,列出每一个位置的文件名、当前内容、影响级别。 3. 依次更新 terminology.md、domain-model.md、api-contract.yaml、order-lifecycle.feature。 4. 根据更新后的规格,同步调整 tests/ 下所有测试骨架。 5. 输出最终的变更说明,包含:变更理由、影响清单、逐文件diff说明、需要人工确认的风险点。 硬性约束: - 禁止修改与STATUS无关的内容,包括其他字段、文案、业务逻辑。 - 禁止在规格中新增或删除字段。 - STATUS作为内部枚举值真实存在时,保留对应枚举,只重命名标识符。

AI执行完之后,产出物大致长这样:

变更结果: - impact-analysis.md 64行 - terminology.md 32行 - domain-model.md 88行 - api-contract.yaml 142行 - order-lifecycle.feature 96行 - tests/ 120行 - README.md 28行 合计:约570行

这套文件加起来确实接近500行。注意,AI并没有写任何“功能实现代码”,它写的是“代码的文档”——术语定义、契约、场景、测试、影响分析。但这些文档比代码更接近业务真相。

3.3 为什么不能直接全局替换

很多人会问:为什么不直接让AI全局把STATUS替换成STATE?因为在规格里,“STATUS”这个词在不同位置代表完全不同的语义:

  • api-contract.yaml里,status是响应字段名,对应一个字符串枚举。
  • domain-model.md里,STATUS可能是一个枚举类型名称,内部还有PENDINGPAIDSHIPPED这些值。
  • order-lifecycle.feature里,订单状态是自然语言描述,根本不会出现大写的STATUS
  • tests/里,可能会有ORDER_STATUS_MISMATCH这样的错误码常量。

如果无脑替换,API文档里的字段名也许能直接改,但领域模型里的枚举类名和具体值需要分开处理,错误的常量名也不能跟着一起改。AI基于规格文档做修改时,它看到的是语义,而不是字符串。这正是Spec Coding对比普通AI编程最有价值的地方:AI不只是“找到并替换”,而是“理解并迁移”。

4. 那500行到底装了什么:一份代码文档的内容拆解

4.1 逐文件拆解:术语、模型、契约、场景、测试

这500行不是垃圾输出,每一块都有它的位置。我按下表拆过一遍,读者可以对号入座:

文件行数主要内容为什么这次变更要动它
impact-analysis.md约64行受影响位置清单、影响级别、风险点为整个变更提供证据链,也是人工审查的入口
terminology.md约32行STATUS与STATE的定义、别名、禁用词术语表是语义事实源,必须先改
domain-model.md约88行状态机节点、字段映射、实体属性说明领域模型里的状态属性名需要跟随重命名
api-contract.yaml约142行OpenAPI字段名、枚举示例、错误码对外契约一旦不一致,客户端立刻爆破
order-lifecycle.feature约96行所有场景里的用户动作、状态断言行为规格必须与领域模型保持一致
tests/约120行测试文件名、测试夹具、断言字段测试是规格的验证投影,不能留旧术语
README.md约28行变更说明、迁移指引、注意事项给下一个开发者和业务方留底

拆解之后你会发现,每一类文档都在回答不同角色的问题。产品经理关心术语表是否改对了;后端关心API契约能不能兼容;测试关心断言逻辑是否还成立;运维关心错误码有没有变化。如果没有Spec Coding机制,这个问题没有任何人能一次性说清。

4.2 为什么这些文档能被当成“代码”来管理

“文档即代码”不是一句口号,它有很具体的工程含义。

首先,这些文档全都是纯文本结构化格式,Markdown、YAML、Gherkin。它们可以被Git跟踪,可以被diff,可以被code review,可以设置行级注释。其次,它们可以被自动化工具解析。比如CI里跑一个脚本,检查terminology.md中的术语是否与api-contract.yaml中的字段命名一致,不一致就报警。这就是“可执行的文档”。

这一点改变了我们debug的方式。以前代码报错,我只能看堆栈;现在规格不一致,我直接在CI日志里看到:“订单状态模块的术语表中已定义STATE,但contract中仍存在status字段,请检查。”问题定位时间从小时级缩短到分钟级。

4.3 这500行有哪些部分是真正需要人review的

AI能把所有文档联动更新,但不代表人可以闭眼merge。我在实际review中总结出三个机器容易犯、必须人盯死的点。

第一,AI在改写自然语言场景时,容易把语义悄悄变掉。比如原本是“客户提交订单后,系统将STATUS置为PENDING”,AI可能改成“系统将状态置为待处理”,表面上对,但“待处理”如果没在术语表里定义过,就会引入新的歧义。第二,AI对枚举值的处理偏保守,可能只改了字段名,没改内部枚举值,导致契约与测试对不上。第三,impact-analysis里AI声称“已全部更新”,但它列的清单是否完整,需要人抽查至少一两个原始引用点。

我把这种review叫做“抽查清单对照法”:人只需要挑3到5个受影响的文件,手动确认修改是否符合语义,不需要重新读一遍500行。其余部分交给规格一致性检查。

5. 三个月的实战踩坑:Spec Coding失控的高发场景与收敛手段

5.1 翻车现场一:AI太配合,把范围越扩越大

第一次带团队跑Spec Coding时,我让AI把订单模块里的STATUS改成STATE,它除了完成正事,还顺手帮我把“订单”改成“采购订单”、“已支付”改成“支付完成”。它的理由写得很正经:“为了全仓库术语统一。”

问题在于,这个仓库里同时存在“订单”和“采购订单”两个概念,本次需求根本没打算动它们。AI的好心直接污染了跨模块的其他文档,CI检查也报出大量无关ant差异,review成本一下翻倍。

后来我在所有变更提示词里固定加了两句话:只改我指定的术语;严禁修改任何与本次变更无关的业务语义。再加一条,如果AI发现其他术语不一致,只能写进“备选观察项”,不许在本次变更中直接修改。从此AI乖了很多。

5.2 翻车现场二:规格与代码失联,文档变成一次性用品

还有一个特别容易掉的坑:文档写得很漂亮,但代码改完之后没人回头更新规格。两周后另一个人让AI改数据字典,AI按旧规格生成结果,产生出一批与线上代码脱节的文档。

这个问题本质上是流程纪律的问题。解决办法是在PR模板里加一个勾选项:“如果本次变更涉及业务概念、接口字段或状态取值,必须同步更新对应规格文档。”同时让CI检查规格文档的更新时间是否早于代码文件。如果程序化地保证“文档先于代码”,失联问题会大幅减少。

5.3 翻车现场三:粒度失控,整个仓库变成“改不起的大文件”

第三个坑比较隐蔽:团队为了让AI生成更准,把所有细节都塞进规格文档。结果一个中等模块的规格仓库膨胀到两万多行,任何一次小需求变更,AI都要把所有文件过一遍,输出的影响分析动辄上千行,人根本审不完。

这是典型的“粒度失控”。规格不是越细越好,它只需要承担三类信息:业务术语、行为场景、对外契约。具体的页面布局、数据库索引、代码风格,都不应该进入核心规格。我给团队定的经验法则是:一份规格文档如果一屏看不清核心内容,那它已经太胖了。保持精简,Spec Coding才有生命力。

5.4 收个尾:我用“三层约束法”让AI老实下来,外加一个影响面指纹技巧

针对AI自由发挥的问题,我最终沉淀出一套“三层约束法”,现在写进了所有Spec Coding项目的system prompt里。

  • 领域约束:AI必须遵守术语表中已定义的语义,不新增未定义术语,不改变业务规则。
  • 范围约束:AI只能处理本次变更指定的模块与字段,禁止扩大范围,禁止顺手优化。
  • 格式约束:AI必须按目录模板输出,字段名不可增删,编号规则不可改变。

这三层约束放在提示词最前面,能显著降低AI“创作热情”带来的风险。但只靠提示词还不够,我建议在规格仓库里加一种轻量机制。我现在会给每份需求变更生成一个“影响面指纹”,它就是一个由变更涉及术语组成的简短集合,比如{ORDER, STATE},写进impact-analysis.md的头部。下一次任何人或AI要评估一个新变更是否与之前变更冲突时,只需要比对指纹交集,秒级完成,不用再把几百行文档从头读一遍。

这个技巧是我三个月实践下来最出乎意料地实用的一个。它让团队从“害怕改一个单词”变成“欢迎改一个单词”,因为每次变更都像给系统做一次免费的语义体检,所有隐藏的引用关系都会被暴露出来,然后再被妥善修复。

Spec Coding真正让我上头的点,是它把AI从“代码生成器”变成了“规格翻译官”。它没有消灭开发者的工作,而是帮我们把工作重心往上移了一层——从纠结代码怎么写,变成了专注语义怎么定。这一层的变化,才是未来几年AI编程最有价值的演进方向。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询