没有系统设计的 Vibe Coding 是一个陷阱
本文信息来源:focusedchaos
“量两次,再剪一次”依然是很好的建议,但 AI 工具让打破这条规则变得异常容易。
降低创作门槛一直都是一件利大于弊的事。WordPress 让任何人都能成为发布者。YouTube 让任何人都能成为播客。Shopify 让任何人都能成为电子商务运营者。AI 辅助编码正在对产品构建做同样的事情。
让千花齐放吧。我完全支持!
问题在于:AI 非常擅长帮助你构建某个东西 ,但并不擅长帮助你把某个东西构建好 。
这种差异至关重要,尤其是对于那些试图交付真正产品(而不是原型或演示)的创始人、产品经理和产品团队而言。
AI 优化的是“能用”,而不是“可演进”
当你让 AI 构建一个功能时,它只会为一件事进行优化:让它立刻能运行。
这通常意味着:
- 用硬编码的值,而不是将它们抽象出来
- 在当下采取降低认知负担的捷径
- 忽视未来的变化,因为未来的变化并未被明确提出或预期
例如,它会乐于将配置值直接硬编码到逻辑中。
最近,我使用 Lovable 构建了一个 Applicant Tracking System(ATS)(我可是个 超级粉丝 ),用来替换我们在 Highline Beta 使用的 ATS。为什么?我觉得这是一个有趣的实验,而且我们并不需要特别复杂的功能。
当我第一次创建 ATS 时,我给了 Lovable 一份职位发布字段列表,但并没有明确说明哪些字段应该由管理员进行配置。Lovable 按照这些字段构建了系统,包括雇佣类型(例如:全职、兼职等)、工作地点类型(例如:线下、远程、混合)等,但把选项全部写死了。当我准备发布职位、看到这些预设好的字段选项时,我立刻意识到这个系统的灵活性不够。我并没有把系统设计好,而 AI 替我把空白补上了。
你 可以 提示它不要这样做。
你 可以 告诉它引入全局设置、环境变量或配置表。
但前提是你本来就知道这些东西 不应该 被硬编码。这种认知并不是来自 vibe coding,而是来自经验(我有这些经验,只是当时没有用上!)

同样的模式也出现在测试上。
开箱即用的情况下,AI 很少会构建测试用例、测试工具(test harness),或任何有意义的测试策略。它会生成(大多)在理想路径(happy path)下可运行的功能性代码,然后悄然继续往下走。
对于 ATS,我希望用户上传一份 PDF 简历,由系统解析数据,从而尽量减少用户需要手动输入的内容。我提示 Lovable 将 PDF 解析器构建到职位申请表中,它确实做到了!我上传了几份简历进行测试,很快就意识到我根本不知道它实际在做什么。有些情况下几乎解析不出什么内容,而在另一些情况下似乎又能获取大量数据。我意识到,我需要一种有意识地测试 PDF 解析的方法,而不是偶然地发现问题。
因此我在 ATS 中构建了一个 PDF Extraction 测验工具。这让测试这个功能变得简单得多,而不必不断地去投递工作。

