如今,似乎所有人都在告诉你:还在一行一行手写代码?那你已经“落伍”了。真正跟得上时代步伐的开发者,早就玩上了“AI全栈”——扔给AI一句模糊的需求,然后闭着眼等结果;代码不用读,Agent必须多开,最好同一时间搞定好几件事情。

朋友圈里天天刷到这类故事,搞得还在手写代码的人总觉得自己已经被时代远远甩在后面。但话说回来,AI固然强大,可它真能包打天下、适合所有开发场景吗?如果不适合,那Vibe Coding到底在什么地盘上才能大显身手?这个问题必须想明白,否则项目做得一点都不踏实。
经过反复琢磨,得出的结论是:Vibe Coding的适应性,并不取决于AI有多强,而取决于语言本身的匹配度。简单来说,你的需求越容易用日常口语讲清楚,就越适合直接用AI来写;反过来,如果你的需求用代码讲比用自然语言讲更容易、更精准,那手工敲键盘才是正解。
这么说可能有点抽象,来拿一个具体的东西说——比如开发一个KV存储引擎。
功能需求
乍一看,KV引擎真没什么高深的。我们先描述一下它的接口大概长什么样:
public interface KVStorageEngine {
void open(DBOptions options);
byte[] get(byte[] key);
void set(byte[] key, byte[] value);
byte[] delete(byte[] key);
Iterator newIterator();
void close();
}
说白了无非就是增、删、改、查加迭代。你把这种需求塞给AI,有的模型二话不说开干,有的可能还会追问几句:对持久化有没有特定要求?要不要支持事务和并发?而一旦你给模型明确的起点,它们就会快速给你排计划。比如Claude Code给出的开发计划还挺像那么回事的:
- 搭建项目骨架,定义核心接口
- 实现内存表(MemTable)
- 实现磁盘表(SSTable)和布隆过滤器
- 引入WAL(预写日志)
- 搞定Compaction(合并压缩)
- 设计并发控制和锁机制
- 实现事务支持
- 拿出快照功能
- 编写主存储引擎
非功能需求
这个计划听起来不错,但真能这样拍板就干吗?上面这些接口,只是冰山露出水面的一角;在水下,还有大量非功能性需求等着被料理。我们来拆开看看——
关于性能。 首先要明确,你这引擎主要啃哪个场景?是追求随机写入的极致速度,还是寻求读写之间的平衡?不同的目标,背后对应完全不同的核心数据结构——到底是LSM-Tree还是B-Tree。如果按Claude Code的计划走LSM-Tree路线,那马上得面对LSM-Tree几个硬伤:读性能存在不确定性,Compaction时的抖动问题也必须处理。怎么解决?要不要引入Cache或布隆过滤器?引入Cache之后,怎样优化跟操作系统天然缓存机制的对齐?要不要加个RateLimiter来限IO流量?线程池怎么设计?
关于持久化。 数据到底怎么落盘?WAL需要在事务完整性、备份快照、写缓冲与磁盘同步之间找平衡。策略让用户自己选?那什么默认配置能帮普通用户一把、实现开箱即用?是不是只有特殊环境才需要手动调?继续往下想,HDD和SSD在持久化上的差异要考虑吗?读写放大对它们的影响怎么量化?支持分布式文件系统吗?要不要支持TTL(过期时间)?
关于一致性。 不同操作间如何确保隔离?随机读写、迭代、Compaction、事务……这些操作互相打架的时候,怎么保持数据一致?
关于抽象和扩展。 MemTable能否支持多种底层数据结构?比如用SkipList来搞顺序存储,用HashTable只为纯粹的随机读取场景。持久化策略是不是也能做成可配置的,方便直接当缓存用?用户操作Compaction时有没有自定义的能力?
这些非功能需求的数量,远远超过最初那几张增删改查的接口。每一个点再往下细分,都能写出长篇大论。
非功能性需求与Vibe Coding
当然,你可以把这些非功能需求一个不落全抛给AI。以现在大型模型的实力,它们完全有能力理解,甚至知道的可能比你更多。但关键问题是——
如果你不把这些条条框框详细地告诉AI,它不会主动把它们纳入考虑。它只会挑那些自己觉得重要的点、或者照搬市场上已有产品的做法来解决。这意味着你需要对数据库领域有极深的理解,才能精准地把这些需求完整喂给AI。你对这个领域理解得越透彻,从AI那撬动的价值才越大。
这些需求不是独立的,而是彼此牵扯、相互制约的。取舍决策背后,取决于你的产品最终要解决什么问题,你追求什么架构哲学。说白了,这种战略层次的目标,AI没法替你做——除非哪天AI自己萌生了创造动机。真到那一步,别说Vibe Coding了,它可能都起身自己挣钱去“赡养”人类了。
所以一旦非功能性需求被理清、做出权衡,远不是“Vibe”二字能概括的。你可能会想:甭管多复杂,我全用自然语言描述清楚不就行了?大不了多细心点。但事情还没那么简单——
细节之中充斥着大量重要的决策
上面谈的还是架构层次的选择。而像KV引擎这种项目,实际开发中还有海量决策,偏偏这些决策用自然语言表述起来极其困难。恰恰是它们的存在,决定了手工编码的不可替代性。
拿最简单的事举例:加锁。每次加锁,你实际上都在做这些抉择:
锁的粒度怎么定?
- 粒度大的坏处——拖累性能
- 粒度小的风险——可能漏掉线程安全
这块代码的竞争频率高吗? 该选悲观锁还是乐观锁?
一旦有锁竞争,会不会影响CPU亲和性?带来性能抖动?
这个锁跟其他锁的关系? 会不会死锁?
一次反问: 锁真的非得加吗?能不能换成局部化处理,或者改用无锁算法优化?
加锁的代码往往只有一行,但你要解释清楚“为什么锁必须放在这儿,而不是别的位置”,可能得写一篇长篇小作文。这个问题有多重要?对于数据库来说,就是命脉。锁摆错了地方,导致灾难性后果;锁的粒度或类型选错了,性能直接崩盘。这些细节层面的决策,重要性丝毫不亚于架构层面的考量。甚至可以说,在功能需求极其简单的时候,对细节的极致打造才是你产品最大的竞争力。
AI能判断锁该加在哪儿吗?当然能。但问题是你没法保证它每次都判断对,而且你永远不知道它靠什么逻辑在做判断。更糟糕的是:这种决策遍布整个代码,它们之间并非孤立,而是彼此串联。串联起来的知识属于隐性知识,很难甚至无法用自然语言清晰地描述。所以,对这种技术细节决定一切的项目,手工编码远比AI替我写要靠谱。而且,坦白讲,这类项目的核心功能就那么固定,优化的空间都在细节上,开发效率的翻倍,其实构不成真正意义上的竞争力。
回归本质
最后回到出发点:想知道你手里的项目到底适不适合Vibe Coding,最简单的方法就是比一比需求的表达方式——你的需求更容易用自然语言描述,还是用编程语言描述更直接。如果是前者,放心大胆扔给AI;如果是后者,大大方方打开编辑器手写,一点都不丢人。
