
开头部分要直接进入场景。先交代清楚这次改单词的需求到底有多让人血压飙升以及为什么它最终会变成一次 500 行文档的深水区作业。先别急着喷 AI 小题大做等你看完影响面分析你会庆幸它帮你写了 500 行而不是改完一个单词就收工。1. 起因领导说改一个单词我却翻遍了整个仓库事情开始得很朴素。产品经理在群里甩了一条消息后台列表页的操作按钮把删除改成归档吧用户觉得删除太吓人了。听起来人畜无害对吧改一个按钮文案前端页面字符串一替换最多再加个国际化词条。但做过 B 端系统的朋友都知道文案改动的背后往往藏着一句潜台词删除本来就是假删除现在改成归档用户会默认数据还在、还能找回那你就不能只改字儿你还得保证它真的能被找回。我当时的反应是先问清楚需求边界。结果产品经理补充了一句也不光后台用户端的说明文档里也把删除改成归档吧语义保持一致。就这么一句轻飘飘的保持一致让我意识到事情没这么简单。用户端的说明文档、后端接口的日志描述、数据库表注释、埋点事件名称、定时清理任务的状态判断……只要业务逻辑里有删除这个概念的地方都可能因为这一处文案变更产生连锁反应。最让我头疼的是删除这个状态在不同系统里的语义并不一样。列表页的删除是软删除数据库记录置一个 deleted 标记但文档里某些流程的删除是硬删除数据直接物理清除。如果我一股脑把所有删除都改成归档等于把两类完全不同的行为混为一谈将来用户点击归档却发现数据彻底没了这锅得找我。于是在动手之前我做了一份影响范围清单列完之后自己都沉默了前端按钮 1 处、列表过滤逻辑 3 处、后端接口路径注释 2 处、数据库表注释 3 张表、埋点事件 2 个、定时任务日志关键词 4 处、用户端文档 7 个章节。加起来远超一次简单的文字替换。这时候我想到的不是自己闷头改而是试试 AI 能不能基于这份影响范围输出一份完整的变更方案。结果这一试就走上了 Spec Coding 的路。2. Spec Coding 到底是什么先写清要什么再让 AI 写怎么做在聊这次经历之前得先把 Spec Coding 这个概念说透。它不是一个新框架也不是某个工具的专属功能而是一种工作方式的统称在写代码之前先把规格说明Specification写清楚再让 AI 按规格去产出代码或文档。传统的开发流程里我们习惯想到哪写到哪。需求一句话代码半小时遇到边界情况再临时打补丁。而 Spec Coding 的核心思路是反过来的需求到手之后先花时间把要什么换算成机器能理解的结构化描述包括输入、输出、状态流转、异常分支、影响范围然后再把这些描述作为提示词交给 AI。有人可能会说这不就是写设计文档吗对本质上确实是设计文档但 Spec Coding 和传统设计的区别在于它的交付对象不仅仅是人更是 AI。人看设计文档看的是逻辑通不通AI 看设计文档看的是信息全不全。只要你的规格里明确定义了某个状态的枚举值、某个接口的返回结构、某个边界条件下应该走哪条分支AI 生成出来的代码大概率是能直接运行的。我第一次正经尝试 Spec Coding 是因为一个临时脚本。当时要处理一批用户导入数据规则特别多手机号去重、空值补默认、格式非法要单独导出、重复数据要标记来源。这些规则如果直接说给 AI或者干脆自己写也能完成但回头维护起来就是一坨。我把需求整理成了一份规格文档里面有输入表结构、输出文件格式、去重判定逻辑、异常数据分级处理规则甚至标注了性能上限是十万行。结果 AI 生成出来的脚本第一次跑就通过了七成用例剩下三成是因为我自己规格里没写清楚手机号空格是否参与去重。那次经历让我彻底转变了态度与其抱怨 AI 写代码不准不如先把规格写到位。很多时候模型生成结果不理想真不是模型笨是我们没说清楚。回到改一个单词这件事。如果我只丢给 AI 一句把删除改为归档它大概率会老老实实把所有叫删除的地方全替换掉包括那些语义上并不对等的位置。这恰恰是 Spec Coding 要避免的灾难。3. 一次改单词引发的 500 行规格文档完整拆解3.1 影响面分析从一个词到一个系统产品经理的保持一致四个字让我不得不把整个系统里所有涉及删除与归档语义的地方全部过一遍然后按必须改、建议改、不改三档分类。这个分类过程本身就是规格文档的雏形。第一类必须改的是面向用户的可见文本。后台列表页按钮、批量操作提示、用户端文档、操作日志里展示给管理员的消息模板。这些地方用户会直接看到删除两个字改了语义之后不能继续露馅。第二类建议改的是内部开发者可见的中介层。比如后端接口的 Swagger 描述、数据字典的注释、代码里注释掉的业务提示。这些地方用户看不见但开发者每天看。如果不改将来排查问题时会被删除和归档两个词反复误导。第三类是绝不能跟着改的逻辑核心。比如数据库里is_deleted字段名、RESTful 接口里的DELETE方法语义、消息队列里 topic 为user.delete的事件名。这些属于系统稳定契约改了就要出大事故。这个三档分类法被我后来写进了规格文档最开头。它让 AI 知道哪些改动是表面替换哪些改动是深层逻辑的重新定义避免模型拿着删除变归档的令牌到处乱砍。3.2 规格文档的结构AI 最需要的四个部分基于三档分类我开始写规格文档。整份文档最终有 500 多行看似夸张但如果拆开来看每个部分的信息密度都很高AI 能从中提取出真正有用的上下文。第一部分是变更目标。我没有写全局替换删除为归档这种笼统描述而是精确到前台可见文案全部替换内部技术字段保持不变日志与埋点使用语义分离的新事件名。这么写的好处是AI 在生成代码时会主动区分哪些位置是展示层哪些是持久层不会傻乎乎地把is_deleted也改成is_archived。第二部分是状态流转定义。这是最容易出问题的地方。归档在这个系统里到底是什么状态是软删除的别名还是独立于正常和删除之外的第三种状态?我在规格里明确画出了状态机正常 - 归档 - 彻底删除归档后不允许直接切换回正常只能走恢复审核流程。没有这个限定AI 生成的代码很可能会允许用户把一个已归档数据直接编辑保存这在业务上是不允许的。第三部分是影响范围清单。我把前面梳理的三类改动列成一张表逐条标注文件路径、改动类型、是否涉及数据库、是否涉及前端展示。AI 拿到这张清单就等于拿到了一张施工地图改哪里、不动哪里一目了然。第四部分是验收标准。我写了几条硬性要求按钮文案变更后语言包 key 不冲突归档操作走软删除接口物理清理任务不误删归档数据埋点事件新旧名称映射关系可查询。有了验收标准AI 生成的代码和测试用例就有了参照物。写到这里500 行只是一个自然结果。它不是因为 AI 喜欢长篇大论而是因为这 500 行里每一行都在回答这个单词改动到底波及了谁这个问题。文档写完的那一刻我心里其实已经很有底了。3.3 从规格到提示词文档怎么写AI 才愿意听文档写好了接下来是把它变成真正能让 AI 理解并执行的提示词。这一环节我踩过不少坑经验是别把整个文档一次性扔给 AI要分层喂。第一次我图省事把 500 行规格文档一口气粘贴进对话窗口结果 AI 的回复明显开始敷衍开头还好越到后面越像在复读我规格里的原话没有自己的推理。后来我改成三层投喂策略。第一层给 AI 一个简短的全局任务描述类比于项目背景这是某 B 端管理系统的文案语义升级需求目标是将用户可见的删除文案调整为归档但底层数据结构与接口契约不发生变化。请基于我提供的规格文档完成代码变更和文档更新。第二层才是详细的规格文档正文。但我不会真的把 500 行一次性发过去而是按模块拆开比如先发影响范围清单等 AI 确认理解后再发状态流转定义。这样既控制了上下文长度也能在每一步引导 AI 给出反馈而不是憋到最后一次性生成一堆跑偏的代码。第三层给出示例。挑一个最典型的改动点手动写好改前改后对比放在提示词末尾。AI 对示例的遵循程度比对自然语言描述的遵循程度高得多。我常把规格文档里的某一条规则配上一个具体代码 diff模型看到之后生成其他位置的改动时风格会自动对齐。4. 从规格到代码AI 是怎么把文字变成 500 行实现的4.1 第一轮生成接口层与前端按钮联动规格文档喂进去之后我让 AI 先产出后端接口层与前端按钮的联动改动。这个范围不大但涉及两个端很适合验证 AI 对规格的理解。AI 的回复速度很快先给了后端接口的改动方案保留原来的 POST /api/resource/delete 作为兼容接口但新增 POST /api/resource/archive内部调用同一个软删除逻辑只是日志操作类型从 DELETE 变为 ARCHIVE。前端按钮改成调用新接口文案改为归档同时气泡确认框的提示语也从删除后不可恢复改为归档后可恢复但需通过审核流程恢复。说实话看到这个输出我愣了一下。因为我没有明确告诉 AI 新增一个接口我在规格里写的是内部技术字段保持不变接口路径可新增但旧接口需保持兼容。AI 自己判断出新增接口比改原接口更安全这个推理路径是合理的而且它没有破坏原有契约。但代码审查阶段我发现一个问题AI 在新增归档接口时把原有软删除逻辑里的一些依赖注入也复制了一遍导致同一个 service 实例被构造了两次。这本不是大问题但如果你不是通过规格驱动而是一句把删除改成归档丢给 AI它很有可能会悄悄改掉原接口的行为然后告诉你已经改完了。4.2 第二轮生成数据库注释与文档的批量修订后端接口定了接下来是数据库注释和用户端文档这些低技术含量但高工作量的部分。这种活最适合 AI不需要它做复杂决策只需要它严格按照规格文档里的术语映射表遍历所有相关文件。我定义了一张术语映射表里面明确列出哪些字段名和注释是关键保留项哪些描述性文本需要替换。比如第一类是is_deleted、deleted_at、del_flag这类字段名一律保留第二类是数据字典 value 为 1 时的中文注释已删除,必须改成已归档第三类是实体类里的 Javadoc 注释可以改。AI 基于这张映射表跑了一遍全仓库文本扫描把匹配到的位置整理成一个变更清单每个位置都标注了建议修改或保持不动。我只需要快速复核它标记为建议修改的文件确认没有误解保留项就可以批量应用。这一步最大的收获不是省了多少时间而是 AI 给了我一双全局视角的眼睛。我自己人工扫仓库大概率会漏掉某个不起眼的 XML mapper 文件里的一行 SQL 注释但 AI 不会它会老老实实把每个命中项都列出来。4.3 第三轮生成测试用例与回归验证规格文档里的验收标准这时候派上了用场。我让 AI 基于验收标准生成一组测试用例重点覆盖三块归档后的数据列表是否默认隐藏、归档操作后日志里的操作类型是否为 ARCHIVE、已归档数据是否无法直接触发物理清理。AI 生成的测试用例共 14 条覆盖了正常路径、异常路径和边界条件。其中有一条用例我印象很深创建一条数据调用归档接口然后用原删除接口去删除这条已归档数据断言原删除接口返回业务错误码ARCHIVED_RECORD_NOT_DELETABLE。这个场景在我们内部讨论时压根没提过但确实是个真实存在的操作路径。AI 之所以能想到这条用例完全是因为规格文档里的状态机写清楚了归档后不允许直接删除这个约束。这让我理解了为什么很多人觉得 AI 测试生成不准因为你没给它一个可以推理的规则基础。规则越细生成出来的测试越能打中要害。4.4 为什么最终是 500 行而不是更多或更少整轮操作下来如果把 AI 生成的接口定义、状态流转逻辑、测试用例、文档修订稿、变更清单和注释补丁全部加起来正好是 500 多行。有人可能会问改一个单词而已真的需要这么多产出吗我的回答是如果这个单词在系统里只出现在一个按钮上那 50 行都嫌多。但它同时出现在前端、后端、数据库、埋点和文档里而且每个位置的语义约束都不一样那 500 行是保守估计。因为这 500 行里的大部分是规格分析和变更清单真正最终的代码 diff 只有不到 200 行。还有一个数值层面的事实如果我让 AI 直接改它会生成大概 150 行代码我手动改大概是 200 行代码加 2 小时排查而用 Spec Coding 的方式AI 生成了 500 行其中一半是规格之间的约束推理和测试边界检查。这笔账看起来好像亏了但你算上沟通成本、误改风险和未来维护时的语义混乱Spec Coding 反而是最省的一版。5. 收获与反思Spec Coding 的适用边界和我的真实体会经历这次改单词事件后我对 Spec Coding 的边界有了更清楚的认识。它不是万能药甚至在一个场景下反而会成为负担需求本身极其简单且封闭。比如改一个 CSS 的颜色值、调整一个弹窗的标题文字这种改动直接交给 AI 或者自己动手都行写规格文档纯属浪费时间。但一旦需求开始出现这处改了那处也得跟着改的苗头Spec Coding 的优势就会指数级放大。因为它的核心价值不在于让 AI 帮你写代码而在于逼你在动手之前想清楚哪些地方不能改、哪些地方必须改、改完之后依据什么标准来验收。这个过程本身就是在降低未来返工的概率。还有一点不得不提Spec Coding 对提示词的要求比想象的更高。很多人用 AI 编程觉得不靠谱大概率是提示词里只有一个模糊的目标而没有边界条件。这次 500 行文档的经历告诉我AI 能不能从要什么推导出怎么做完全取决于规格里有没有把不要什么写清楚。我在状态流转定义里特意加了一行任何情况下禁止直接将归档数据状态翻转为正常状态必须先进入待审核队列。没有这一行约束AI 在生成批量操作代码时很可能会漏掉审核链路。最后说一个具体的技巧把规格文档看作一个可版本化的产品而不是一次性提示词。我会把它提交到 git 仓库和代码一起维护。下一次需求再涉及归档语义时直接基于旧文档迭代而不是从零开始重新解释一遍背景。这个习惯让我在后续多次需求中复用同一份规格的时间成本趋近于零。这次为了改一个单词写了 500 行文档的事看起来像段子实际上是我最近工作中最踏实的一次交付。它教会我一个很简单的道理AI 不是替你思考而是帮你把思考的结果更快地变成现实。前提是你得先有一份能让 AI 读懂的思考过程。