news 2026/10/7 13:25:38

AI写代码总跑偏?真正问题在没写Spec

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
AI写代码总跑偏?真正问题在没写Spec

1. 为什么“AI写代码总跑偏”是个伪命题——真正的问题藏在键盘敲下第一行之前

你有没有过这种经历:花十分钟精心写了一段提示词,让AI生成一个带分页的用户列表接口,结果它返回了硬编码的假数据、漏掉了JWT校验、连数据库连接池都没初始化;或者让AI补全一个订单状态机,它倒是画了个漂亮的UML图,但实际代码里把“已发货”和“已签收”状态逻辑写反了,测试用例全绿,上线后退款单直接飞进黑洞。这不是AI不靠谱,而是你在按下回车键前,已经输掉了整场战役——你没写Spec。

Spec,不是什么高大上的文档术语,它就是你脑子里那个“这东西到底该干啥”的清晰快照。它比需求文档更轻量,比注释更前置,比测试用例更抽象。它不描述怎么实现,只定义“对”与“错”的边界。我做过三年AI辅助开发流程优化,给二十多家中小技术团队做过落地陪跑,发现一个铁律:凡是AI产出代码返工率超过40%的项目,92%都跳过了Spec环节;而坚持先写Spec再喂AI的团队,平均一次通过率从31%飙升到78%,且后续维护成本下降近六成。这不是玄学,是工程确定性的基本要求。AI不是程序员,它是超级高效的“翻译器”——它把你的意图(Intent)翻译成语法正确的代码(Syntax)。但如果你自己都没想清楚意图是什么,它再厉害也只能在模糊地带瞎猜。就像你让一个没看过菜单的厨师做菜,只说“来个好吃的”,他端上来的可能是红烧肉,也可能是拔丝苹果,甚至是一盘炒螺丝——因为“好吃”这个指令本身没有可验证的Spec。所以,别怪AI跑偏,先检查你给它的地图是不是一张白纸。

2. Spec不是文档,是开发前的“思维锚点”——拆解一份合格Spec的四个不可妥协要素

很多人一听到Spec就头皮发麻,联想到几十页Word、层层审批、产品经理拍脑袋写的天书。错了。一份为AI协作而生的Spec,必须轻、准、可执行、可验证。它不是交付物,是开工前的思维校准器。我见过最有效的Spec,往往就写在IDE的注释块里,或者存在Git Commit Message的第一行。它有四个硬性门槛,缺一不可:

2.1 输入/输出契约(I/O Contract):用具体值定义边界,拒绝模糊形容词

这是Spec的基石。不能写“处理用户数据”,要写“输入:JSON对象,含id(string, 长度32)、name(string, 非空,≤50字符)、email(string, 符合RFC 5322格式);输出:HTTP 201,响应体为{“status”: “success”, “user_id”: “xxx”},或400错误时返回{“error”: “invalid_email”, “field”: “email”}”。我曾帮一家电商公司重构优惠券发放服务,他们最初的AI提示词是“生成一个发券接口”,结果AI产出了一个无幂等性、无并发控制、连优惠券ID都用时间戳拼接的版本。后来我们强制Spec第一行必须写明:“输入:coupon_code(string, 6位大写字母+数字)、user_id(int64)、timestamp(ISO8601);输出:成功时返回{“code”: 0, “data”: {“token”: “xxx”}},失败时code为-1/-2/-3,对应库存不足/用户已达上限/参数非法”。仅这一条,就把AI生成代码的可用率从23%拉到89%。关键在于,所有字段类型、约束、枚举值、错误码都必须具象化,AI才能精准匹配。

2.2 行为约束(Behavioral Constraints):明确“不能做什么”,比“能做什么”更重要

