游乐游手机版
首页/AI教程/文章详情

AI编程时代如何用Prototype直接看效果避免Spec错误

时间:2026-08-05 15:39
AI编程时代,应优先制作原型而非详尽spec,用可运行代码可视化需求,减少信息损耗。原型分UI和Logic分支,借助AI快速验证设计决策,通过后迁入生产代码,提升开发效率与准确性。

AI 编程时代 Prototype 方法论信息图封面AI 编程时代 Prototype 方法论信息图封面

在AI编程领域,有一个令Matt Pocock深感困扰的普遍现象。许多开发者在拿到AI工具后的第一反应是,必须先撰写一份详尽无遗的需求文档。他们投入大量精力打磨一份事无巨细的规格说明(Spec),期望AI能照单全收、一次到位。然而,结果往往是AI产生了一堆古怪的代码,与预期大相径庭。

那么,问题究竟出在哪里?

1. 一个真实的需求:为订单追踪页添加搜索功能

假设你接到一个需求:为一个基于React的订单状态追踪页面增加搜索功能。该页面包含5种订单状态、筛选器、分页、批量操作,以及状态之间复杂的转换逻辑。

如果采用Spec驱动的方式,开发流程大致如下:

回合1。撰写一份Spec:“订单详情页,顶部显示订单号和状态标签,中间是物流时间线,底部是商品清单。状态标签用不同颜色区分。” AI生成了一版代码。结果时间线是竖向的,所有状态标签都是蓝色。

回合2。修改Spec:“时间线采用横向步骤条,已完成状态为绿色、进行中为蓝色、取消为灰色。时间线下方显示预计送达时间。” AI生成第二版。这次步骤条太宽,超出了手机屏幕,预计送达时间也没有考虑时区。

回合3。补充Spec:“步骤条在小屏幕上自动换行,预计送达时间标注时区。” AI生成第三版。布局对了,但步骤条只有三个节点,实际有六种状态未被覆盖,商品清单的图片加载失败时也没有占位图。

回合4。再次补充Spec……此时已经花费了40分钟,写了800字的Spec,产出了4版无法使用的代码。

每一轮循环都是:纯文字描述 → 凭空想象 → 获取代码 → 发现问题 → 重新描述。这种损耗不断累积,越来越大。

Matt Pocock的Skills仓库中,prototype skill的定义只有一句话:“A prototype is throwaway code that answers a question”。它解决的正是上述问题——在你无法用语言精确描述需求时,先用可运行的代码将问题可视化。用眼睛来评审,而不是用文字来翻译。

Spec 驱动模式的信息损耗循环示意图下图展示了这个信息损耗的循环过程。

2. 为什么AI使“先做原型”变得更具性价比

在传统开发中,制作一个原型(Prototype)的成本并不低——可能需要半天搭建环境,再花半天制作交互。因此,大多数情况下,我们选择先写Spec,毕竟“文字总比代码便宜”。

