氛围编程(Vibe Coding)的真相以及为什么要警惕氛围编程
小麦2025年07月02日2018 字
给氛围编程泼一盆冰水,聊聊我对氛围编程的观察和思考。
引言#
氛围编程(Vibe Coding)是 2025 年最热门的编程概念之一,由 OpenAI 联合创始人、前特斯拉 AI 负责人 Andrej Karpathy 提出。这种编程方式强调 "完全沉浸在氛围中,拥抱技术的指数级发展,并忘记代码的存在"。
氛围编程的定义#
不同人对于氛围编程的定义和实践并不相同,不过大致可以分为以下两类:
- 保守派:认为主要通过聊天,但需要进行代码审查的模式属于氛围编程
- 激进派:认为完全依赖 AI、不进行代码审查的纯聊天模式属于氛围编程
无论定义如何,氛围编程的核心特征都是通过自然语言对话让 AI 生成可用代码,或是完成一个软件功能。
实际操作中,我更多属于保守派,即在严格限定的范围内,通过 Vibe Coding 让 AI 独立完成一个不太重要的模块,但人写起来要花一些功夫。
氛围编程要解决的问题#
氛围编程解决两大问题:效率和门槛。
首先,它将开发者从繁杂的代码逻辑和 bug 中解放出来,更关注程序的运行结果,可以说是结果驱动开发。
其次,氛围编程可以实现快速验证想法,几乎抹平了编程门槛,让人人都能参与进来。
错误的期盼#
许多人将氛围编程视为解决所有软件开发问题的万能解药,期望通过它跳过传统的编程学习过程,实现 “弯道超车”,本质上是在用 AI 生成的代码来掩盖自身技术能力的缺陷,认为掌握氛围编程就能快速开发出成功的产品。
但是,真实情况往往会比想象中的更复杂,一个成功的产品需要的不仅仅是代码,还需要优秀架构设计、用户体验以及市场验证等。
从 MVP 过渡到生产级的鸿沟#
"AI is like having a very eager junior developer on your team" an idea well illustrated in this illustration by Forrest Brazeal
生产级应用和 MVP 应用的差异是巨大的。
在代码量级上,MVP 通常几千行,而生产级通常都在数十万行以上。要维护好一个数十万行代码的 codebase 并非易事,在处理大规模代码库时,AI 往往难以理解复杂的代码结构和依赖关系,产生大量的冗余代码。
一个常见的错误论断是:我功能实现出来了,代码烂不烂其实不重要。这里的错误在于,只考虑到眼前的成果,而忽视了阶段性成果到最终价值的转换其实还有很大的 gap。这就像爬山,爬过一个小坡,前方还有一万个陡坡在等着。古人早就说:“不识庐山真面目,只缘身在此山中。”
另外,生产级应用非常强调通过工程化手段,来提升稳定性和可维护性,对于不同的场景,要有针对性的解决方案。比如同样是大促秒杀,淘宝和京东的做法会很不一样,氛围编程大概率想不出来也写不出来以前没有见过的方案。
几个需要警惕的问题#
1. 此氛围非彼氛围#
那些声称通过氛围编程提效数十倍、以一敌百的成功案例背后,往往隐含了以下事实:
- 使用者本身就是资深工程师,具备快速调试和问题解决的能力。
- 项目复杂度相对较低(多为原型或小工具)。
当自我陶醉在氛围编程的成就中时,不妨想想此氛围是不是彼氛围。
2. 简单问题复杂化#
氛围编程通过不断的迭代和纠错来解决问题,但这种机制容易将简单问题复杂化。
举一个例子:
我有一个卡片列表 cards,帮我实现一个 React 卡片瀑布流组件,它能始终占满屏幕宽度,并自动计算列数。
宇宙最强编程模型 Claude Sonnet 4 给出的实现包含复杂的 hooks 计算逻辑:
import React, { useState, useEffect, useRef } from 'react';const WaterfallCards = ({ cards }) => {const containerRef = useRef(null);const [columns, setColumns] = useState(3); // 默认3列const [positions, setPositions] = useState([]);const [containerHeight, setContainerHeight] = useState(0);const cardWidth = 300; // 卡片固定宽度const gap = 16; // 卡片间距// 计算列数const calculateColumns = () => {if (!containerRef.current) return;const containerWidth = containerRef.current.offsetWidth;const cols = Math.floor((containerWidth + gap) / (cardWidth + gap));setColumns(Math.max(1, cols)); // 至少1列};// 计算卡片位置const calculatePositions = () => {if (columns === 0) return;const columnHeights = new Array(columns).fill(0);const newPositions = [];cards.forEach((card, index) => {// 找到高度最小的列const minHeightIndex = columnHeights.indexOf(Math.min(...columnHeights));// 计算位置const x = minHeightIndex * (cardWidth + gap);const y = columnHeights[minHeightIndex];newPositions.push({ x, y });// 更新该列高度(假设每个卡片高度为200px + gap)columnHeights[minHeightIndex] += (card.height || 200) + gap;});setPositions(newPositions);setContainerHeight(Math.max(...columnHeights));};// 监听窗口大小变化useEffect(() => {calculateColumns();window.addEventListener('resize', calculateColumns);return () => window.removeEventListener('resize', calculateColumns);}, []);// 重新计算位置useEffect(() => {calculatePositions();}, [cards, columns]);return (<divref={containerRef}style={{position: 'relative',width: '100%',height: containerHeight,padding: `${gap}px`,boxSizing: 'border-box'}}>{cards.map((card, index) => (<divkey={card.id || index}style={{position: 'absolute',left: positions[index]?.x || 0,top: positions[index]?.y || 0,width: cardWidth,height: card.height || 200,backgroundColor: '#fff',borderRadius: '8px',boxShadow: '0 2px 8px rgba(0,0,0,0.1)',padding: '16px',boxSizing: 'border-box',transition: 'all 0.3s ease'}}>{/* 卡片内容 */}<div>{card.title}</div><div>{card.content}</div></div>))}</div>);};export default WaterfallCards;
但实际上经验丰富的老登只需要一行代码就可以了:
<div className="grid grid-cols-[repeat(auto-fill,minmax(200px,1fr))] gap-4">
假设氛围编程的使用者并不知道有 CSS Grid 布局这个东西,那么极有可能写不出来这样的代码。因此基础学习和通识教育依然是重要的。
3. 不可忽视的沉默成本#
氛围编程可以在短时间之内生成数千甚至上万行代码,随着代码量的增长,技术债务的影响会呈指数级增长。开发者对技术债务做出的妥协(不重构、不优化),在未来会通过改造成本成倍返还,直到难以通过有限的精力维系下去,然后推翻重做。
激进的氛围编程恰恰是妥协到底,缺乏系统性的质量控制机制,开发者对代码毫无理解,重构会变得非常困难。也并没有有效的方法论来规避客观的技术债务问题。
一个经典论断是:维护不下去那就重来,反正不缺 tokens。这里的错误在于,没有几个项目禁得起重来,能重来的项目也不缺那些 tokens 花掉的钱。
4. 敬畏软件工程#
几十年来,软件工程一直在讲模块化设计、关注点分离、单一职责、开闭原则、分层结构、领域驱动、代码重构。这些方法论无一不是在为一个成功的产品打好地基,俗话说地基不稳地动山摇。
软件系统的复杂性是客观存在的,不会因为开发工具的改进而消失。经典的软件工程方法论提供了管理复杂性的有效手段。
当前阶段的氛围编程,似乎屏蔽了软件工程的实践细节,但是这些方法往往需要精心选择、相互配合才能发挥价值。专注局部功能的实现,缺乏对整体系统思考和设计的氛围编程,还没有解决软件工程已经解决的种种难题。
小结一下#
氛围编程作为一种新兴的编程方式,它降低了编程门槛,提高了开发效率,让更多人能够参与到软件开发中来。但是,我们依然必须清醒地认识到其局限性和适用边界,同时小心沉默成本,敬畏软件工程。