再说一次,你可以提示 AI 去构建测试工具,它很可能会照做(或者至少尝试)。但除非你明确提出要求,否则它不会主动为可测试性进行设计。如果你没有太多产品构建经验,你可能不会去要求,甚至都意识不到应该这么做,于是在对系统实际运行情况缺乏清晰认知的情况下,一层又一层地往上叠加功能。
结果:功能可用,但杂乱无章的产品
最终的结果是可以预见的——大量产品涌现出来,它们:
- 功能可用 ✅
- 构建速度快 ✅
- 表面上容易调整 ⚠️
- 测试起来很痛苦 ❌
- 修改时非常脆弱 ❌
- 演进成本不断攀升 ❌
像 Lovable 这样的工具让你通过提示就能轻松完成改动。迭代过程感觉近乎魔法。你可以在一个下午里用 vibe coding 的方式完成几十次调整。
但以下两者之间存在真正的差别:
- 通过提示进行无休止的迭代;以及,
- 构建具有连贯结构和明确意图的东西。
Vibe Coding 优化的是速度,而不是可承重的结构。
这对于你出于兴趣而做的小型 DIY 项目来说没问题。但当你在为一座新房子打地基时,这就很危险了。
Vibe Coding 仍然需要系统性思维
Vibe coding 并不会消除系统设计,它只是把系统设计推到了幕后。
如果你一开始不去思考结构,你在技术上仍然是在实现某种结构,只不过是无意中实现的,而这非常危险。
系统设计关注的是产品如何随着时间推移保持整体的稳定与一致。
它会提出这样的问题:
- 关键设置应该放在哪里?
- 哪些内容应该是可配置的,哪些应该是硬编码的?
- 产品的不同部分之间是如何相互依赖的?
- 当六个月后某些东西发生变化时,会发生什么?
- 数据模型中隐含了哪些假设?
这些决策不会出现在截图中。但它们决定了你的产品是灵活的,还是脆弱的。
AI 会很乐意在不回答这些问题的情况下帮你构建功能。它会让东西跑起来。它会按照你告诉它的方式把各个点连接起来。但它不会停下来提醒你,“这可能应该是一个全局设置,” 或者 “这个 schema 以后迁移起来会很痛苦。”
这种判断力源自对系统的理解。
要想成功进行 vibe coding,你需要对正在构建的系统有一个清晰的心智模型。 你不需要一份庞大的架构文档。你需要的是一张粗略的地图,知道哪些是核心,哪些是共享的,哪些很可能会变化,以及哪些真的不该变化。
系统设计是让你在高速前进时不至于把手指切掉的关键。
在用 Vibe Coding 开发一个功能之前需要问的 5 个系统问题
这是大多数人都会跳过的实操部分。
在你让 AI 去构建 任何东西 之前,先停下来,用自然语言回答这五个问题。不要写代码。不要写提示词。
- 未来可能会发生哪些变化? 如果它可能会变化,那么就不应该被硬编码。
- 这应该只存在一处,还是无处不在? 如果同一个值、规则或概念在多个地方出现,你就需要在系统层面进行设计来处理它。只构建一次,并在所有地方复用。像 Lovable 这样的工具如果你不明确说明,会乐于一次又一次地重建同样的东西,甚至每次实现方式都不同。
- 什么才是事实源(source of truth)? 它是来自配置、数据库、用户输入,还是隐藏在逻辑中的假设?
- 如果我修改它,会破坏什么? 如果你无法回答这个问题,说明系统已经很脆弱了。
- 我该如何测试它? 如果测试过程感觉别扭或需要大量手工操作,那问题很可能出在系统设计上。
你不需要完美的答案。你只需要提出正确的问题。
这五项检查能将氛围式编码从随机行动转变为有意图的进展。
产品需求文档(PRD)真正发挥作用的地方
在这个阶段,有些人会问: 我是否应该写一份 PRD?
诚实的回答是:我很纠结。
一方面, 我很喜欢把事情写下来 ,保持深思熟虑和明确表达。尽管我坚信 MVP 的重要性 ,但我仍然习惯于思考边界情况、错误处理以及“完整性”。我已经构建软件 30 年了,知道很多地方容易出错。我也确实犯过很多错误!因此,尽量全面并提前考虑各种问题,听起来是合乎逻辑的。
另一方面,AI 构建工具和代码助手简直像魔法一样。只需向 Lovable 这样的工具输入一个相对简单的提示,30 秒内就能得到一个完整的应用程序,这种体验令人极其满足。快速构建的冲动,往往会压过谨慎构建的冲动。
一如既往,你需要为具体工作选择合适的工具。如果你正在构建一个非常复杂、任务关键、并且涉及人们资金的应用程序,就应该考虑使用一份规范、稳健的 PRD。如果你构建的是一个更简单的应用,不至于让整栋房子倒塌,那就可以少做一些规划。
我开始尝试使用系统草图 。
一页式的强制约束工具,用来在 AI 替你用代码回答之前,先回答上述五个问题。其中一个关键点是理解并明确你在构建过程中所做的假设、为何要这样构建,以及这些选择所带来的影响。如果你不向 AI 提供这些上下文,它就会自行猜测。关键在于在系统决策固化之前,提供足够的结构,把这些决策外化出来。
有趣的是,如果你是在复制一个现有产品,你可以直接把它当作你的 PRD。它的结构本身就编码了关于配置、数据和依赖关系的决策。这也是为什么复制一个设计良好的产品,比从零开始要容易得多。我以我们现有的 Applicant Tracking System 工具作为新工具的基础,在提示 Lovable 构建功能之前,这帮助我先理清了系统设计和整体结构。
记住:你始终是在将 vibe coding 融入到一个系统中,无论这个系统是否经过你的刻意设计。
对于经验不足的产品人来说,vibe coding 的真正风险并不是糟糕的代码,而是“意外架构”。那句老话“measure twice, cut once”依然是很好的忠告。
边界情况和错误处理才是产品真正成熟的地方
Vibe coding 在两个方面悄然走了捷径:边界情况和错误处理。
处理边缘情况和错误是一项不那么光鲜、又繁琐的工作。你希望边缘情况和错误不要经常发生,但正是对它们的妥善处理,才能把一个原型变成用户真正可以依赖的产品。
当你进行 vibe coding 时,几乎总是在构建“理想路径”:输入是干净的、假设成立、用户行为也完全符合你的预期。
AI 非常擅长这一点。
但它对以下方面要冷淡得多:
- 当数据缺失时会发生什么
- 当输入格式不正确时会发生什么
- 当系统之间产生分歧时会发生什么
- 当用户做出意料之外的操作时会发生什么
- 当模型不确定时会发生什么
像 Lovable 这样的工具通常会添加基础的错误提示或防护机制。这很有帮助。但这里的“基础”其实涵盖了很多东西。达到生产级别的产品会花费大量时间来处理那些混乱的边缘情况:部分失败、状态不明确、重试、回退、降级模式、结果不清晰等等。
这些并不是事后才考虑的事情,而是核心的产品决策。Vibe coding 会迅速削弱它们的重要性,因为一切看起来都在正常运行……直到不再如此。
我给你举两个例子:一个简单的,一个更复杂的。
简单示例:字段格式化
以下是 John Smith 申请 Senior Designer 职位的示例:

