为什么我不"氛围编程"

一份"简短的"个人陈述,解释为什么氛围编程从未让我作为一名开发者产生共鸣。

为什么我不"氛围编程"
AI模型价格对比 | AI工具导航 | ONNX模型库 | Vibe Coding教程 | Tripo 3D | Meshy AI | ElevenLabs | KlingAI | ArtSpace | Phot.AI | InVideo

最近网上有很多关于氛围编程(vibe coding)以及大语言模型(LLM)将如何彻底改变软件开发领域的讨论。每一个新模型都会将我们推入纯粹生产力的领域,以思维的速度交付软件,消除产品开发中的所有摩擦和开销。诸如此类。

也许吧。我只能相信你的说法。我不"氛围编程"。

如果它对你有效,那很好!在这篇文章中,我并不打算深入论证LLM的优点或缺陷,但它就是从未让我个人产生共鸣。这个页面是一份"简短的"个人陈述,解释其中的各种原因。

1、我是个吝啬鬼

我不是一个纯粹主义者。我尝试过在IDE中集成的LLM。它们对于一些足够简单容易描述但又烦人到不想自己做的任务很有用。例如,将一组方形图片调整为更小的尺寸。我可以去查看ImageMagick的命令行参数,但这是一个让AI来做的好选择。然后我尝试使用一个AI工具来分析我的项目代码和几个其他小任务,然后一切都尴尬地停了下来。系统告诉我刚用完额度,需要提供信用卡购买更多token才能继续。

你必须理解,我来自一个双方家族都是吝啬鬼的长久传统。几个世纪以来,我们一直在大西洋两岸精打细算、寻找便宜货。举个例子,我的一个远祖在菲利普国王战争中丧命,因为他离开安全堡垒去取撤离时落在房子里的奶酪。所以你必须相信我,为了能够思考而永久付费给一个服务的想法,在我看来既荒谬可笑又令人毛骨悚然,我甚至懒得给他们我的卡。我合上笔记本,卸载了IDE,甚至回到了使用Emacs。然后我意识到我甚至不再注意到有什么缺失了。

2、我老了

我老了这件事确实有帮助。我写代码已经很长时间了,尤其在一个把5年经验的开发者称为"高级工程师"的行业里。经验有时是对焦虑的一剂良药(只要不是对在把5年经验开发者称为高级工程师的行业中的年龄歧视感到焦虑),而AI的炒作确实让我想起了早期低代码和无代码工具的突破。我不怀疑AI可以成为开发者的有用工具。我知道有任务可以借助更好的工具得到帮助。但这些论点总是让我再次想到偶然复杂性和本质复杂性。

Fred Brooks在我自己还是年轻程序员的时候就老了。作为IBM System 360系列主机(及配套操作系统)的项目经理,他亲身经历了所有现在常见的软件项目出问题的方式当时还是新奇的。他在一本书《人月神话》(The Mythical Man-Month)中收集了这些观察,这本书今天仍应该是软件工程课程的必读之作。我的版本是一个较新的再版本,包含了一篇后来的文章"No Silver Bullet",Brooks在其中研究了新工具对开发者生产力的效果。要像程序员一样思考,你必须理解现实世界是复杂的。编程最好被理解为将简化表示——我们称之为抽象——强加在我们混乱的现实之上,通过降低复杂性使其变得可理解。这让我们能够将具体情境泛化为可以相互堆叠的层级。例如,将花生酱涂到面包上的具体动作可以被泛化为一个spread(substance)方法,可以接受花生黄油或奶油芝士作为参数。然后我们可以使用这些spread方法来创建更高级的函数如create_pbj()等等。在现代高级编程语言中编码就像站在抽象的金字塔顶端,一行代码可能触发数百万个跨系统的操作。这非常令人兴奋!

那么,如果我们能继续下去,把编程这个行为本身也抽象掉呢?这就是代理式AI的梦想,成群的代理可以被分配任务自主实施而无需监督。听起来很棒!但这解决的是Brooks所说的偶然复杂性,即写代码本身复杂的东西。在这篇文章写成之后,软件开发在对抗这类复杂性方面取得了巨大进步。我们不需要写低级机器码,可以使用现代动态解释型语言编译为汇编。我们不需要从头记住怎么写快速排序,只需要调用标准库中的sort方法。我们不需要从头构建整个Web应用程序,可以使用现有框架。如果我想重命名或重构一些代码,我的编辑器可以帮我做。AI似乎是最新的一轮迭代,一些编辑器已经用不可预测的AI代理替换了可预测的旧的重命名和重构工具。当然,这可能像是掷骰子,但致命失败到底有多常见?

