深度讨论 AI 辅助编程导致的"代码感觉"现象,指出盲目依赖 AI 补全带来的技术债积累与质量下滑。
无论是在阅读本文之前还是之后,你也可以收听播客,了解关于这个话题的更多见解:
🎙️ 在 Spotify 上收听:
事先声明一下,正如我在标题中提到的,我非常支持 AI。我认为它是计算机科学演进过程中顺理成章的下一步。我们始终致力于构建更智能的系统,并尽可能实现自动化——这是我们天性的一部分。人类渴望便利、效率和简单。我们越能轻松地创建和管理复杂系统,就越好,这完全没有任何问题。
大语言模型(LLM)已经成为这一进程的基石。如今,几乎每一位软件工程师都在以某种方式使用它们(或者至少绝大多数人如此)。我的职业软件工程生涯始于遥远的 2017 年,当时我受聘成为一名初级软件工程师。那时的环境截然不同。为了找到一个有时几乎无从寻觅的解决方案,花上一整天把互联网翻个底朝天并不罕见。如果当时我能使用 ChatGPT,我本可以在 10 分钟内生成一个解决方案,对其进行分析,再根据自己的具体用例加以调整。
当时,我们能用的最佳资源就是 StackOverflow。老实说,它常常给人一种互联网最恶劣社区之一的感觉。我记得自己曾在一个鲜有人使用的平台上工作,那个平台的文档糟糕透顶,社区支持也几乎不存在。走投无路之下,我决定在 StackOverflow 上发布一个问题。你知道后来发生了什么吗?什么都没有。没有回复,没有赞成票,也没有反对票,只有一片沉默。我又发布了几个问题(哦,我甚至还因此获得了一枚徽章——真不是开玩笑),终于,有个人不知出于什么原因给我的问题投了反对票,导致我的账户被锁定。没错,就这么简单。账户被锁了,不是因为发送垃圾内容或恶意挑衅,而是因为我提出了一些合理的问题,只是没有人知道该如何回答(这可真是开启软件工程职业生涯的绝佳方式,对吧?)。如果当时拥有如今这样的 AI 工具,我职业生涯的那个阶段就不会如此痛苦。我本可以找到那些答案,而不必让自己承受巨大压力,也不必在晚上 10 点回家的路上,坐在一辆冰冷、空荡的公交车里,怀疑自己的职业选择。
我分享这一切,是为了说明一件事:我非常支持 AI、机器学习、深度学习以及整个相关领域。就连我的博士研究也聚焦于数据挖掘和 AI。我曾与一些对这项技术持怀疑态度的人进行过专业讨论。坦率地说,我无法理解这种敌意。我为什么要拒绝一个能帮助我更聪明地工作、更快速地学习并提高生产力的工具?
但是,这并不意味着我们应该以最糟糕的方式利用任何工具的潜力。某个东西功能强大,并不意味着我们就该肆无忌惮地使用它。包括 AI 在内的工具,应该协助我们,而不是取代我们。这一区别至关重要。
这也引出了我最核心的担忧:凭感觉编程。
我对这种趋势存在一些根本性的意见。它就是让我感觉不对劲。事实上,它在太多层面上都显得不妥,以至于我甚至可能无法在一篇文章里把所有问题都讲清楚。不过,我们先从最基础、最根本的问题谈起,再逐步深入到更复杂的问题。
即使凭感觉编程背后的概念很棒,这个名字依然是最糟糕的选择。我认为这个名称根本没有经过充分推敲。让我们先分别定义这个术语的两个组成部分,再对它进行拆解:
氛围(Vibe):一个地方、情境、人物等所具有的气氛,以及它们带给你的感受。(dictionary.cambridge.org)
编程(Coding):编写一系列计算机可以遵循并用来执行任务的指令,这些指令被称为程序。它涉及通过使用一种或多种编程语言编写代码,设计并实现算法,也就是对操作过程的逐步说明。(wikipedia.org)
定义完这两个词之后,我只剩下两个相当愚蠢但很诚实的问题:
这里面所谓的“氛围”究竟在哪里?
这里面所谓的“编程”究竟在哪里?
我认为它恰恰与这两者完全相反。
在我看来,编程中的美好氛围来自学习——真正的学习。当你深入研究一种新语言、试验一个新库、探索一种新的设计模式或架构风格时,这种氛围就会出现。你尝试理解它、把玩它、将它集成到项目中,甚至可能为了看看它究竟如何运作,而从头启动一个全新的项目。
接着,你不可避免地会失败。你会碰壁。因为如果没有碰壁,就说明你其实还不够努力。你会花上几个小时弄清楚究竟哪里出了问题,而在这个过程中,你又会学到更多。最终,一切豁然开朗。你把事情做对了。你甚至可能会把学到的东西分享给其他人,就这样,你成长了。相比刚开始时,你已经成为了一名更优秀的工程师。
这才是氛围。整个过程中的好奇、失败、坚持、突破和情绪——正是这些赋予了编程活力与意义。
我曾花费无数个小时修复顽固的 bug,而且不,那一刻并不总是有趣。有时它令人沮丧、筋疲力尽,甚至几乎让人失去信心。但在我找到解决方案的那一瞬间,一切又都亮了起来。突然之间,世界仿佛恢复了色彩。我甚至能准确回忆起当时听的音乐、具体时间、天气如何、喝的是什么咖啡——每一个微小的细节。
后来,当我再次听到同样的音乐时,一切都会重新涌现。我仿佛又回到了那里,再次经历那些氛围。正是这段情绪上的旅程和那种获得回报的感觉,让真正的编程对我而言意义非凡。这才是真正的氛围。它不只关乎结果,更关乎那个促使你成长的过程。
刚开始职业生涯时,我完全专注于终点——最终结果、产出、“最终产品”。但天哪,我错得太离谱了。随着时间推移,我意识到过程才是真正重要的东西。
根本不存在最终的终点,只有持续前进道路上的一个个里程碑。而这条道路充满了挑战、教训,以及最重要的——氛围。
这恰恰是我最初成为软件工程师的原因。早在高中时,我就常常想象未来的自己能够深入理解复杂系统,能够凭借一套精准、来之不易的技能解决问题。这样的形象激励着我,也正是它让这份工作如此酷。
对我来说,这才是真正的氛围——编程时经历的那场情绪过山车。高峰与低谷,沮丧与突破。当你沉浸在问题中,慢慢依靠自己把事情弄明白时,情绪也随之不断变化。我想不出还有什么氛围能比这更好了。
我无法理解,怎么会有人把这样一个过程称为“凭感觉”:你只需要告诉一个 LLM 要做什么,它便直接为你生成代码。我并不是说这件事一无是处,稍后我还会谈到这一点,但至少在短期内,我无法想象自己会这样做。
让我们想象一下,在 AI 尚未发展到今天这种水平、仍然只存在于科幻作品中的 20 世纪 80 年代,凭感觉编程会是什么样子。
你是一名计算机科学专业的学生,正在想办法支付大学学费。你打开当地的报纸,发现了一则不同寻常的招聘启事:
招聘:凭感觉程序员
80sCoolVibes, Inc.
加利福尼亚州威尼斯海滩——成立于 1981 年
你是否正在寻找一份完全不需要任何实际编程知识的编程工作?
你能否用浅显的英语把事情解释清楚?
那么恭喜你——这份工作正适合你。
……以及剩余文本……
薪水并不高,但刚好足以支付你的学费。于是你投递了申请,而令你意外的是,你得到了这份工作。
这是你上班的第一天,你兴奋不已。你终于在历史上最具标志性的年代之一——20 世纪 80 年代——踏入了科技世界。计算机产业正在腾飞,未来正在被实时书写,而你也想成为其中的一员。
在办公室里,有一个叫 Marcus 的人——公司里唯一真正的软件工程师。他很聪明,代码写得也非常出色。但问题在于:他不做决策,也不设计系统。他只会坐在那里,等着某个人——也就是你——告诉他要构建什么。
你的工作是什么?告诉 Marcus 你想要什么。等他把它构建出来。审查结果。告诉他需要调整哪些地方。然后不断重复。
渐渐地,你开始意识到,有些事情不太对劲。
你正身处科技史上最强调“感觉”的时代。你原本想成为一名构建者、创新者,成为一个能够从内到外理解系统的人。但现在,你却只是在隔着键盘玩传话游戏。你并没有亲自编写代码,只是在审批代码、引导代码、通过提示词生成代码。
你不是程序员。你只是那个告诉代码生成器该做什么的人——无论这个生成器是人还是机器,其核心概念都是一样的。
我不知道你会怎么想,但如果是我,到了那一刻,我一定会开始认真质疑自己当初的决定和求职能力;或者,我会直接怀疑自己是不是成了新版《黑镜》某一集里的角色——而这听起来甚至更加可怕。
编程语言每天都在变得越来越平易近人。现代语言往往会相互借鉴最优秀的理念,努力让语法变得更简洁、更直观、更容易学习。当然,凡事总有例外,但总体来说,如果你正在设计一门希望能够适应未来并被广泛采用的语言,那么拥抱这些进步已经不再是可选项,而是必需品。
你可能会反驳说,PHP 这样的语言仍然被广泛使用,或者几乎整个美国银行系统都运行在 COBOL 之上。你说得没错,但它们完全属于另一个类别。我说的不是那些曾被用于构建庞大遗留系统的语言——这些系统几乎不可能重写,或者重写的风险极高。
以航空业为例。如果飞机的机载软件是用 C 编写的,没有人会想把它迁移到某种“更好用”的语言上,这完全有充分的理由。你不会希望飞机在 35,000 英尺的高空突然出现意料之外的 Bug。同样,如果某个银行核心系统已经在 COBOL 上运行了几十年,通常最好不要动它。系统规模如此庞大、重要性如此之高,以至于哪怕一个很小的改动,也可能造成严重的中断。在这些情况下,稳定性永远比优雅更重要。
但对于刚刚开始设计或正在努力获得市场认可的新项目,情况就完全不同了。如果你的语言不容易阅读、编写和推理,同时又没有提供其他突破性的优势,那么它将很难获得广泛采用。如今,开发者体验比以往任何时候都更加重要。
我想表达的重点是,现代高级编程语言已经变得非常直观。以 Python 为例,你几乎可以像阅读普通英语一样阅读它,而这是一件好事。任何人在学习几分钟基础知识后,都可以用 Python 构建一个简单的计算器应用。这就是易用语法的力量:它让人们能够亲手构建,而不只是输入提示词。
你不需要让 AI 模型替你编写整个应用。你可以用自己的方式亲自完成,同时仍然保持完全的控制权。你是飞行员——坐在左侧驾驶位,双手握着驾驶盘。当你走进死胡同,或者想不起某段语法时,再去求助你的副驾驶(AI)。你获取信息,对其进行完善,根据自己的具体需求加以调整,然后将其集成到代码库中。你不是在盲目复制,飞机仍然由你驾驶。
凭感觉编程所做的,是在一个已经高度抽象的概念之上,再引入一层抽象;但这一次,这层抽象的可预测性要低得多。像 C# 这样的编程语言,本身已经是与机器码隔离的高级抽象,但它们仍然精确且可靠。如果你写出的内容违反了 C# 的语法规则,代码就无法编译。事情就是这么简单。而且,如果你确实懂得如何使用 C# 编程,你就拥有控制权。你可以记录错误、调试关键代码段、分析性能,并编写简洁且易于维护的代码。换句话说,你就是飞行员。你理解系统底层正在做什么。即便存在抽象,它依然是一致且确定的。
但凭感觉编程改变了这一点。它引入的抽象并不像托管代码带来的抽象,而是模糊得多。例如,对于同一段源代码,C# 编译器始终会生成相同的中间语言和字节码。另一方面,AI 工具可能会因为上下文、随机性或提示词措辞不同,而针对同一个请求生成完全不同的结果。这让这层新的抽象远没有那么可靠——至少目前如此。
我不确定 AI 的未来会是什么样,也不会假装自己能够预测它。但就目前而言,如果你在编程时过度信任 AI,事情可能会在极短时间内变得非常糟糕。
需要说明的是,我说的不是这样一种工作流:你向 AI 寻求帮助,审查它的输出,对其进行调整,然后经过深思熟虑后将其集成到项目中。这样做没有问题,而且很有成效。这正是一名优秀副驾驶应该发挥的作用。我说的是彻底的凭感觉编程:你输入一个模糊的提示词,甚至完全不查看代码,就直接把它发布到生产环境。现在已经有大量案例证明,这种做法可能造成多么严重的后果。
以那个如今已经臭名昭著、使用 Cursor 构建的 SaaS 项目为例。作者曾自豪地发推称,该项目“没有一行手写代码”。两天后呢?他再次发推,但这一次说的是 API 密钥额度被耗尽、用户绕过订阅限制,以及各种随机垃圾数据被写入数据库。用他们自己的话说,就是“各种莫名其妙的事情都在发生”。
这不是软件工程。这是在掷骰子,然后把它称作开发。
我仍然真心同情那个人。你以为自己构建出了了不起的东西,最后却只能眼睁睁看着别人滥用它、钻尽每一个漏洞,并榨干它的全部价值,这种感受令人无比沮丧。但有件事我们都必须接受:可持续的成功没有捷径可走。
即使你侥幸在没有付出太多努力的情况下迅速取得了某种成果,这些捷径通常也会留下裂缝。而裂缝很容易被人利用。
人们会注意到你为了成功而走过的捷径,其中有些人会故意在相同的道路上布下陷阱,只等着某个人失足。
没错,利用他人的失败牟利是不对的。但世界并不公平,互联网更不公平。总有人在积极寻找可以利用的弱点。因此,无论你是在构建产品、创业,还是学习一项新技能,最好的心态都很简单:“抱最好的希望,做最坏的打算。”这不是悲观,而是准备。
在了解了这个通过凭感觉编程构建的 SaaS 案例之后,我们再简要谈谈这种方式带来的安全风险。
为公司构建软件时,安全不是可选项,而是最高优先级之一。你不会希望自己的秘密 API 密钥出现在 GitHub 仓库里,更不希望它们被公开暴露。凭据、令牌和敏感配置都应该得到安全存储、加密,并被赋予适当的权限范围。
但 AI 工具并不能天然理解你的应用中哪些内容属于敏感信息。它们不知道哪些变量是机密信息、哪些数据绝不能写入日志,也不知道哪些安全最佳实践适用于你的具体用例。当然,你可能知道这些,并且会告诉 AI,因为你是一名经验丰富的开发者,过去遇到过这些问题。但那些没有经验的人呢?那些把 AI 当作辅助工具、却从未从零开始构建过安全系统的人呢?他们可能会在毫不知情的情况下,把机密信息提交到版本控制系统中,以明文形式记录用户密码,暴露内部端点,或者制造巨大的攻击面——仅仅因为代码“看起来没问题”。
这正是凭感觉编程真正的危险所在:它可能直接跳过那些你甚至不知道自己本应关注的部分。
软件可能会以极快的速度变得非常复杂,尤其是在企业环境中。如果你的应用完全由 AI 模型构建,而你最终在尝试修改某个极其具体的内容时碰了壁,那么 AI 很可能也帮不上忙。有一次,我在定制自己的个人 .NET 项目模板应用。我需要以一种非常具体的方式调整 .NET 项目模板中的 template.json 文件,但即使经过多次尝试,AI 仍然无法生成可用的解决方案。最后,我在一个 GitHub 讨论帖的深处找到了修复方法。
到那时,你就需要一名真正的软件工程师——一个能够阅读、理解代码,并对其进行精准修改的人。甚至还需要一个知道如何找到 AI 无法找到的解决方案的人。但问题在于:这个人在处理 AI 生成的代码时,很可能不会有什么愉快的体验。事实上,仅仅为了添加一项功能、修复一个 bug,甚至只是理解现有的代码结构,都可能需要付出巨大的精力。至于从头重构整个代码库?那可能会是一场噩梦。
凭感觉编程的构建速度很快,但它也可能悄无声息、难以察觉且迅速地积累巨额技术债务。
当被问及人们对 ChatGPT 说“请”和“谢谢”之类的话会让 OpenAI 损失多少钱时,Sam Altman 曾在 X 上给出过一句广为流传的回答:“几千万美元,但花得值,谁知道呢。”
而这还仅仅是礼貌性回复,例如“没问题”或“不客气”。如果这些微不足道的互动都要耗费数千万美元,那么我们就能大致了解其背后究竟消耗了多少能源。
现在把视野拉远,看看仅 ChatGPT 一款产品的整体规模:
约 1.22 亿日活跃用户
约 1.22 亿日活跃用户
约 4 亿周活跃用户
约 4 亿周活跃用户
每天处理约 10 亿条消息
每天处理约 10 亿条消息
每天消耗约 1 GWh 电力,大致相当于为 33,000 个美国家庭提供一天的用电量
每天消耗约 1 GWh 电力,大致相当于为 33,000 个美国家庭提供一天的用电量
对于仅仅一款产品而言,这是一个惊人的能源消耗量。
软件工程的核心原则之一始终是效率——不仅是性能或架构方面的效率,也包括我们使用资源的方式。然而,在凭感觉编程中,我们做的却恰恰相反:我们正在将能源消耗推向前所未有的水平。偶尔在静态网页上查找一些信息是一回事,让 AI 模型整天生成、重新生成并改写整个代码库,则完全是另一回事。
如今,全球有数千万名软件工程师。而凭感觉编程从本质上来说,比真正的软件工程更容易。因此,我们不难想象这样一个未来:凭感觉编程者的数量将远远超过传统开发者。
如果这种情况真的发生,软件开发的能源足迹可能会急剧膨胀,随之带来碳排放的大幅增长,以及一场我们尚未做好准备应对的可持续性危机。
这已经不再只是一个技术问题,也是一个环境问题——而且我们迟早必须面对它。
那么,凭感觉编程究竟适合用在什么地方?
首先,快速生成样板项目就是一个很好的应用场景。AI 工具能够大幅简化这一过程,尤其是在你尚未建立模板系统的情况下。当然,如果你已经投入时间构建了自己的自定义模板,那么生成样板代码可能只需运行一条 CLI 命令。但如果你没有呢?AI 正好可以很好地填补这一空白。
凭感觉编程另一个真正大放异彩的领域,是为客户创建演示项目。有时,你并不需要一款功能完整的产品,只需要一些可以展示的东西:一个可运行的概念,或一个粗略的概念验证。与其花费数小时拼凑一个用完即弃的演示,不如让 AI 来处理。快速构建、展示你的构想,然后将其丢弃,或者把它保留下来,作为日后进一步完善的原型。
这种方式对于非技术利益相关者也可能非常有用,例如项目经理或产品负责人。借助 AI 工具,他们可以快速构建原型,以直观且可操作的方式向开发团队传达自己的构想。他们不必再编写冗长的需求文档,而是可以生成心目中产品的粗略版本,从而更清楚地表达自己想要实现的目标。这种快速原型设计能够减少误解,帮助开发者更快、更准确地交付符合预期的成果。
它还可以在新开发者入门或帮助人们探索这一领域时发挥重要作用。通过试验 AI 生成的代码,初学者可以初步了解不同领域中的编程是什么样子。他们可以生成 Web 应用、桌面工具、移动应用和游戏,并从中发现真正令自己兴奋的方向。虽然它无法替代深入学习和真实经验,但凭感觉编程可以成为通往真正软件工程的一扇大门。
凭感觉编程本身并不坏,但如果用错了场景,它也可能让人一步步滑向危险境地。就像生活中的几乎所有事物一样,它只是一种工具。而任何工具都既可能为你所用,也可能成为你的负担。一切都取决于你如何使用它,以及在什么时候使用它。
我近期会开始凭感觉编程吗?大概不会。我仍然想做驾驶舱里的主驾驶,完全掌控局面,充分了解底层正在发生什么。现在还不是我与 AI 交换座位、把驾驶杆交给 AI,让自己退居副驾驶的时候。
但一旦它成为行业标准,我肯定会转向这种方式。——从长远来看,我仍然相信这就是未来。
如果其他人能从这种工作流中获得活力与创造力呢?如果他们热衷于用这种方式构建产品呢?那就尽管去做吧。没有人有权阻止他人探索新的工作流或工具。我唯一的期望,是他们在开始时能充分了解实际情况,清醒地认识其中的风险与局限,尤其是在他们尚不具备发现危险信号所需的技术经验时。
归根结底,我们都是同一个开发者社区的一员。无论你属于守旧派还是新潮派,无论你亲手编写代码还是通过语音提示词来构建,最重要的是我们能够尊重彼此选择的道路,并互相帮助、共同成长。
这才是真正的感觉!
想了解幕后视角?请查看后续文章:
Behind the Mic: AI and the Vibe Coding Podcast Retrospective
部分评论可能仅对已登录的访客可见。登录后即可查看全部评论。
如需采取进一步措施,你可以考虑屏蔽此人和/或举报滥用行为。