AI编程时代如何用Prototype直接看效果避免Spec错误
AI编程时代,应优先制作原型而非详尽spec,用可运行代码可视化需求,减少信息损耗。原型分UI和Logic分支,借助AI快速验证设计决策,通过后迁入生产代码,提升开发效率与准确性。
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”。它解决的正是上述问题——在你无法用语言精确描述需求时,先用可运行的代码将问题可视化。用眼睛来评审,而不是用文字来翻译。
下图展示了这个信息损耗的循环过程。
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参数进行切换。
三个关键约束:
- 变体必须结构不同。不仅仅是换颜色、换文案——而是不同布局、不同信息层级、不同主要操作。如果两个变体只是卡片背景色从蓝变绿,那不是prototype,而是微调。
- 优先嵌入已有页面。将变体挂载到已有的路由上,保留现有的数据获取、参数和鉴权,只更换渲染部分。这样变体是在真实环境中被评估的——有真实的header、真实的sidebar、真实的数据密度。一个空白路由上的所有变体都会“看起来还行”,因为没有上下文。
- 新路由兜底。只有当原型确实没有已存在的页面可以挂载时才使用。路径需包含
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原型的分支对比
6. Prototype的通用规则
不管走哪条分支,六条通用规则都适用:
- 从第一天起就标记为可丢弃,明确标注。原型代码放在实际使用位置附近,但命名要让路过的读者一眼看出是prototype。不要让下一个读者误以为这是生产代码。
- 一条命令就能运行。用户必须能不假思索地启动它。如果是
pnpm项目就pnpm prototype,如果是Python就python prototype.py。 - 默认无持久化。状态保存在内存中。持久化是原型要检查的内容,不是它应该依赖的。如果问题本身涉及数据库,使用一个名字清晰的scratch DB或本地文件,标上“PROTOTYPE — wipe me”。
- 跳过打磨环节。不包含测试、错误处理(除了让原型能运行的最小限度)、抽象层。目的是快速学到东西,不是写漂亮代码。
- 展示状态。每次action或variant switch后,打印/渲染完整的相关状态。让用户能直接看到“什么变了”。
- 完成后捕获答案。验证过的决定迁入真实代码,原型本身作为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
游乐网为非赢利性网站,所展示的游戏/软件/文章内容均来自于互联网或第三方用户上传分享,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系youleyoucom@outlook.com。
同类文章
WorkBuddy使用一个月避坑指南:5个常见问题及解决方案
使用WorkBuddy一个月,踩过指令模糊、未指定输出格式、反复打断任务、积分过期、未验证结果五个坑。对应解法:明确文件路径、动作、维度、格式和文件名;指定输出格式;耐心等待;优先使用快过期积分;抽查验证汇总逻辑。
图片生成任务到用户隔离:AIGC后端与PostgreSQL建模实践
基于AIGCCreativeStudio实践,后端采用Express+TypeScript与PostgreSQL17,通过users、generation_tasks、images三表模型实现任务状态机、图片本地存储及受认证访问,确保用户隔离与资源安全。
动态代码拖累SEO?用Gofair纯静态页面剔除冗余代码
静态页面加载速度快,搜索引擎爬取效率高,优于动态建站。某孕产妇用品企业改用Gofair静态建站,五天多关键词冲至谷歌首页。SEO效果需通过关键词反查验证,流量数据易被干扰。未来静态页面策略将更主流。
WorkBuddy AI工作台实操教程 零基础搞定周报与数据分析
使用WorkBuddy时需下达清晰指令,包括文件路径、输出格式和完整需求。典型场景如周报生成、Excel数据清洗与可视化,需注意指定去重列和输出格式,避免打断大文件处理。定时任务可自动化抓取新闻,轻量模型和Ask模式可节省积分。
CC压缩机制之toolResultBudget源码实现原理技术深度解读
toolResultBudget机制在每次模型请求前自动执行,检查单个API-levelusermessage中tool_result总量是否超过200K字符,若超则将最大的工具结果落盘并替换为预览,以降低上下文噪音。该机制位于压缩流水线最前端,在microcompact之前执行,确保后续压缩更高效。
- 热门数据榜
相关攻略
2026-08-05 22:59
2026-08-05 22:59
2026-08-05 22:59
2026-08-05 22:58
2026-08-05 22:58
2026-08-05 22:46
2026-08-05 22:45
2026-08-05 22:45
热门教程
- 游戏攻略
- 安卓教程
- 苹果教程
- 电脑教程