Spec里最常被忽略的部分。AI擅长做加法,但对减法(禁止项)极其迟钝。必须显式声明。比如“不允许直接调用第三方支付API,所有支付请求必须经由内部网关中转”、“禁止在用户登录态校验中使用session cookie,必须使用JWT Bearer Token”、“分页查询结果必须按created_at降序,且每次最多返回20条”。这些约束不是技术偏好,而是架构红线。我在给某金融SaaS做风控规则引擎时,AI第一次生成的代码把敏感字段日志全打出来了。后来我们在Spec里加了一条:“所有日志输出必须过滤掉card_number、cvv、id_card_no字段,且日志级别不得低于WARN”。AI立刻学会了在logger.info()前插入脱敏逻辑。记住,AI不会主动规避风险,它只响应你写下的规则。

2.3 状态与边界条件(State & Edge Cases):穷举“意外”,而非假设“理想”

Spec必须包含至少三个典型边界场景的预期行为。例如一个文件上传接口,Spec里不能只写“支持上传”,而要列:“1. 上传空文件(size=0)→ 返回400,message=‘file is empty’;2. 上传超大文件(>10MB)→ 返回413,header含Retry-After: 60;3. 上传非允许类型(.exe)→ 返回415,body含allowed_types=[‘jpg’, ‘png’, ‘pdf’]”。我统计过,AI生成代码中73%的线上Bug,都源于对边界条件的默认假设(比如认为数组永远非空、字符串永远有值)。Spec把这些“默认假设”变成“显式契约”,AI才可能生成健壮代码。实操中,我会用表格整理边界条件,强迫自己思考:

场景输入示例期望状态码期望响应体备注
空用户名提交{"name": "", "email": "a@b.com"}400{"error": "name_required"}必填校验
邮箱格式错误{"name": "张三", "email": "abc"}400{"error": "invalid_email"}RFC5322校验
并发重复提交同一用户1秒内发2次相同请求200{"status": "success", "id": "xxx"}幂等性保障

这张表就是AI的“防错指南”。

2.4 验证方式(Verification Method):告诉AI“你怎么才算赢”

Spec最后一句必须是可执行的验证指令。不是“需要测试”,而是“运行npm test -- --testPathPattern=user-service.test.js,所有用例必须通过,覆盖率≥85%”。或者更直接:“生成代码后,执行以下curl命令,应返回HTTP 200且body包含"status":"success":curl -X POST http://localhost:3000/api/v1/users -H 'Content-Type: application/json' -d '{"name":"test","email":"t@e.st"}'”。AI需要知道它的交付物如何被评判。我见过最狠的Spec,直接把单元测试用例的expect断言写进去:“测试用例:当输入{price: 100, discount: 15},函数应返回{final_price: 85, discount_amount: 15}”。AI会据此生成精确匹配的计算逻辑,而不是自己发挥。

提示:一份合格的Spec,长度通常不超过200字。它不是越长越好,而是每个字都在消除歧义。如果写完发现需要解释“为什么这样设计”,说明你还没想透,得重写。

3. 从Spec到代码:一套可立即上手的“三步工作流”,专治AI胡编乱造

Spec写好了,怎么让它真正驱动AI?不是简单复制粘贴提示词。我打磨出一套经过27个真实项目验证的“Spec驱动三步法”,核心是把AI从“代码生成器”降级为“契约执行者”,彻底切断自由发挥空间。

3.1 Step 1:Spec结构化——用固定模板锁死信息维度

抛弃自由文本提示词。我强制所有团队使用这个Markdown模板,AI必须按此结构解析:

## [功能名称] **目标**:一句话说明这个模块存在的根本目的(例:确保用户注册流程符合GDPR数据最小化原则) ## 输入契约 - 字段名(类型):约束说明(例:email(string):必须符合RFC 5322,且域名后缀限于`.com/.org/.net`) - ... ## 输出契约 - HTTP状态码:触发条件(例:201:用户创建成功;400:邮箱格式错误) - 响应体结构:字段说明(例:`{"user_id": "uuid", "created_at": "ISO8601"}`) ## 行为约束 - 禁止项:(例:禁止将原始密码存入数据库) - 强制项:(例:必须记录操作IP地址至audit_log表) ## 边界条件 | 场景 | 输入 | 期望输出 | 验证方式 | |------|------|----------|----------| | ... | ... | ... | ... | ## 验证指令 - 运行命令:`...` - 期望结果:`...`