然而,即使更好的工具减少了偶然复杂性,本质复杂性仍然存在。仍然有设计我们的抽象和系统的复杂工作——需要以优雅、清晰和可维护的方式来做。而这种复杂性不会消失。这类工作需要技能、经验和从系统失败中来之不易的智慧。我不确定LLM的华丽自动补全方式是否能很好地处理这类复杂性,这类问题通常不那么直截了当。也许通过提示,可以引导它朝向一个偏好方案,但在那种情况下,做引导的人还不如自己设计方案,因为LLM无法解释为什么它选择了某条路径。本质复杂性往往是奇怪、罕见和混乱的。也许我错了,模型在这些混乱情境中也在变好,但我发现它通常需要一种特定的思维方式和处理方法。幸运的是,我喜欢混乱的东西。

3、我热爱混乱

到目前为止我一直在谈论软件如何抽象过程,但我们也使用抽象的简化特性作为理解世界的工具。在经典著作《国家的视角》中,James Scott描述了后启蒙运动的核心项目是如何通过抽象和分类使其人口和财产变得可读的。测量即修改。例如,一个国家可能开始不把森林视为复杂生态系统,而是仅以可造船木材的百分比来评估。这种观点然后允许一个国家以替换这些森林为单一树种的纯林等方式采取行动。一片森林被抽象为一个生长船桅杆的系统。

这种方法创造了官僚机构和纸质表格,后者演变为Web表单和数据库。作为程序员,我们需要简化世界的混乱数据才能对其采取行动。我们期望日期是精确的。我们期望名字相对简单。我们期望数据在输入时是完整的且随时间保持一致。每个程序员和每个系统设计都是一系列普罗克儒斯忒斯式的选择——关于我们想反映在系统中的现实的哪些方面,以及哪些可以丢弃。我这样说不是在批评;这种方法是构建不会被无休止的特殊情况(我们称之为"边缘情况",因为它们本应是外围的罕见路径)所困的系统的唯一方式。但是,这个过程如此内化,以至于我们有时忘记了它也是人为的,尤其是在描述人的时候。强制性别字段只接受"男"或"女"并不能强迫性别本身是二元的。我们对种族的定义是不断变化的社会建构。我们的简化模型可能为我们提供洞察(自闭症诊断在过去20年增加了300%!)但无法捕获这些洞察背后的潜在因素(这可能只是自闭症定义变化和筛查增加的结果)。退一步来看任何模型是如何构建的以及它没有捕获什么类型的知识是很重要的。每个抽象也是一种遮蔽。作为一名数据记者,我学会了如何采访数据,以及如何对所有我发现答案可能误导人的方式保持高度严谨。偏执是数据记者最好的朋友,如果你想避免尴尬的更正。你需要能够思考不仅数据说了什么,还有它没有包含的所有内容。

不幸的是,这种元认知是LLM永远无法做到的。模型就是它们的现实。正如Robin Sloan在他引人入胜的文章"Are Language Models in Hell?"中简洁指出的那样,AI模型以 stripped-down 的方式构建和看待世界。你和我看文本时会看到它的上下文(文本格式和标题、作者简介、链接来源的网站),而LLM纯粹在一个字母世界中运作,仅此而已(技术上,它们接收子词token,这就是为什么早期模型无法计算strawberry中'r'的数量)。让LLM认识到它对现实的看法的局限性,就像问金鱼水怎么样

在写这一节的时候,我一直在想DOGE在社会保障管理局笨拙地寻找欺诈的尝试。在一个例子中,DOGE查看SSA数据库,发现有超过900万条出生日期在120多年前但没有记录死亡日期的记录。埃隆·马斯克宣称唯一的解释是有数以百万计的人欺诈领取福利。他在问题的原因和影响严重性上都错了。DOGE本可以质疑数据质量。他们本可以检查正在进行的付款。他们本可以请SSA的任何专家来解释。但他们直接照单全收数据并跳到了错误的结论,这个模式他们一遍又一遍地重复:

