在前文我提到目前正在做的 vscode docpilot 插件是我准备当作试探 vibe coding 底线的一个实验项目。虽说是实验项目,但要求并不低,毕竟我是打算要在市场发布它的,也打算开放它的源代码。
既然如此打算,自然不能在发布和开源时太丢人,那么自然至少需要:
- 功能正确
- 代码质量过得去
- 自动化测试
就目前的功能而言,耗时 1.5 周:
- 轻量级 pdf viewer 的基本功能,如翻页导航、文本选择、复制、搜索等。亮点:
- 轻量级自定义 viewer,不像那些 pdf viewer 的 vscode 插件那样打包了整个 viewer 进去。
- 同时支持本地和远程 pdf 文件。
- github copilot chat 的集成。亮点:
- 自带缓存管理和智能 chunking 策略
- debug 模式,显示 text layer 方便了解常见的 pdf 文本选择问题。
- PDF Inspector,支持 object 和 page 两种视图,查看 pdf 内部的图片、字体、表格、元数据等信息。亮点:
- 对于大文件,支持 progressive loading,这里主要是图片提取。
- Extractor,支持提取 pdf 中的图片、字体、表格等信息。
阔是,此时的代码质量一言难尽:
- 没有任何测试
- pdf viewer 代码行接近 5k
此时,在新增功能时,我已明显觉得 CC 不给力了。于是乎,我觉得在新增功能前进行两次大手术:添加测试框架和重构 pdf viewer。
各花时差不多 1 周,其间自己否定自己了好几次,但从中也学到了一些在真实生产环境下 vibe coding 的实践经验。于是,撰文记录下来,供团队和大家参考。
我的 Vibe Coding 目标
继续之前,先说说的我的目标:
- 从事的项目是实际的真实项目,而非为了吸引流量写的 POC,毕竟我又不是各大厂商的 DR。
- 追求自动档的 vibe coding,既 90% 以上的代码都是 ai 小弟写的,我只干两件事:
- 讨论计划和验收标准
- 看测试用例了解是否覆盖典型场景和边界场景
这并非是由于哥的 coding 技能不行(了解我和我团队的人应该心里有数,这里就不吹嘘了),看到 ai 小弟来了觉得有了救命稻草。而是因为:
- 我是一个懒人。
- 我想做杠杆率更大的事情。
不断试探 vibe coding 在真实项目中的应用边界,则有助于未来将杠杆率最大化。你想想,人肉手敲键盘的速度怎么赶得上电信号的光速,😄。
到目前为止,vscode docpilot 的代码情况:
- unit、integration 和 e2e 测试基础设施已经建立
- pdf viewer 重构完成,分拆成若干组建,引入了单独为 webview bundling 的过程。
- 它原本的 vscode 插件相关的代码本来基础就不错(因为核心复杂逻辑不在此),目前没有进行大动作。
整个项目打包之后 200+k,同时 90+% 的代码都是 ai 小弟写的:
- 主程:CC
- 副程:GC, github copilot
- 评审:Gemini
- 信息收集:Gemini 和 ChatGPT
我则是:PM + 测试 + 评审。
将 LLM 视为函数对待有助你设定正确的 Vibe Coding 预期
现在,vibe coding 处于泡沫期。身处其中,若不设定正确的期望,不仅浪费金钱和时间,还会让自己从一个极端走向另一个极端,看不清真实的情况,也无助于合理利用。
抛开那些让人眼花缭乱的高级术语和工具不谈,vibe coding 和普通的 RAG 没有太大本质区别,只有复杂度差异。若有此认识,你会对 vibe coding 有更清晰的认识和期望,同时也会更明白高质量输出的关键在哪里。
因此,以 CC 为例,我不太建议你去做:
- 找时髦的生态工具,搭建复杂的工作流,然后如油管上那帮 AI KOL 们一样,一键生成整个系统。
- 一开始去考虑什么 slash command 或者最近 CC 的新特性:subagent。
- 一些所谓的 CC native 的项目模板,不建议现阶段使用。
以上都是执行层面(即 how)的优化和自动化,对于方向层面的(即 what)复杂度帮助并不大。并且,有经验表明:MCP 工具过多也会影响 ai coding 的效率。
MCP 对于编码任务的用处较小,原因在于它们会消耗宝贵的上下文用于定义,
相反,我建议你:
- 关注如何将 vibe coding 与你现有的开发流程结合起来,甚至于改造现有流程一适应它,使其能最大化产出。
- 之后,在结合以上工具,提升执行层面的效率。
到目前为止,我在 CC 的使用中:
- 没有引入其他生态工具,如 superclaude 或 task manager。
- 没有使用最新的 subagent 特性。
- 没有配置额外的 MCP tools,就它缺省的。
- 使用了 slash command 和 claude.md
主打一个朴实无华,聚焦提升和 CC 们打交道的能力,因为那些外部工具帮助不了你。
多次自我否定之后的经验
充分计划,一击命中
不知各位是否有这样的感觉:当面对一个问题时,若 ai 无法第一次就生成八九不离十(即 90% 正确)的代码,那么你就不要再指望可以动动嘴就把事情办成了,除非那是常规需求。
敏捷惯了的同学需要在此尤其注意:不要采用先干了再说的做事方式。如此只会让你陷入无休止的对话之中,浪费时间和精力。不要迷信网上的 PUA 技巧,它如果理解错了,什么招都不好使!
将每次 ai 代码生成视为一个 batch 任务,充分讨论,最后再执行:
- 给它提供充分的上下文信息,让它生成计划。
- 你来 review 计划,并针对计划不断提问,促使它反思和完善。
- 在计划通过之后,让它将计划保留到文件中。
- 方便追踪
- 方便 ai 罢工之后再接着干,类似游戏存档。
- 代码生成
- 检查功能
当然,你可以在这里要求它同时生成测试,方便功能代码和测试代码相互验证。
如果发现它生成的不尽如人意,且差异较大,不要硬着头皮继续,直接推翻重来(注:这里替你省了 n 天时间!)。
由此,这里得出一个另一个技巧:版本控制 + 特性分支,方便随时丢弃。
何为充分的上下文信息?请解放你的思路和想象力!
它们无非就是提供给小弟干活的信息,不见得仅仅就是代码本身。作为一个负责任的带头大哥,你当然可能也会给小弟提供一些背景知识之类的。因此,这些信息可以是(除了显而易见的代码):
- 各类图:流程图、ui 设计图、架构图等。
- 通用知识,如找 chatgpt 总结的那些相关领域知识的条条框框,没有必要详细,条目即可。它们是为了唤醒 llm 的记忆。
- 业务知识
- …
一个原则,凡事有助于帮 ai 小弟更好地理解你的意图的,都可以提供。
我是如何驱使 CC 生成测试的
第一次 CC 生成的测试,我惊异于其的 pass 率,一看代码,忍不住拍断大腿:遍地 mock!
当时我尚未如本文所言杀伐决断,跟 CC 来来回回交锋了一两天吧,终于忍不住推翻重来。
此时,我换了一个思路:让 Gemini 先总结一下现状,明确了一下测试的目标和范围。之后,交给 CC 去讨论,然后按上面说的开始走。
这一次,它生成的测试代码有点意思了,剩下的就是在这样的基础之上继续迭代。最终形成了 unit、integration 和 e2e。
最后一个 playwright 驱动 vscode 的 e2e 测试,费了些时间。
因为传统做法都是单独将 webview 中的网页单独起到一个浏览器中去测试。但为了逼一逼 CC,在确认我的方案可行之后,我决定要 playwright 直接驱动 vscode 的 webview,完成真正的 e2e 测试。
在 CC 脑子短路之时,又是让 Gemini 大哥生成了一段如何让 playwright 驱动 vscode webview 的代码,将其传给 CC,这才让它重新明白了前进的方向。
这里有两个关键的上下文起到了关键作用,最终都是靠 Gemini 的长上下文帮忙解决的:
- 帮助 CC 理解测试目标的项目概括
- 帮助 CC 理解 playwright 驱动 vscode webview 的示例代码。
我是如何驱使 CC 重构 pdf viewer 的
这是一次痛苦的经历,连续推翻代码两次。
第一次放手让小弟干,结果规划能力和编码能力不匹配,导致很多精细的控制,如 lazy loading 和 progressive loading 怎么都通不过,而且还丢三落四。
第二次决定反其道而行之,让 CC 聚焦一个小目标,一步步拆分,依旧不理想,同样的问题。
第三次,我突发奇想:
- 让 Gemini 总结重构的原则,都是干条条,没有解释。
- 让 Gemini 去读这个原则 + readme + 代码,生成一个重构计划。
- 我 review 计划,提出问题,尤其是前几次重构时的误区。
- Gemini 修正,我在 review。
- 如此多次。
- 最终形成了一个重构计划,并保存。
考虑到 CC 的上下文不如 Gemini,因此让 Gemini 直接执行计划,我实际测试并跑了一下,居然大面上不错。
之后,CC 再接手完成精加工。
各位应该不难看出此处的关键上下文:
- 重构原则 + readme + 代码
- 前面的重构误区
这两次经历充分让我意识到一言不合就回滚的重要性。与其采用刘徽割圆的方式无限逼近,不如直接推翻重来,充分计划,追求阿飞的那一剑。
并且,两次基本都是在重来之后,一次性到达理想高度。时间耗费最大的反而是试图逼近的无休止对话,再次提醒:那是遥不可及的海市蜃楼,幻象!
用好 Git
推翻重来可以发生于各阶段,建议各位将 vibe coding 等同于你打游戏的场景:
- 在每个满意点,及时保存,方便小范围随时回滚。
- 使用特性分支,方便大范围的推翻重来。
这种组合方式可保你在 vibe coding 时安全驾驶,无后顾之忧。
随时 compact
除了阶段性回滚不如意代码,阶段性遗忘也很关键。
上下文过长会导致 ai 出现记忆力涣散的毛病,同时也浪费处理时间和费用。我的习惯是在阶段性完成后,compact 一下上下文。
可将此与你的开发计划结合起来,让 ai 小弟开发完随时:
- 更新进度文件
- 你复核
- commit 或 stage
- compact 上下文
不满意,就回滚。
测试和 backup 是你的 vibe refactoring 的防护网
除了前面那些,在进行架构性重构时,测试和被重构的代码备份也很关键。
测试,大家都懂,就是让 ai 在重构时边运行边改。
备份,尤其是原来可工作的备份也很关键,它可以让 ai 在重构时可随时参考。因此,在重构前,建议手动复制一份。
并且,要留意不要让 ai 在重构过程中将其误判为重复代码,直接删除了。不要问我是怎么知道的!
多总结,形成高层知识网
即便上下文再长,你要让它记住所有细节也不太可能。并且有论文表明 llm 对于长上下文也会出现性能下降的问题《“Lost in the Middle: How Language Models Use Long Contexts”》。
既然如此,不妨向人学习,记笔记,做总结。形成高层知识网之后,方便 ai 小弟能更全面的考虑问题。此时 Gemini 大哥最擅长,前面在测试和重构例子中都均有提及。
但也请复核它生成的内容,确保你期望的内容被正确包含。典型的高层知识:
- readme
- code review:源代码和测试
- 网上搜罗(或 LLM 总结的)的知识
- 当前任务的进度报告,这在换 llm 时最方便,换人如换刀嘛。
- …
好记性不如烂笔头,多用外部存储来作为 ai 小弟们的知识传递网。
及时重构和测试
如果让我再次用 CC 开启一个新项目,我肯定会在每次任务完成之后及时重构和测试。
也正是因为头次使用,想尽快看看它几斤几两,故而一路狂奔,直到最后打算将它发布和开源之后,才下定决心开始这一动作。毕竟哥是一个随性的人,😄。
重构可以让代码聚焦,有助于 llm 更好的生成;测试则是 llm 可自行调用的保护网。最后,别忘了给它传授 MF 的 refactoring 原则。
这样下来,基本盘就稳了。
结语
深度思考,聚焦本源,方是 vibe coding 的核心。时髦的工具和命令不过是锦上添花,若不聚焦本源,反而是代码屎山的加速器。慎之,慎之!