但AI的出现改变了这个等式。根据Matt Pocock的prototype skill设计,一个原型只需满足三个条件:

  • 一条命令即可运行(pnpm python bun
  • 默认无持久化(状态保存在内存中)
  • 跳过打磨环节(不包含测试、错误处理、抽象层)

在AI的辅助下,这些约束意味着几分钟内就能生成一个可运行的原型。当原型的成本趋近于零时,情况就发生了变化——你讨论的保真度应该相应提高。

这就是Matt Pocock倾向于在更高保真度上进行更多讨论的原因。并非Spec没有用,而是AI让原型变得足够廉价。廉价到值得在“它应该长什么样”或“这个状态机是否正确”这类问题上,直接查看运行效果,而非阅读文字描述。

3. 保真度:哪些问题适合写Spec,哪些问题适合做原型

保真度本质上指的是讨论的精确程度。不同的问题需要不同保真度的讨论方式。

有些问题简单讨论几句即可——例如文件如何组织、接口叫什么名字、使用什么设计模式。这些是低保真度问题,写几行文字就能对齐,Spec足够应对。

有些问题则必须看到运行效果才能判断——例如交互细节、布局节奏、状态机边界条件。这些是高保真度问题,文字描述的精度不够,每多一轮翻译就多一层损耗。

Matt Pocock的wayfinder skill为此提供了一个明确的切换信号:

换句话说——如果你们还在讨论“要不要加这个功能”或“接口怎么设计”,继续深入讨论即可。一旦讨论焦点变成“它应该长什么样”或“这个状态转换是否正确”,文字就不够了,必须使用可运行代码。

问题类型

保真度需求

推荐方式

信号

架构选择、模块划分

grilling / to-spec

能用一句话说清

接口设计、数据结构

中低

grilling + spec

能画草图对齐

布局、交互节奏

prototype(UI)

“我想看看它长什么样”

状态机、业务逻辑边界

prototype(Logic)

“我不确定这个 edge case 对不对”

整体技术方案

grilling → to-spec

多轮讨论能收敛

保真度光谱:从低保真到高保真的讨论方式对比保真度光谱:从低保真到高保真的讨论方式对比

4. 两条链路:Spec驱动 vs 原型驱动

Matt Pocock的Skills仓库定义了两条清晰的开发链路。

Spec驱动链路

grill-with-docs → to-spec → to-tickets → implement → code-review

信息载体是文字。每一轮“写Spec → AI生成 → 发现问题 → 修改Spec”都是一次翻译。你脑海中的画面需要翻译成文字,AI再将文字翻译成代码,你最后把代码翻译回画面。每一次转换都有损耗。

原型驱动链路

grill-with-docs → prototype → 反馈循环 → handoff → implement

信息载体是可运行代码。你不再需要描述“搜索结果应该按时间倒序排列”,而是直接看到页面上搜索结果的排序,然后说“B变体的排序方式正确,但A变体的筛选器交互不行”。

Matt Pocock在prototype的to-spec模板中专门留了一个接口:

意思是——如果原型产出的代码片段比文字更精确地表达了某个设计决定(例如一个状态机、一个reducer的签名、一个类型定义),可以直接内联到Spec中,并注明来自prototype。

可运行代码是最高精度的需求文档。这并非一句口号,而是prototype skill在架构层面的设计意图。

5. Prototype的两条分支

Prototype并非笼统的“写个demo”。Matt Pocock将其分为两条结构完全不同的分支,选错了会浪费整个原型。

UI分支:为设计问题打分

触发信号:“What should this page look like?”、“I want to see a few options”。

UI原型的核心思路:在同一路由上生成结构不同的变体,使用?variant= URL参数进行切换。

三个关键约束:

  1. 变体必须结构不同。不仅仅是换颜色、换文案——而是不同布局、不同信息层级、不同主要操作。如果两个变体只是卡片背景色从蓝变绿,那不是prototype,而是微调。
  2. 优先嵌入已有页面。将变体挂载到已有的路由上,保留现有的数据获取、参数和鉴权,只更换渲染部分。这样变体是在真实环境中被评估的——有真实的header、真实的sidebar、真实的数据密度。一个空白路由上的所有变体都会“看起来还行”,因为没有上下文。
  3. 新路由兜底。只有当原型确实没有已存在的页面可以挂载时才使用。路径需包含prototype字样,例如/prototype/order-search
Matt Pocock的实操demo:tldraw搜索原型

Matt在演示中为一个基于tldraw的图表应用添加搜索功能。数据模型很复杂——包含图表及其历史快照。他不确定搜索栏应该长什么样、应该如何交互。

于是他运行了prototype。AI生成了三个结构不同的变体:

  • A版:搜索框在上方,结果按图表名称分组显示
  • B版:左侧有分组筛选器,可以向下钻取
  • C版:所有结果平铺展示,没有筛选器

Matt逐个评审——不是写一份评估文档,而是看着运行效果直接说出感受:

这个环节是整个方法论的精华。他不是在“选最好的那个”,而是在收集设计决策。每个变体都编码了一些设计选择,他的反馈就是对这些选择进行取舍。

原型会话消耗了约10万token后,Matt进行了一次compact(上下文压缩),然后口述反馈:

AI生成D版本,将两者融合。Matt强调了一个关键细节:原型直接集成在live page上,而不是独立路由。因为这样呈现的是代码实际运行的方式——更诚实的呈现。

UI原型还包含一个浮动底部切换栏:左箭头/右箭头 + 当前变体标签,键盘 也可切换。在生产构建中隐藏(通过process.env.NODE_ENV !== 'production'控制)。

文件命名示例:在/settings路由上做搜索UI原型,变体文件可能是:

// 在已有的 settings 页面路由上 const variant = searchParams.get('variant') ?? 'A'; return (<> {variant === 'A' && } {variant === 'B' && } {variant === 'C' && } );

Logic分支:为状态机测试边界

触发信号:“Does this state machine handle the edge case?”、“I want to feel out what the API should look like”。

Logic原型的核心思路:纯逻辑终端小程序 + TUI shell。

关键约束:逻辑模块必须可移植、纯净。源码原文:“Keep it pu re: no I/O, no terminal code, no console.log for control flow”。

一个Logic原型的典型结构:

# order_state.py — 可移植纯模块(可以搬进真实代码库) def transition(state: OrderState, event: OrderEvent) -> OrderState: """纯 reducer:(state, event) => state 没有 I/O,没有 terminal code""" if state == "pending" and event == "confirm": return "confirmed" if state == "confirmed" and event == "ship": return "shipped" if state == "shipped" and event == "deliver": return "delivered" # edge case: 确认后还能取消吗? if state == "confirmed" and event == "cancel": return "cancelled" raise ValueError(f"非法转换: {state} + {event}") # tui_shell.py — throwaway TUI 包装 import order_state # 每帧:清屏 → 渲染当前状态 → 等待键盘输入 → dispatch → 重渲染

Logic原型的产出有两层:TUI shell是throwaway,但那个纯逻辑模块可以直接搬进生产代码。这就是prototype的“答案”——不是代码本身,而是代码验证过的那个设计决定。

分支选错的代价

Matt Pocock在SKILL.md里写得很直接:“Getting this wrong wastes the whole prototype”。

把UI问题走logic分支——你写了一堆reducer和状态机,但还是不知道页面应该长什么样。把logic问题走UI分支——你搞了三个漂亮的变体,但状态机的边界条件根本没验证。判断标准很简单:问题的关键词是“look”还是“beha ve”。

UI 原型与 Logic 原型的分支对比UI原型与Logic原型的分支对比

6. Prototype的通用规则

不管走哪条分支,六条通用规则都适用:

  1. 从第一天起就标记为可丢弃,明确标注。原型代码放在实际使用位置附近,但命名要让路过的读者一眼看出是prototype。不要让下一个读者误以为这是生产代码。
  2. 一条命令就能运行。用户必须能不假思索地启动它。如果是pnpm项目就pnpm prototype,如果是Python就python prototype.py
  3. 默认无持久化。状态保存在内存中。持久化是原型要检查的内容,不是它应该依赖的。如果问题本身涉及数据库,使用一个名字清晰的scratch DB或本地文件,标上“PROTOTYPE — wipe me”。
  4. 跳过打磨环节。不包含测试、错误处理(除了让原型能运行的最小限度)、抽象层。目的是快速学到东西,不是写漂亮代码。
  5. 展示状态。每次action或variant switch后,打印/渲染完整的相关状态。让用户能直接看到“什么变了”。
  6. 完成后捕获答案。验证过的决定迁入真实代码,原型本身作为primary source提交到throwaway branch,而不是main分支。主分支只保留验证过的决定。

7. 原型如何进出主链路

原型不是写完就结束了。Matt Pocock设计了一个清晰的进出机制。

出:handoff出 → 新会话运行prototype

当grilling进行到某个问题需要“看到运行效果”才能继续时,使用/handoff将当前对话压缩成一份handoff document,保存到OS临时目录。然后开一个新会话,加载handoff文档,运行/prototype

Handoff文档不重复其他产物(specs、plans、ADRs、issues、commits),只引用它们。它还包含一个suggested skills部分,告诉下一个agent应该调用哪些skill。

迭代:compact + 口述反馈

原型运行起来之后,不是一次定型。Matt的实际操作是:

  • 生成3个变体,使用?variant=切换
  • 口述反馈——“A的搜索框位置正确,但分组方式不对。B的筛选器不错。C的布局最干净”
  • 做一次compact(上下文压缩),将长会话压缩到可继续的长度
  • 继续口述——“我喜欢A的搜索框,也喜欢C的布局”
  • AI生成融合版D,将多个变体的优点合并
  • 再改两轮——“把预计送达时间移到步骤条上方”、“商品图片加个骨架屏加载态”,每轮15秒出结果

关键细节:原型直接集成在live page上,不是独立路由。Matt强调这是“更诚实的呈现”——因为原型展示的是代码实际运行的方式,而不是一个隔离的demo环境。

进:prototype完成 → handoff回

原型迭代满意后,再次/handoff,将原型的结论(哪个变体被选中、哪些设计决策被验证)压缩成文档,回到原始会话。原始会话引用handoff doc,继续推进。

交给AFK agent实施

原型完成后,下一步不是自己重构。交给AFK agent(Away From Keyboard,后台异步agent):

  • 接入真实功能
  • 删除原型临时代码
  • 确保符合原始设计意图

因为discuss → prototype的过程已经产出了一份富含设计决策的可运行资产,实施agent可以直接参考——不需要从文字spec反推设计。

原型做完不必然直接implement

这是很多人容易误解的地方。原型验证完设计决定之后,有两条路。

  • 直接implement——如果问题简单、原型答案清晰、且改动范围小
  • 回到to-spec / to-tickets——如果原型揭示的问题比预期复杂,需要先将原型的结论沉淀成spec,再拆票实施

Matt Pocock在to-spec和to-tickets的模板里都专门留了引用prototype代码片段的接口。原型的答案可以feed into spec——“if a prototype produced a snippet that encodes a decision more precisely than prose can, inline it”。

原型是提升讨论保真度的手段,不是交付物。它的价值在于“回答了一个问题”,而不在于代码本身。

8. 三处反例:别这么干

反例一:将原型直接提升为生产代码

这是最常见的错误。原型是在无测试、最小错误处理的约束下编写的——源码明确说明“The variant code was written under prototype constraints (no tests, minimal error handling). Rewrite it properly when you fold it in.” 将原型代码直接搬进主分支,等于把一个“快速验证工具”当成“生产级实现”。

反例二:变体只差颜色不差结构

源码原文:“Variants that differ only in colour or copy. That's a tweak, not a prototype. Real variants disagree about structure.” 三个变体,A是蓝色卡片、B是绿色卡片、C是红色卡片——这不是prototype,这是壁纸。真正的变体应该在布局、信息层级、主要操作上有本质区别。

反例三:UI问题走Logic分支(或反之)

你不知道搜索结果页应该长什么样,于是写了一个reducer来处理搜索状态——这答非所问。或者,你不确定订单状态机的边界条件是否正确,于是做了三个漂亮的UI变体——状态机的edge case根本没验证。

9. 判断准则:什么时候该干什么

信号

动作

讨论还在“要不要做”、“接口怎么设计”

停在grilling

讨论变成“它应该长什么样”、“我想看看几个选项”

切prototype(UI)

讨论变成“这个状态机对不对”、“edge case怎么处理”

切prototype(Logic)

原型验证完,结论清晰,改动小

直接implement

原型验证完,揭示的问题比预期复杂

回到to-spec / to-tickets

讨论到不了高保真度但硬要写spec

停下来,先grilling搞清楚问题本身

一句话总结:Prototype是“用运行代码代替文字描述来讨论设计”的手段。什么时候你觉得“光说不清楚了”,就是该做原型的时候。

完整的决策流程图:从 grilling 到 prototype 到 implement完整的决策流程图:从grilling到prototype到implement

来源:https://cloud.tencent.com.cn/developer/article/2720905
上一篇AI编程的边界 哪些任务适合AI 哪些必须人工把关 下一篇用WorkBuddy打造高中数学试卷高精度校对流水线
本站内容用于信息整理与展示,如有侵权或内容问题请及时联系处理。

相关推荐

补充同频道和同主题内容,方便继续浏览更多相关内容。

同类最新

继续查看同栏目最近更新的文章。

更多
WorkBuddy使用一个月避坑指南:5个常见问题及解决方案
AI教程 · 2026-08-05

WorkBuddy使用一个月避坑指南:5个常见问题及解决方案

使用WorkBuddy一个月,踩过指令模糊、未指定输出格式、反复打断任务、积分过期、未验证结果五个坑。对应解法:明确文件路径、动作、维度、格式和文件名;指定输出格式;耐心等待;优先使用快过期积分;抽查验证汇总逻辑。

图片生成任务到用户隔离:AIGC后端与PostgreSQL建模实践
AI教程 · 2026-08-05

图片生成任务到用户隔离:AIGC后端与PostgreSQL建模实践

基于AIGCCreativeStudio实践,后端采用Express+TypeScript与PostgreSQL17,通过users、generation_tasks、images三表模型实现任务状态机、图片本地存储及受认证访问,确保用户隔离与资源安全。

动态代码拖累SEO?用Gofair纯静态页面剔除冗余代码
AI教程 · 2026-08-05

动态代码拖累SEO?用Gofair纯静态页面剔除冗余代码

静态页面加载速度快,搜索引擎爬取效率高,优于动态建站。某孕产妇用品企业改用Gofair静态建站,五天多关键词冲至谷歌首页。SEO效果需通过关键词反查验证,流量数据易被干扰。未来静态页面策略将更主流。

WorkBuddy AI工作台实操教程 零基础搞定周报与数据分析
AI教程 · 2026-08-05

WorkBuddy AI工作台实操教程 零基础搞定周报与数据分析

使用WorkBuddy时需下达清晰指令,包括文件路径、输出格式和完整需求。典型场景如周报生成、Excel数据清洗与可视化,需注意指定去重列和输出格式,避免打断大文件处理。定时任务可自动化抓取新闻,轻量模型和Ask模式可节省积分。

CC压缩机制之toolResultBudget源码实现原理技术深度解读
AI教程 · 2026-08-05

CC压缩机制之toolResultBudget源码实现原理技术深度解读

toolResultBudget机制在每次模型请求前自动执行,检查单个API-levelusermessage中tool_result总量是否超过200K字符,若超则将最大的工具结果落盘并替换为预览,以降低上下文噪音。该机制位于压缩流水线最前端,在microcompact之前执行,确保后续压缩更高效。