在随后的大量分析中,机构专家仔细记录了DOGE工作中的谬误,据《纽约时报》审查的文件和那些人士透露。
"这些付款是有效的,"代理副局长Sean Brune在一份检查其中一个问题的备忘录中写道。(财政部发言人拒绝置评。)
但据知情人士称,Russo没有回复置评请求,他表示DOGE不会信任职业公务员。相反,他坚持让Akash Bobba——一个21岁的曾在Palantir实习并成为DOGE首席程序员之一的人——进行他自己的分析。

DOGE团队以他们自己狂野的方式,为自己复刻了导致LLM出错的相同运行条件。他们拒绝考虑数据告诉他们之外的其他解释。他们不与圈外任何人交谈。他们抓住了一个简化的解释,因为它完全验证了他们对无能政府员工和到处都是猖獗欺诈的世界观而让他们感到满意。

这不是一个罕见的情况。我自己就非常害怕看起来像个蠢货,所以我永远不会把我的数据分析外包给LLM。但当然,很多人确实这样做了。我担心这个问题只会变得更糟。

4、摩擦是一种礼物

LLM驱动的开发的吸引力在于它应该消除摩擦。支持者讲述开发团队在一天内交付数十个功能的故事,使用多组代理在他们的指挥下自主工作在越来越奇怪的拓扑结构中。我理解,软件开发可能是乏味和令人沮丧的。能够以相对荒谬的速度大量产出代码并使用精致的产品而非原型,一定超级令人兴奋。

但我需要摩擦。

当我最初学习一门新语言或框架时,我需要与摩擦斗争才能完成最基本的任务。这很糟糕!当我与一个新的和不熟悉的代码仓库或数据源打交道时,我需要腾出数小时来仔细审查它。我经常发现自己做一个精读,调出特定文件逐行查看,直到我理解它们的上下文和开发者的选择。我知道我可以直接让LLM为我总结项目以节省时间,但我发现我需要这个过程来真正沉浸在代码中。我需要它不仅理解开发者做了什么选择,还有他们为什么这样做,以及这些选择如何反映他们使用的语言的约束或习惯用法。我通过失败来学习,如果LLM把这项工作从我这里拿走,我不会真正理解我在做什么。

即使在用熟悉的语言和我自己的代码工作时,我仍然严重依赖摩擦作为线索。当写代码变得困难时,这告诉我在当前架构上走错了方向,我应该认真考虑重新设计以使未来的增强更容易。当这种情况发生时,我通常会出去走走(或下线休息一天)给我的大脑空间,退后一步从新角度思考。这确实有效。我发现这些停顿如此有效,以至于即使在路径看似清晰时,我也会强迫自己这样做。在处理大型软件项目时,我会等到先写好一个架构决策记录描述我想做什么,然后才开始编写新功能的代码。这些文档迫使我捕获此时此刻的思考、对问题的假设以及方法的影响。有时候,它甚至让我意识到我太迷恋最初的想法,以至于没有看到它会走偏,它始终是给未来继承我工作的人捕获"他们当时在想什么"的好方式。

LLM驱动的方式对待摩擦就是直接编码绕过它而不重新思考任何东西。而LLM会配合。它可能会写出能工作的代码。性能指标没问题,测试会通过(尤其是如果测试也是LLM写的)。但它不知道为什么选择了那条路径。它感觉不到摩擦,也无法解释一种架构方案是否比另一种更清爽。如果编写提示的工程师缺乏判断什么方案好什么方案不好的洞察力,他们就会陷入一遍又一遍要求AI用编码绕过摩擦的动态中。这可能导致一团奇怪的抽象灌木丛,而留给未来团队的唯一设计文档是一个几年前用来给AI模型下指令的Markdown文件。祝你好运从中重建架构决策!值得注意的是,我见过的大多数氛围编程的成功故事都是由已经是他们要求LLM构建的领域的专家(因此能够指导其工作)的开发者完成的,或者是失败代价很低的情况。对于其他所有情况,我们只需要弄清楚如何知道该死的猫头鹰剩下的部分是否好用和安全。