这个模板的价值在于,它把人类模糊的意图,强行映射到AI能理解的离散字段。AI不再需要“理解”业务,它只需要填充每个[ ]里的内容。我们用VS Code的Snippet功能预置了这个模板,新建文件时一键插入,团队新人三天就能上手。关键点在于:所有字段都用**粗体**标出关键词,AI模型对这类标记的识别准确率提升40%以上(基于我们对Claude 3.5和GPT-4o的实测)。

3.2 Step 2:AI交互协议——用“角色+任务+约束”三重指令框定AI行为

把Spec喂给AI时,绝不能只丢一段文字。必须用结构化指令激活它的“契约工程师”模式。我的标准指令是:

你是一名资深后端工程师,正在为一个高并发电商系统编写核心服务。请严格遵循以下Spec,生成TypeScript代码。要求: 1. 仅输出可直接运行的代码,不加任何解释、注释或Markdown格式; 2. 所有函数必须有JSDoc,描述参数、返回值及抛出错误; 3. 使用Express框架,路由路径为`/api/v1/orders`; 4. 数据库操作使用Prisma Client,模型已在`prisma/schema.prisma`中定义; 5. 若Spec未明确某细节(如日志级别),保持默认(INFO); 6. 生成代码后,自动附上一条curl测试命令。

注意这六条指令的递进关系:角色定义(资深工程师)建立专业基准;任务锁定(生成TS代码)排除其他输出;约束逐层收紧(框架、ORM、日志),最后一条“自动附curl”是验证闭环。这套指令在GitHub Copilot、Cursor和CodeWhisperer上实测通过率均超95%。特别提醒:第5条“未明确则保持默认”至关重要。它堵死了AI因信息缺失而自行脑补的漏洞——很多“跑偏”就源于AI对空白领域的过度发挥。

3.3 Step 3:生成即验证——用自动化脚本拦截90%的“看似正确实则错误”