PDF 解析器是能用的,但在他的简历里,LinkedIn URL 前面没有 “https://”,于是系统就抛出了一个错误。这真的很烦人。我无法保证每个人的简历里都会有一个“格式正确”的 LinkedIn 个人资料 URL。所以我要么让系统接受不带 https:// 的 URL 格式,要么让系统自动去格式化这个 URL(这又可能引发其他问题)。这只是一个相对简单的产品里,一个很简单的错误 / 边界情况问题。要构建并上线一个好的产品,你必须把所有东西都测试到位,并且把所有潜在的问题都想清楚,包括格式、条件判断等等。
复杂示例:AI 功能的幕后
我决定在 ATS 中添加一个 AI 简历评分 功能。看起来很有用,而且我们当前的 ATS 并没有这个功能。我与 Lovable 合作来构建它,并很快开始测试简历。我没有测试优秀的简历,而是测试了糟糕的简历,因为 AI 评分的一个重要原因是用于筛选候选人。测试优秀简历并得到高分是“理想路径”——感觉很好,但并不足以全面验证 AI 简历评分是否真正发挥了作用。

我用两个岗位(Senior Product Designer 和 Senior Software Developer)开始投递,但使用的是非常薄弱的简历。系统会输出评分,而我则需要去揣摩 AI 到底在做什么。有一次,它竟然给一份几乎空白(夹杂着垃圾输入)的简历打了比一份更好的简历还高的分数。为什么?后来发现,AI 在“地点”这一维度上权重给得过高。那份垃圾简历位于多伦多(与岗位所在地相同),而那份更好但仍然不怎么样的简历则在温哥华。为了解这一点,我们和 Lovable 进行了大量来回沟通,不断微调各项权重。
边缘情况和错误往往会催生新功能
使用糟糕数据(而不是优质数据)测试 AI 简历评分,最终新增了两个功能:AI Scoring Explanation 和 Test AI Scoring。
当你思考边缘情况和错误处理时(“可能会出什么问题?” 对比 “可能会进展顺利的地方?”),这有助于你意识到软件用户真正需要什么。AI Resume Scoring 工具在生成分数时没有任何解释。我知道用户不会信任它,因此我构建了评分背后的推理过程(最初很简要,随后逐步变得更加详细)。
以下是 AI Scoring Explanations 的部分截图:

Test AI Scoring 功能是一项管理员能力,允许我持续测试 AI 评分的运行情况。说实话,每当我对 ATS 做出一次有意义的更改时,我可能都应该准备一批简历和职位,用于自动运行测试。目前这还是手动进行的,既非常繁琐,又风险很高。