如果我不提另一件让我烦恼的事——当LLM推广者将摩擦视为问题时——那将是我的疏忽。我在广告、现场演示和LinkedIn帖子中看到的大多数LLM营销描绘了一个孤独的工程师(或单个团队)英勇地使用LLM驱动的编码来快速推出某种应用或网站并迅速上线(我们的速度和KPI爆表了!)。但行业真正想让开发者使用LLM做工作,而工作中的摩擦通常是旨在防止缺陷甚至概念不佳的功能上线到生产环境的既定流程和实践。不可避免地,优先考虑LLM驱动速度的需求被转而针对人本身——其他工程师或产品管理、项目管理、测试、合规或设计方面的团队成员。因为那些角色也被视为摩擦。当我们能制作AI角色时,谁还需要用户研究?当我们有AI工具生成Web布局时,谁还需要设计?当我们是我们代理大军的指挥官时,谁还需要项目经理?如果我们不需要等待另一个开发者审查我们的Pull Request,只是自动合并通过了测试和扫描的代码呢?**如果我们不需要花任何工作时间与他人交谈,就可以纯粹活在编码的领域中呢?**但是,软件开发是一个协作过程,团队的每个成员都在帮助塑造一个优秀的产品。移除那些角色或用LLM化的幽灵替换它们当然会让团队移动得更快,但这不意味着他们交付的产品会更好。而且这个过程肯定会更加孤独。

6、我非常在意

也许我不使用LLM的最简单的原因是我太热爱编程了,不想把它交给一台机器。就像如果我是艺术家或音乐家我也不会求助于AI一样,编程是我表达创造力的一种方式,我不会放弃那种乐趣。虽然有时可能会极其令人沮丧,但将一个模糊的想法塑造为真实系统的过程有一种深刻的愉悦,尤其是当它涉及优雅的实现或有趣的问题时。有些晚上,我合上工作电脑打开个人电脑,投入到我想构建的某个新有趣的东西中。当我在团队中专业地构建软件时,那甚至更好!我热爱协作和共同塑造软件的过程,尤其是人们挺身而出主动承担问题的方式。我不认为当团队只是在接受提示的责任而LLM助手在做工作时,这种动态是相同的。或者LLM助手在替代团队的某些部分。

责任心很重要。在过去的几十年里,我在一些角色中培养了强烈的个人责任感。作为一名数据记者,代码中的错误可能导致尴尬的更正或毁灭性的诉讼。在公民技术领域,错误可能意味着提供服务和福利方面的灾难性失败,无论是针对整个脆弱群体还是单个个人。我不会说我从未犯过错,但我非常在乎做对,因为我在乎工作的使命。我很荣幸能与许多同样关心并希望为人们尽最大努力的人共事。LLM不会在意。当然,它可以出色地假装,但它仍然只是一个心智的模拟——将更可能相互关联的词语串联在一起。它不会因为错误而烦恼,也不会试图做得更好,因为它没有内在意识,更不用说良知了。它永远无法被追究责任,正因为如此,我永远无法将我的道德责任转交给它。

当LLM做得好时,它是一个将取代所有程序员的天才。当LLM删除了你所有的基础设施或对测试"撒谎"时,那就是你的错。毕竟,你只需要以正确的方式组织你的提示和工作流,就会让LLM给出正确的输出。哎呀,再试一次。然后再试一次。我读过的大部分LLM建议都强调你必须预先给出所有必要的指令、修正和附则,否则系统会做错事。这种思维模式与敏捷编程有很大不同,敏捷编程强调频繁的路线修正和反馈以及信任团队会做正确的事。相反,我们似乎正在退回到一种类似于1950年代早期计算机的分时模型的新使用模式。不同的是,这里不是走上去递交一沓穿孔卡片,孤独的程序员而是在向一台机器提交法律文书以转化为程序。