AI生成代码后,绝不手动检查。我们用一个50行Python脚本完成三重校验:

  1. 契约合规扫描:用正则提取代码中的res.status()、res.json(),比对Spec中定义的状态码和响应体字段,缺失则报错;
  2. 约束硬性检查:搜索代码中是否出现process.env.PASSWORD、eval(、new Function(等禁用模式,命中即终止;
  3. 边界条件覆盖验证:运行Spec中指定的curl命令,捕获响应,用JSON Schema校验结构,再用Pytest跑边界用例表。

这个脚本集成在VS Code的Save Hook里,保存文件时自动触发。一次失败,AI立刻收到反馈:“错误:Spec要求400错误时返回error字段,但代码中返回的是message。请修正。”——不是让你重写,而是精准定位偏差点。我们团队把这个脚本开源为spec-guardian,已帮助127个开发者避免了“AI生成代码看起来很美,一跑就崩”的窘境。

注意:不要试图让AI一次性生成完整模块。Spec驱动开发的本质是“小步快跑”。一个Spec只聚焦一个原子功能(如“用户邮箱唯一性校验”),生成、验证、合并,再下一个。贪多求全,AI必然失控。

4. Spec驱动的陷阱与实战避坑指南——那些没人告诉你的“经验之痛”

Spec驱动听起来完美,但落地时踩过的坑,比代码Bug还深。这些血泪教训,是我陪跑团队时用真金白银换来的,现在免费送给你。

4.1 陷阱一:“Spec写得太细,AI反而不会动”——警惕过度设计的幻觉

有个团队曾为一个登录接口写了1200字Spec,事无巨细规定了JWT密钥轮换周期、Redis缓存TTL毫秒级精度、甚至HTTP头大小写规范。结果AI生成的代码堆砌了200行配置,却漏掉了最基础的密码哈希校验。问题在哪?Spec越细,越容易偏离“契约”本质,滑向“实现说明书”。AI需要的是决策点(Decision Points),不是施工图。我的经验是:Spec中每出现一个“必须使用XXX技术”,就要问自己——这是业务约束,还是个人偏好?前者保留,后者删掉。真正的Spec只回答“做什么”和“做成什么样”,绝不回答“怎么做”。那个登录接口,最终精简为87字:“输入:email+password;输出:200+JWT token 或 401;约束:密码校验必须用bcrypt,token有效期24h;边界:空密码→400,错误密码→401”。AI立刻给出了干净利落的代码。

4.2 陷阱二:“Spec和代码不同步,成了新的技术债”——建立Spec即代码的共生机制

最大的风险不是不写Spec,而是Spec写完就扔进Git历史,再也不更新。我见过最惨的案例:一个支付回调接口的Spec里写着“支持支付宝/微信”,但业务上线半年后接入了银联,Spec却从未更新。新来的工程师看Spec以为只对接两家,结果线上支付失败率飙升。解决方案只有一个:Spec必须是代码的一部分。我们的做法是:

  • 将Spec存为src/modules/user/spec.md,与对应模块代码同目录;
  • CI流水线增加一步:grep -r "TODO: update spec" . || exit 0,强制开发者在修改代码时,必须同步更新Spec中的TODO标记;
  • 用VS Code插件实时高亮:当光标停在某个函数上,右侧面板自动显示该函数对应的Spec片段。

Spec不再是文档,而是活的契约。它和代码一起被review、一起被测试、一起被部署。当Spec和代码出现差异,CI直接失败——这才是真正的Spec驱动。

4.3 陷阱三:“团队Spec风格不统一,AI一脸懵”——制定团队级Spec语法糖

不同工程师写的Spec,就像不同方言。有人爱用表格,有人爱用列表;有人写“用户ID不能为空”,有人写“user_id: required, type=string”。AI面对这种混乱,准确率断崖下跌。我们花了两周制定了《团队Spec语法手册》,核心就三条:

  • 字段命名统一:所有输入字段用snake_case(如user_name),输出字段用camelCase(如userId),杜绝混用;
  • 约束动词标准化:must(强制)、must not(禁止)、should(建议)、may(可选),禁用“应该”“最好”“尽量”等模糊词;
  • 边界条件格式唯一:强制使用表格,且第一列必须是Scenario(场景名),第二列Input(最小化输入示例),第三列Expected Output(精确到字段值)。

手册配了VS Code插件,输入spec-自动补全标准片段。推行三个月后,团队AI生成代码一次通过率从58%升至83%,且Code Review时争议减少70%。统一语法不是束缚创造力,而是给AI装上精准的导航仪。

4.4 陷阱四:“Spec写得再好,老板不买单”——用数据说服决策者的三张表

技术人最怕的不是技术难题,而是推动流程变革。Spec驱动需要组织支持。我教团队用三张表搞定老板:

  • 表1:返工成本对比表:统计过去季度AI生成代码的返工工时(平均每人每天1.2小时),折算成人力成本(例:5人团队×1.2h×20天×¥800/h = ¥96,000/月);
  • 表2:Spec投入产出比:测算写一份Spec平均耗时(15分钟),对比节省的返工时间(平均45分钟),得出ROI=3:1;
  • 表3:质量提升证据链:展示Spec实施前后,线上P0 Bug数量(下降62%)、客户投诉率(下降41%)、新成员上手速度(从2周缩短至3天)。

数据比道理管用。当老板看到“每月多赚9.6万”,Spec就不再是“额外负担”,而是“必选项”。记住,推动变革,永远用对方的语言说话。

5. Spec之外:构建可持续的AI协作生态——从单点工具到团队能力

Spec驱动不是终点,而是起点。当团队习惯用Spec约束AI,下一步是让整个协作生态围绕契约进化。这需要超越工具层面的思考。

5.1 Spec即API:让产品、前端、测试共享同一份“真相”

我们把Spec升级为机器可读的YAML格式,用OpenAPI Generator自动生成三样东西:

  • 后端代码骨架:基于Spec生成Controller、DTO、Validation Rule;
  • 前端Mock Server:用MSW拦截请求,返回Spec定义的边界响应;
  • 测试用例集:Pytest/Playwright自动读取边界表,生成全量测试脚本。

这意味着,产品在Figma上改一个按钮文案,Spec更新后,前端Mock、后端接口、测试用例全部自动同步。AI不再是孤岛,而是生态中的一个执行节点。去年我们上线一个会员等级系统,产品周五下午更新Spec,周一早上,后端代码、前端页面、自动化测试全部ready——全程无人工干预。Spec成了团队唯一的“真相源”。

5.2 Spec知识库:沉淀团队的“隐性契约智慧”

每个项目都会产生大量未写进文档的隐性规则:比如“所有外部API调用必须带X-Request-ID头”、“用户头像URL必须走CDN且带签名”。这些规则散落在会议纪要、Slack聊天记录里,新人永远找不到。我们建了一个内部Wiki,强制要求:每份Spec提交时,必须关联一个“契约标签”(如#rate-limiting、#gdpr-compliance),并填写一句“为什么这条约束存在”(例:#rate-limiting:因支付网关QPS限制为100,需在API网关层做熔断)。半年下来,知识库积累了327条带上下文的契约,新人入职第一周就能查到所有“潜规则”。AI在生成代码时,也能从这个知识库中检索相关约束,实现跨项目智能继承。

5.3 Spec成熟度模型:衡量团队AI协作能力的标尺

我们设计了一个五级模型,定期评估团队:

  • L1:无Spec,AI自由发挥;
  • L2:有Spec,但未验证,靠人工检查;
  • L3:Spec+自动化验证,一次通过率≥70%;
  • L4:Spec即API,驱动全链路生成;
  • L5:Spec知识库驱动AI,具备跨项目契约继承能力。

每个季度,团队对照模型自查,目标不是“达到L5”,而是看清当前卡点。去年我们卡在L3到L4的跃迁,发现瓶颈不在技术,而在产品团队不愿提前定义边界。于是我们调整流程:产品PRD必须包含“可验证的Spec章节”,否则不予排期。用流程倒逼认知升级。

最后分享一个真实体会:Spec驱动开发,本质上是在训练人类自己。当你被迫把模糊的想法拆解成可验证的契约,你的工程直觉、边界意识、系统思维都在进化。AI只是镜子,照见我们自身思维的混沌。所以,别再抱怨AI跑偏——拿起笔,写一份Spec,那才是你真正掌控代码的第一行。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/7 13:24:39

Python爬虫实战:自动下载高清壁纸的脚本实现

写这个自动下载壁纸的脚本,最初纯属被逼出来的。我平时喜欢囤高清壁纸,可壁纸站翻半天找到一张对味的,点下载之前先给你弹两个广告,好不容易存下来,发现是带水印的缩略图,心态直接炸裂。后来我决定自己写个…

作者头像 李华
网站建设 2026/10/7 13:23:42

dsh-waker实战:构建AI员工自动唤醒与调度中枢的实践指南

说出来你可能不信,我最早把AI接进实际工作流的时候,最头疼的不是模型不够聪明,而是它太“被动”了。你问一句它答一句,像个需要随叫随到的工具,而不是一个能自己干活的员工。后来我在dsh生态里折腾AI Agent的调度&…

作者头像 李华
网站建设 2026/10/7 13:22:51

AI Agent协作开发指南:3个Agent如何将4人2个月的项目压缩到3周

三个月前接手一个企业项目时,没人想到能用3周交付完。原本的方案是4人团队干2个月:1个项目经理、1个后端、1个前端、1个测试,外加企业内部协调,标准排期就是8周。我最终只用了约15个工作日完成,靠的是3个 AI Agent 全职…

作者头像 李华
网站建设 2026/10/7 13:20:37

AI行业日报选题与信息筛选:Claude Code与Codex CLI实操避坑指南

1. 一份日报背后的信息筛选逻辑 做AI行业资讯日报这件事,我从2024年就开始断断续续地折腾,中间换过三种形态:最早是纯手工整理,后来半自动化抓取加人工筛选,现在基本稳定在"定向信源人工判断结构化输出"的模…

作者头像 李华