边缘情况不仅仅是技术问题,而是设计问题:
- 当系统不够自信时,应该发生什么?
- 可以接受多大的不确定性?
- 谁应该看到错误,以及以什么方式看到?
- 系统应该在什么时候停止,什么时候继续运行?
如果你不明确地做出这些决策,AI 就会替你隐式地做出决定,而你很可能不会喜欢这些默认选择。
渐进式构建正是糟糕架构暴露的地方
大多数真实的产品都不是一蹴而就的,而是逐步构建出来的。
你从一个简单的东西开始:一个基础版本的功能,一个以最直接方式解决核心问题的 MVP。
然后在此基础上不断添加:更多能力、选项、逻辑、用户、规则等等。这很正常,这正是产品真实的演进方式。
但通过氛围式编码进行渐进式构建有一个被人们低估的锋利边缘。如果你没有彻底思考底层的系统设计,每增加一层,都会提升某些东西出问题的概率,而且往往不是以显而易见的方式。
功能的原始版本可能仍然“能用”,但是:
- 新的逻辑可能无法一致地应用到旧的流程中
- 早期的假设可能不再成立
- 你之前处理过的边界情况可能会以新的形式再次出现
- 曾经通过的测试可能已经不再具有任何意义
当你向 AI 提示 “Add X”、“Support Y” 或 “Handle this new case” 时,新增能力往往感觉易如反掌 。
但如果没有清晰的系统模型,这些新增内容可能会绕过现有规则、与早期逻辑发生冲突、引入你无法立即察觉的回归问题,或制造出你从未为之设计的错误状态。
示例:自定义问题对 AI 简历评分的影响
在搭建好基础 ATS 之后,我想新增一个应用程序功能:自定义问题。这些问题可以针对每个职位发布单独创建,用来向求职者询问特定事项。Lovable 非常轻松地构建了自定义问题功能,尽管我知道其中有几个问题需要考虑,包括: 如果在求职者已经作答之后,自定义问题被修改或删除,会发生什么?(注:向后数据兼容性始终是一个巨大的问题)。我为此制定了合适的规则,并实现了该功能。

我忘了要做的一件事是决定这些问题会如何影响 AI 简历评分工具。如果你花时间在职位发布中添加自定义问题,那它们一定很重要,你也希望这些答案能够影响评分。但有些问题可能是是/否题、多项选择题或自由填写题。有些问题是必填的,而有些则不是。 某些类型的问题是否会对评分产生更大的影响?有些问题是否实际上是决定性的“硬性条件”?例如,如果有人回答“否”,表示不能流利地讲英语,这个候选人是否应该被自动淘汰?
哎呀。
有时候一些小功能或迭代会产生巨大的影响 。你很容易一头扎进各种疯狂的兔子洞,把一切过度复杂化。AI 编程工具会很乐意这么做,因为这是你要求它们的(而且这也符合它们基于额度计费的商业模式!)
归根结底,这一切都取决于良好的系统设计:先思考再动手,先规划再进行氛围式编码。你不需要过度规划或想得太多,但在开始之前,确实应该做出一些关键的设计决策。否则,渐进式构建只会变成一团疯狂的乱麻。
学习曲线正在变得更陡,而不是更平坦
这是我认为最有意思的挑战:
- AI 让开始构建变得前所未有地容易。
- 但它并不一定让把东西构建好变得更容易。
事实上,它恰恰相反。
如果每个人都能构建,那么每个人都在做产品决策。如果每个人都在缺乏必要核心技能的情况下做产品决策,我们就会有大量糟糕的产品。
除此之外,在进行 vibe coding 时,你实际上需要一套更广泛的技能组合,因为产品决策就是系统决策,也是代码决策。Vibe coding 要求你更早把事情做对(如果你不想在之后陷入彻底的混乱),并且将责任集中到更少的人身上。
我们比以往任何时候都更需要强大的产品判断力,我甚至认为需要更强、更专业的产品经理。 产品经理应该是构建者 ( 而不仅仅是项目经理 ),而现在你拥有了一套几乎无限的强力工具可以使用。
如何在不(过度)偷工减料的情况下进行 vibe coding

✅ 这样做:
- 在提示之前先设计系统。 即使是一个粗略的系统草图,也比让 AI 自行发明你的架构要好。
- 将任何可能变化的内容外部化。 如果你心里想“以后可能会调整”,那就不要把它硬编码。
- 假设功能会不断演进。MVP 只是起点,而不是终态。设计时要考虑可扩展性。
- 测试不理想路径。 边界情况、错误输入、歧义以及失败模式,才是真正让产品出问题的地方。
- 构建用于理解系统正在做什么的工具。 如果你无法解释为什么某件事情会发生,那么你就无法掌控它。
❌ 不要这样做:
- 不要相信“顺利路径”。“它曾经跑通一次”并不等于“它是可用的”。
- 不要让 AI 决定你的默认值。AI 会自信地填补空白,但不一定是正确的。
- 不要因为快就复制逻辑。 今天的重复,会变成明天的脆弱。
- 不要把迭代当成架构。 更多的提示词并不等于更好的结构。
- 不要忽视向后兼容性。 破坏昨天的数据,是让人讨厌今天功能的最快方式
AI 让更多人能够构建产品,这一点令人惊叹。
但那些能够长期成功的建设者,将是那些把 AI 与基础且关键的产品管理纪律相结合的人。
AI 是一种强力工具。
强力工具不会消除工匠精神,反而会惩罚缺乏它的人。