我开玩笑;这里不存在法律责任。考虑到涉及的人群构成相似,这可能并不令人惊讶,但LLM供应商正在重复与特斯拉相同的动态。新功能未经安全测试就推送给用户,而更奇怪的是,像特斯拉超级粉丝一样,LLM推广者经常将灾难性结果归咎于自己和他人,说用户在编写提示时本应该做得更好。我真的不确定该怎么看这个,但让我不安的是,技术正在标准化一种资本主义,其中消费者承担了更多风险,因为企业和政府都放弃了他们的责任。在飞镖杀死一个孩子后我们禁了飞镖,但聊天机器人驱使用户走向死亡和精神错乱却被接受为AI创新的价格。当氛围编程本身导致有人因系统故障而死亡,而不是死于尴尬时,情况会改变吗?

编码也是我困难时期的慰藉。有研究表明玩俄罗斯方块是避免PTSD的有效方法。理论是这种疗法之所以有效,是因为参与大脑中处理排列和旋转形状的部分会阻碍创伤记忆的形成。我很幸运没有患有PTSD(我也不是在轻视患有PTSD的人),但我确实能认同这个概念。编程感觉像一个复杂的拼图,有时是我黑暗时期的慰藉。正如上面的例子所暗示的,我对DOGE了解很多,因为过去一年我一直在构建和维护一个跟踪他们暴行的系统。不同于工作项目,这是一项将数据集组装起来为一个想要保持不透明的组织提供清晰度的练习。这是一项有回报的练习,也是我将对绝望的感受转化为我希望有用的东西的方式。这不是我唯一一次将代码作为处理悲伤的方式,它之所以有效是因为它就是工作,如果我只关注产品,这个过程就会大打折扣。

7、几个其他愚蠢的理由

这已经证明是一篇比我预期长得多的文章,特别是因为它最初只是Bluesky上的几篇短文。在结束之前,再写几个快速的理由!

首先,我绝对讨厌AI聊天机器人默认采用的虚伪语气。作为一个在东海岸城市长大的人,当有人在不认识我的情况下对我异常好时,我会非常怀疑,因为这通常意味着他们要么要开始一场骗局,要么要向我传教。读LLM聊天记录让我起鸡皮疙瘩。是的,我知道我可以让LLM采用完全不同的语气,但不知为何这让这个想法感觉更糟了。

像许多开发者一样,我有一整个文件夹的未完成的业余项目草稿。例如,有一个是我想写一个Spelling Bee的克隆版,但要用Clojurescript写,这样我就可以使用Blabrecs代码来生成非词并让它超级令人沮丧。好吧,我想那可能只是对我来说好笑。你得在场才行。从LLM的角度来看,这些是失败的文件夹,我确实可以使用LLM每天做一个应用或任何我想要的挑战。然而,过程远比产品重要(再说一次!)。不是每个异想天开都需要变成现实。通常,我从头脑风暴的乐趣中学到的比从学习到足够知道不需要继续完成这个项目中学到的更多。有时候很容易忘记这一点。

这篇文章本来不打算讨论在工作中使用LLM的道德问题。不是因为我不在乎,而是因为许多其他人已经比我更有效地撰写了这项技术的令人不安的影响。在这个LLM向学校投弹或按需生成儿童色情内容的时刻,我真的不想使用它们。而且我觉得完全不提这个方面也不舒服。也许资本主义下确实没有道德的消费,但如果我连试都不试,那我就该死。我们无法用让如此多人受苦的工具来建设一个更好的世界。

奇怪的是,似乎没有人比LLM推广者更痛苦。如果开发者把他们新获得的生产力提升用来过那个十年前书呆子们假装崇拜的每周4小时工作制,我可能会更被说服。但讽刺的是,似乎硅谷的许多人正在把工作外包给AI代理,然后用新获得的空闲时间做更多工作。他们没有用时间来放松、创作或享受,而是在拥抱996工作制和一种会让弗雷德里克·泰勒都恐惧地脸色发白的超量化工作场所。LLM革命最终可能会波及我和我的工作,但我宁愿不先把自己工作到坟墓里。

8、现在怎么办?

我假装不知道未来。也许技术会进步到这样一个程度,我会后悔自己缺乏经验和熟悉度。或者也许它会停滞,整个金融纸牌屋会轰然倒塌。如果发生这种情况,我希望我们能将软件开发重建为建设一个更美好世界的人性化实践,一次一行代码。


原文链接:Why I Don't Vibe Code

汇智网翻译整理,转载请标明出处