如何充分利用 Vibe Coding 「YC讲座实录」
- 视频链接:How To Get The Most Out Of Vibe Coding | Startup School
- 官方频道:Y Combinator
- 日期:2025年4月25日
Vibe Coding 核心理念与入门
大家好,我是 Tom,YC 的合伙人。在过去一个月里,我一直在尝试用 Vibe Coding 来做几个个人项目,我发现它不仅效果惊人,而且只要你愿意尝试和学习最佳实践,就能确实地提高这项技能。
在这期视频里,我想分享一些能让你在使用 Vibe Coding 时获得出色结果的方法。这有点像一两年前的提示工程(Prompt Engineering),那时人们每周都会发现新东西,并在社交媒体上分享。其实,最好的 Vibe Coding 技巧,往往就是那些专业软件工程师会使用的技巧。有些人可能会说,“那不就是软件工程吗,还算 Vibe Coding 吗?” 我觉得这不重要,关键在于我们想用这些工具获得最好的结果。
YC 创始人的 Vibe Coding 实用技巧
YC 的春季批次几周前刚刚启动。在我分享我的建议之前,让我们先听听 YC X25 批次的创始人分享他们是如何利用 AI 工具获得最佳效果的。
创始人 A: 如果你卡在某个地方,AI IDE 无法实现或调试,并且陷入了循环,有时直接去 LLM 的官方网站,也就是它的用户界面,把你的代码粘贴进去,问同样的问题,反而能得到结果,而 IDE 不知为何就是做不到。这样就能解决问题了。
创始人 B: 我建议在同一个项目上同时加载 Cursor 和 Windsurf。Cursor 速度快一些,所以可以用来做很多前端相关的、更偏全栈的工作,比如连接前后端。Windsurf 则需要更长的思考时间。以前我写“构建这个 Agent”或“修改这个提示”时,会在等待的时候刷手机。我会粘贴错误信息,然后刷手机。但现在,在等 Windsurf 思考的时候,我可以在 Cursor 上开始更新前端。有时我会同时加载两者,提供相同的上下文,比如在更新前端时,我会说“用那个文件的风格来设计样式”,然后同时按下回车。它们会给我生成两个略有不同的前端版本,我选择我更喜欢的那一个。
创始人 C: 我的建议是,把 AI 看作一种不同的编程语言,把 Vibe Coding 看作一种新的编程范式。你不再是用代码编程,而是用自然语言编程。因此,如果你想获得好的结果,你需要非常详细地提供必要的上下文和信息。
创始人 D: 我通常反向开始 Vibe Coding,也就是先从测试用例入手。我会手动精心设计测试用例,不使用任何 LLM 来编写它们。一旦测试用例完成,我就有了强大的约束规则,LLM 在生成代码时可以遵循这些规则。然后,它们就可以自由地生成想要的代码了。当我看到测试用例全部通过(显示绿色标记)时,工作就完成了。我不需要微观管理我的代码库,只需要大致看看代码的模块化程度就可以了,其他都还好。
创始人 E: 我认为非常重要的一点是,首先要花相当多的时间,在一个纯粹的 LLM 环境中,构建出你想要做的东西的范围和实际架构,然后再把它交给 Cursor 或其他编码工具去执行。不要让它在代码库里随意发挥、胡乱编造实际上行不通的东西。所以,要确保你清楚自己构建目标的实际内容。
创始人 F: 我的建议是,要密切关注 LLM 在回答你问题时是否陷入了“兔子洞”。如果你注意到它一直在重新生成代码,而且看起来有点奇怪,无法真正解决问题,或者你发现自己需要不停地复制粘贴错误信息,那很可能说明哪里出了问题。你应该退一步,甚至提示 LLM 说:“嘿,我们退一步,分析一下为什么会失败”。是因为你没有提供足够的上下文让 LLM 理解?还是你运气不好,它就是无法完成你的请求?
这里的核心主题是,要让 LLM 遵循优秀专业软件开发者会使用的流程。那么,让我们深入探讨一些我见过的最好的 Vibe Coding 建议。
高效 Vibe Coding 的实践框架
1. 工具选择与规划
首先,从哪里开始?如果你以前从未写过任何代码,我可能会推荐像 Replit 或 Lovable 这样的工具。它们提供了易于使用的可视化界面,是直接在代码中尝试新 UI 的好方法。实际上,许多产品经理和设计师现在会直接用代码来实现新想法,而不是先用 Figma 这类工具设计模型,就因为它非常快。
但我尝试时发现,虽然这些工具生成的 UI 令人印象深刻,但当我想要更精确地修改后端逻辑,而不仅仅是纯粹的 UI 更改时,像 Lovable 这样的工具就开始遇到困难。我可能改动了这边的一个按钮,后端的逻辑却莫名其妙地改变了。
所以,如果你以前写过代码,即使像我一样有点生疏了,你可能可以直接跳到像 Windsurf、Cursor 或 Claude Code 这样的工具。
选定你想用的工具后,第一步不是马上开始写代码。相反,我建议与 LLM 合作编写一份全面的计划。把这份计划放到项目文件夹下的一个 Markdown 文件里,并不断回顾它。这是一个你和 AI 共同制定的计划,你在实施项目的过程中逐步推进,而不是试图一次性完成所有事情。
在你创建了计划的初稿之后,仔细检查一遍,删除或修改你不喜欢的部分。你可能需要明确标记某些功能为“不做”(因为太复杂),也可以保留一个“后续想法”的部分,告诉 LLM:“我考虑过这个,但目前不在范围内”。
有了计划之后,与 LLM 合作,一部分一部分地去实现它。明确地说:“我们现在只做第二部分”。然后,检查它是否工作正常,运行你的测试,然后进行版本提交 (git commit
)。接着,让 AI 回到你的计划文件,将第二部分标记为已完成。
我目前可能不会期望模型能够一次性完成整个产品,特别是复杂的项目。我更倾向于一步一步来,确保每一步都有一个可工作的实现,并且关键是要提交到 Git,这样如果下一步出了问题可以回滚。不过说实话,这个建议可能在未来两三个月内就会改变,模型进步太快了,很难说不久的将来会是什么样子。
2. 善用版本控制 (Git)
我的下一个建议是使用版本控制。版本控制是你的朋友,要虔诚地使用 Git。我知道那些工具自带了类似“撤销”的功能,但我目前还不太信任它们。所以我总是在开始一个新功能前,确保我的 Git 状态是干净的,这样万一 AI 跑偏了,我还能回滚到一个已知的、可工作的版本。
如果 AI 生成的代码不理想,不要害怕使用 git reset --hard HEAD
(硬重置)然后重新来过。我发现如果我反复提示 AI 去尝试修复某个问题,效果往往不好,它倾向于堆积一层又一层的坏代码,而不是真正理解问题的根源。你可能尝试了四五六次不同的提示,最终得到了解决方案。这时,我建议你记下这个解决方案,然后执行 git reset
回滚所有尝试,接着在一个干净的代码库上,将那个最终有效的解决方案输入给 AI,这样你就能得到一个干净的实现,而没有层层叠叠的垃圾代码。
3. 编写与运用测试
接下来你应该做的是编写测试,或者让你的 LLM 为你编写测试。它们在这方面做得相当不错,尽管它们常常默认编写非常底层的单元测试。我个人更倾向于让测试保持在非常高的层级,基本上是模拟用户点击浏览网站或应用的过程,确保功能是端到端正常工作的,而不是在单元级别测试函数。
所以,在转向下一个功能之前,请确保编写了高层级的集成测试。LLM 有一个坏习惯,就是会不必要地更改不相关的逻辑。你让它修复那边的一个问题,它却毫无理由地修改了这边的某些逻辑。因此,拥有这些测试套件能够及早发现这些“回归”问题,识别出 LLM 何时偏离了轨道、做了不必要的改动,这样你就可以 git reset
然后重新开始。
4. LLM 不仅仅用于编码
要记住,LLM 不仅仅是用来写代码的。我在构建这些个人项目时,会用它们来处理很多非编码工作。例如,我让 Claude Sonet 3.7 帮我配置了 DNS 服务器——这总是我讨厌的任务,还通过命令行工具设置了 Heroku 托管。它简直成了我的 DevOps 工程师,让我的进度加快了 10 倍。
我还用 ChatGPT 为我的网站创建了 favicon 图标,就是浏览器标签页顶部那个小图标。然后,Claude 接收了那张图片,并编写了一个快速的一次性脚本,将其调整为我在所有不同平台上所需的六种不同尺寸和格式。所以,AI 现在也是我的设计师了。
5. 高效调试技巧
好了,现在我们来看看 Bug 修复。当我遇到任何 Bug 时,我做的第一件事就是直接将错误信息从服务器日志文件或浏览器的 JavaScript 控制台复制粘贴给 LLM。通常,仅仅这条错误信息就足以让 AI 识别并修复问题。你甚至不需要解释哪里出错了,或者你认为哪里出错了,单单错误信息就够了。
这太强大了,我预计很快所有主流的编码工具都能自动获取这些错误,而无需人类进行复制粘贴。你想想,我们作为“复制粘贴机器”的价值有点奇怪,对吧?我们把思考交给了 LLM,但我认为复制粘贴这个环节很快会消失,这些 LLM 工具将能够监控日志(tail logs),或者启动一个无头浏览器来检查 JavaScript 错误。
对于更复杂的 Bug,你可以让 LLM 先思考三到四种可能的原因,然后再开始写代码。每次修复尝试失败后,我会 git reset
然后重新开始,这样你就不会累积一层层的“硬壳”(crust)。不要在不重置的情况下进行多次 Bug 修复尝试,因为 LLM 只会添加更多垃圾代码。git reset
,重新开始,并添加日志记录 (logging
),日志是你的朋友。
如果还是不行,就切换模型。也许试试 Claude Sonet 3.7,或者 OpenAI 的某个模型,或者 Gemini。我经常发现,不同的模型能在其他模型失败的地方取得成功。
如果你最终找到了某个棘手 Bug 的根源,我建议你重置所有之前的更改,然后在一个干净的代码库上,给 LLM 非常具体的指令,告诉它如何在那个精确的位置修复那个特定的 Bug,以避免累积那些层层叠叠的垃圾代码。
6. 提供明确指令与上下文
下一个技巧是为 LLM 编写指令。将这些指令放在合适的地方,无论是 Cursor 的规则(rules)、Windsurf 的规则,还是 Claude 的 Markdown 文件。每个工具的命名约定略有不同,但我认识一些创始人,他们为他们的 AI 编码助手编写了数百行的指令,这使得 AI 的效率大大提高。网上有大量关于在这些指令文件中应该包含什么的建议,你可以自己去查找。
7. 处理外部文档
好了,我们来谈谈文档。我仍然发现让这些 AI 助手直接查阅在线网页文档的效果还有点不稳定。有些人建议使用 MCP 服务器来访问文档,这对某些人有效,但对我来说似乎有点小题大做。所以我通常会直接下载某组 API 的所有文档,并将它们放在我工作文件夹的一个子目录里,这样 LLM 就可以在本地访问它们。然后在我的指令中,我会说:“在实现这个功能之前,先去阅读文档。” 这样做通常会准确得多。
顺便提一句,别忘了你可以把 LLM当作老师。特别是对于那些不太熟悉某种编程语言的人来说,你可以先实现某个功能,然后让 AI 逐行解释这个实现,并向你说明。这是学习新技术的绝佳方式,比我们过去常做的滚动浏览 Stack Overflow 要好得多。
8. 实现复杂功能
现在我们来看看更复杂的功能。如果你正在开发一个新的、比你通常信任 AI 实现的功能更复杂的部分,我建议你先在一个完全干净的代码库中,把它当作一个独立的项目来做。先获得一个小的、可工作的参考实现,排除你现有项目的复杂性干扰。甚至,如果有人写过并发布在 GitHub 上,你可以下载一个参考实现。然后,将你的 LLM 指向这个实现,并告诉它在你的大型代码库中重新实现时要遵循这个参考。这种方法效果出奇地好。
9. 关注代码结构
记住,小文件和模块化是你的朋友。这对人类程序员来说也是如此。我认为我们可能会看到一个向更模块化或基于服务的架构转变的趋势,在这种架构中,LLM 有清晰的 API 边界可以在其中工作,同时保持一致的外部接口。而不是那些巨大的、具有大量内部依赖的单体仓库(monorepos)。这些对于人类和 LLM 来说都很难处理,因为不清楚在一个地方的更改是否会影响代码库的另一部分。因此,拥有这种具有一致外部 API 的现代架构意味着你可以更改内部实现,只要外部接口和测试仍然通过,你基本上就没问题。
10. 技术栈选择考量
关于选择正确的技术栈的一点说明。我选择部分使用 Ruby on Rails 来构建我的项目,主要是因为我以前做专业开发者时比较熟悉它。但我对 AI 的表现感到非常惊讶,特别是当它编写 Ruby on Rails 代码时。我认为这是因为 Rails 是一个有 20 年历史的框架,拥有大量成熟的约定。很多 Rails 代码库看起来非常非常相似,对于有经验的 Ruby on Rails 开发者来说,很明显某个特定功能应该放在哪里,或者实现某个结果的“Rails 方式”是什么。这意味着网上有大量相当一致的高质量 Rails 代码训练数据。
我其他的朋友在使用像 Rust 或 Elixir 这样的语言时,效果就不那么理想,因为网上这类语言的训练数据就少得多。但谁知道呢,这种情况可能很快就会改变。
11. 创新的交互方式
下一个建议:使用截图。现在你可以将截图复制粘贴到大多数编码助手中,这非常有用。既可以用来展示你看到的 UI 实现中的 Bug,也可以用来从你想要在项目中借鉴的其他网站获取设计灵感。
语音是另一种与这些工具交互的非常酷的方式。我使用了 YC 投资的一家公司 Aqua。基本上,我可以对着电脑说话,Aqua 会将我说的话转录到我正在使用的工具中。我目前在 Windsurf 和 Claude Code 之间频繁切换,但有了 Aqua,我实际上可以以每分钟 140 个词的速度输入指令,这大约是我打字速度的两倍。而且 AI 对轻微的语法和标点错误容忍度很高,所以即使转录不完美也基本没关系。实际上,我这整个演讲稿就是用 Aqua 写的。
12. 频繁重构
接下来,确保频繁重构。当你让代码正常工作,并且关键是实现了测试之后,你就可以随心所欲地进行重构了,因为你知道你的测试会捕捉到任何回归问题。你甚至可以要求 LLM 识别出你的代码库中看起来重复或者可能是重构好目标的部分。
再次强调,这只是任何专业软件开发者都会遵循的建议。你不应该有数千行长的文件,保持文件小而模块化,这使得人类和 LLM 都更容易理解发生了什么。
持续学习与实验
最后,保持实验!这个领域的技术似乎每周都在变化。我尝试每一个新发布的模型,看看哪个在不同场景下表现更好。有些模型更擅长调试,有些更擅长长期规划,或者实现功能,或者重构。
例如,在目前(视频录制时),Gemini 似乎最擅长整个代码库的索引和提出实施计划,而对我来说,Sonnet 3.7 似乎是实际执行代码更改的主要竞争者。我几天前刚试用了 GPT-4.1,老实说,我还没有那么印象深刻,它给我返回了太多问题,而且实际上实现错误的次数也太多了。但我下周会再试试,我相信情况又会发生变化。
结尾
感谢观看。如果你有任何关于如何充分利用这些模型的技巧或诀窍,非常希望你在下面的评论中分享。
要点回顾
Vibe Coding 核心理念与入门
- 定义与现状: Vibe Coding 指利用 AI (LLMs) 辅助甚至主导软件开发。它效果显著,且可以通过实践和学习最佳方法来提高效率。
- 类比: 类似于几年前的提示工程 (Prompt Engineering),最佳实践和技巧在不断涌现。
- 核心思想: 最好的 Vibe Coding 技巧往往与专业软件工程的最佳实践一致。目标是利用 AI 工具获得最佳结果。
- 学习心态: 保持开放心态,乐于尝试和采纳最佳实践。
YC 创始人的 Vibe Coding 实用技巧
- 调试: 若 AI IDE 陷入调试死循环,尝试将代码和问题粘贴到 LLM 的原生网页界面寻求解决方案。
- 多工具协作: 同时使用不同 AI 编码工具(如 Cursor 和 Windsurf),利用各自优势(速度 vs 深度思考),甚至并行生成不同方案供选择。
- 视 AI 为编程语言: 将 Vibe Coding 视作一种新的编程方式,需要提供详尽的上下文和信息才能获得好结果。
- 测试驱动: 先手动编写高质量的测试用例,然后让 LLM 生成能通过这些测试的代码,最后仅需概览代码模块化程度。
- 先规划架构: 在使用具体编码工具前,先花时间与纯 LLM 交流,明确项目范围和架构。
- 监控 AI 状态: 注意 LLM 是否陷入困境(“兔子洞”),如果反复生成奇怪代码或需要频繁粘贴错误信息,应暂停,让 LLM 反思失败原因(上下文不足或运气不好?)。
高效 Vibe Coding 的实践框架
1. 工具选择与规划
- 新手: 可从 Replit 或 Lovable 等提供可视化界面的工具开始,适合快速实现 UI 原型,但可能在复杂后端逻辑修改上受限。
- 有经验者: 可直接使用 Windsurf, Cursor, Claude Code 等工具。
- 关键步骤 - 先规划:
- 与 LLM 合作制定全面的项目计划 (Markdown 文件形式存放于项目内)。
- 明确功能范围,标记“不做” (Won't do) 或“后续考虑” (Ideas for later) 的部分。
- 按计划分步实施:每次只完成计划的一个部分。
- 检查、运行测试、提交版本控制 (
git commit
)。 - 让 AI 标记计划中已完成的部分。
- 注意: 目前不宜期望 AI 一次性完成复杂项目,分步验证更可靠(但技术发展迅速,此建议可能很快过时)。
2. 善用版本控制 (Git)
- 高频使用: 频繁进行
git commit
,作为可靠的回滚点。不要完全依赖工具内置的撤销功能。 - 保持干净: 开始新功能前确保 Git 工作区是干净的。
- 果断回滚: 若 AI 生成代码不理想或陷入困境,大胆使用
git reset --hard HEAD
回滚到已知良好状态重试。 - 避免累积错误: 不要反复提示 AI 修复同一问题,这会累积劣质代码。找到正确方案后,应回滚到干净状态再应用该方案。
- 高频使用: 频繁进行
3. 编写与运用测试
- 让 AI 编写: 可以让 LLM 编写测试,但要引导它。
- 偏好高层级测试: 优先编写模拟用户操作的端到端集成测试,而非低级单元测试。
- 时机: 在完成一个功能、进入下一个功能前编写测试。
- 作用: 测试能有效捕捉 LLM 意外修改不相关代码导致的“回归” (regressions)。
4. LLM 不仅仅用于编码
- 扩展应用: 利用 LLM 完成非编码任务,如配置 DNS、设置 Heroku 托管 (DevOps)、生成网站图标 (Favicon) 并编写脚本处理图像 (设计)。
- 角色: AI 可以充当你的 DevOps 工程师和设计师。
5. 高效调试技巧
- 直接粘贴错误: 遇到 Bug 时,首先将完整的错误信息(来自服务器日志或浏览器控制台)直接粘贴给 LLM,通常足以让其定位并修复问题。
- 未来趋势: AI 工具可能会直接接入错误日志,无需手动复制粘贴。
- 复杂 Bug: 让 LLM 先分析几种可能的原因,再尝试修复。
- 失败后回滚: 每次修复尝试失败后,使用
git reset
回滚,避免代码库越来越混乱。 - 添加日志: 使用日志 (
logging
) 辅助调试。 - 切换模型: 如果一个模型卡住,尝试切换到其他模型(如 Claude, OpenAI, Gemini),不同模型各有优劣。
- 最终修复: 找到棘手 Bug 的根源后,回滚所有尝试性修改,然后在干净的代码库上给出精确的修复指令。
6. 提供明确指令与上下文
- 编写规则/指示: 在工具允许的地方(如 Cursor rules, Windsurf rules, Claude markdown file)为 LLM 编写详细的操作指南和背景信息,能极大提升其效率。
7. 处理外部文档
- 本地化: 当前让 AI 直接读取在线文档效果不佳。建议将相关 API 文档下载到项目本地子目录中。
- 明确指示: 在指令中要求 LLM 在编码前先阅读本地文档。
- 利用 LLM 学习: 让 AI 逐行解释它生成的代码,是学习新技术的好方法,优于在 Stack Overflow 上搜索。
8. 实现复杂功能
- 独立原型: 对于复杂功能,先在全新的、独立的代码库中实现一个最小可行参考版本 (reference implementation)。
- 利用参考: 可以下载 GitHub 上的现有参考实现。
- 指导迁移: 让 LLM 参考这个简单的实现,在你的主项目中重新实现该功能。
9. 关注代码结构
- 小文件与模块化: 保持代码文件小、功能模块化,这对人类和 LLM 理解代码都有利。
- 架构趋势: 可能向更模块化、面向服务的架构演进,具有清晰 API 边界,便于 LLM 在不破坏外部接口的情况下修改内部实现。避免大型、高耦合的单体仓库 (monorepos)。
10. 技术栈选择考量
- 成熟框架优势: 具有悠久历史、完善约定和大量高质量训练数据的技术栈(如 Ruby on Rails)可能让 AI 表现更好,因为模式一致性高。
- 新兴语言挑战: 较新或训练数据较少的语言(如 Rust, Elixir)可能效果稍差,但这种情况可能随模型进步而改变。
11. 创新的交互方式
- 利用截图: 将 UI 问题截图或期望模仿的设计截图直接粘贴给 AI,辅助沟通。
- 语音输入: 使用 Aqua 等工具进行语音输入,可以达到比打字更快的输入速度,且 AI 对转录中的小错误容忍度较高。
12. 频繁重构
- 时机: 当代码功能正常工作并通过测试后,即可进行重构。
- 保障: 测试用例能捕捉重构引入的回归问题。
- AI 辅助: 可以让 LLM 识别代码中重复、冗余或适合重构的部分。
- 专业实践: 保持代码整洁、文件小而模块化,是专业软件开发的标准做法。
持续学习与实验
- 保持更新: Vibe Coding 技术日新月异,每周都可能有变化。
- 尝试新模型: 积极试用新发布的模型,评估它们在不同任务(调试、规划、编码、重构)上的表现。
- 模型差异: 认识到不同模型各有侧重(如视频发布时 Gemini 擅长规划,Sonnet 3.7 擅长编码实现)。
- 拥抱变化: 持续实验,找到最适合自己工作流程的工具和方法。