最近关于「凭感觉编程」(Vibe Coding)以及 LLM 将如何颠覆软件开发的讨论铺天盖地。据说,每一个新模型的发布都会把我们带入纯粹生产力的天堂。
Jacob Harris 说:或许吧,但我自己是不「凭感觉编程」的。
我不是原教旨主义者,但我是个守财奴
他试过 IDE 里的 LLM。对于那些描述起来很简单、但自己动手又嫌烦的任务,它们确实挺好用的。但当他试着用 AI 工具分析项目代码时,额度用光了。如果想继续,请绑定信用卡购买更多 Token。
「当我发现为了让自己能『思考』,居然还要无休止地给一个服务交钱时,我浑身不自在。」他卸载了 IDE,用回了 Emacs。然后发现,压根儿没觉得少了 AI 有什么不习惯的。
年纪大了,读过《没有银弹》
Fred Brooks 在《人月神话》中区分了「偶然复杂性」(accidental complexity)和「本质复杂性」(essential complexity)。
编程最好被理解为:在混乱的现实之上强加一种简化的模型——「抽象」——通过降低复杂性来让世界变得可理解。在现代高级编程语言中写代码,就像是站在一座由抽象概念堆砌而成的金字塔顶端:只需一行代码,就能在多个系统上触发数以百万计的底层操作。
AI 智能体的终极梦想是成群结队的 agent 接受任务,然后在无人监督的情况下自动实现它们。这解决的仅仅是偶然复杂性——编写代码本身那些繁琐、笨重的地方。
然而,即便更好的工具削弱了偶然复杂性,本质复杂性还在那儿。设计出正确、优雅、清晰且易于维护的抽象架构和系统,依然是一项无比艰巨的工作。LLM 那种花哨的「高级自动补全」,面对这种很难直接找到标准答案的复杂性,到底能发挥多大作用?
每一次抽象,同时也是一次遮蔽
James Scott 在《国家的视角》中描述了一个核心动机:通过抽象和分类,让人口和财产变得清晰可辨。能量化的东西,就能被改造。
例如,一个国家看待森林时,可能不再将其视为复杂的生态系统,而是仅仅通过「能用于造船的木材比例」来评估。这种视角随之促使国家采取行动——用单一树种的林场取代原生森林。一片森林被抽象成了一个「种植船桅的系统」。
作为程序员,为了对世界采取行动,我们必须减少现实数据中的混乱。每一个程序员和每一次系统设计,都在做出一种削足适履的强制妥协。但这个过程如此根深蒂固,以至于我们有时会忘记它同时也是一种人为的造作。
强制性别字段只接受「男」或「女」,并不能迫使性别的本质变得非黑即白。每一次抽象,同样也是一次遮蔽。
LLM 永远无法做到试图跳出来审视系统本身的元认知。对它们来说,模型本身就是现实。要求 LLM 去认识到它所看到的现实是有局限性的,就像是问金鱼水温怎么样一样。
摩擦是上天的恩赐
大语言模型驱动开发的魅力在于,它标榜能消除一切摩擦。但 Jacob 需要这种摩擦。
刚开始学习新语言或框架时,和摩擦搏斗的感觉糟透了。但在处理陌生代码库时,他需要预留几个小时逐字逐句地深度死磕,打开特定文件一行一行看,直到完全理解上下文和开发者做出选择的原因。
他需要的不仅是知道开发者做了什么选择,还需要知道他们为什么这么选。他在失败中学习,如果 LLM 把这部分苦差事替他干了,他将永远无法真正理解自己到底在做什么。
即使是在熟悉的语言环境里写自己的代码,他依然严重依赖摩擦作为重要线索。当写代码变得非常困难时,这说明在当前的架构下他正走向一条歧路。它在提醒他应该认真考虑重新设计。
而 LLM 驱动开发对待摩擦的态度,就是不管三七二十一,闭着眼睛直接写过去。它大概率能写出能跑通的代码,但它根本不知道自己为什么选择了那条路,它感受不到摩擦。
过程远比结果重要
不是每一个突发奇想的脑洞都必须变成现实产品。通常情况下,他从头脑风暴的乐趣中,以及为了证明「我没必要把这玩意做完」而学习新知识的过程中,获得的收获要多得多。
在艰难的时刻,写代码也一直是他的慰藉。编程就像是在解一个复杂的谜题,在黑暗的时期,它常常是避风港。它之所以管用,正是因为它是一项需要投入精力的工作。如果只盯着最终结果,这个疗愈的过程就会大打折扣。
结论
也许 LLM 革命最终会席卷他和他的饭碗,但在那之前,他可不想先把自己卷进坟墓里。
如果那一天真的到来,他希望我们能把软件开发重新建设成一种充满人性关怀的实践。