乐于分享
好东西不私藏

别把Vibe Coding当成软件工程:AI能写代码,但从不问你边界条件

别把Vibe Coding当成软件工程:AI能写代码,但从不问你边界条件

Vibe Coding能够生成代码。而工程设计则创造出系统。因为工程设计决定了那些存在于生成代码之外的元素,这些元素对于让解决方案在生产环境中长期运行至关重要。

这并不是对人工智能的反对意见。相反,这是一种支持工程技术的理由。

一个模型可以在几秒钟内生成一个登录系统。该系统不会考虑电子邮件是否应该保持唯一性。如果要求电子邮件必须保持唯一性,但生成的代码并没有强制执行这一规则,那么这个缺失的环节就可能导致生产环境中的系统故障。

大型语言模型无法看到那些用于保障软件安全的问题类别。

Vibe Coding能给你带来怎样的体验呢?

“氛围编码”指的是由非软件工程师通过提示来自动生成代码的过程。

氛围编码虽然能生成代码,但无法确保代码在生产环境中长期稳定运行所需的连贯性。

代码被部署到运行时生产环境中,从而构成了代码运行的上下文。大型语言模型无法了解运行中的系统是什么,因此无法提供具有系统感知能力的代码。

此外,大语言模型并未考虑业务需求,因此生成的代码中就不会包含与业务相关的地址信息。

如果没有这种业务和运行时环境的感知能力,那些被忽视的需求就会导致失败。

在任何代码出现之前,工程师们就已经做出了那些确保系统安全的决策。

主题
描述
问题的构建方式
明确问题的定义、用户的需求、约束条件以及预期的结果。
需求工程
激发相关行为、不变式、边界情况以及验收标准。
系统建模
状态模型、数据流、序列图、因果推理。
建筑设计
边界、责任、接口、故障模式、权衡取舍……
非功能需求的定义
性能、可靠性、安全性、合规性、可操作性、成本。
风险识别
未知因素、依赖关系、故障点以及相应的解决方案。
接口和合同设计
定义 API、模式以及行为保障条款。
规划与排序
将工作分解为易于处理且可实现的单元。

所谓的工程学究竟是什么?

当工程师编写代码时,他们所做的不仅仅是简单的输入文字。他们是在创造些什么啊:

  1. 消除歧义

  2. 划定界限

  3. 行为建模

  4. 确定系统在承受压力时的行为表现

这一切在甚至还没有一行代码存在的时候就已经开始了。这就是让系统保持连贯性的工作。

工程工作、编程活动都暂时中断了。

在人工智能语言模型中,这些工程领域的知识被忽略了。

区域
工程师们会做出怎样的决定呢
大型语言模型生成了什么?
不变量
永远不变的真理
这种代码假设一切都很正常
身份与独特性
什么使得一个实体“与另一个实体相同”?
将一切视为可互换性的代码
限制条件
系统绝对不允许出现这种情况。
那些在不注意的情况下违反界限的代码
故障模式
系统在承受压力时的表现如何
只在幸福路径下才有效的代码
连接与排序
究竟什么在何种情况下起作用,以及作用的顺序是什么。
完全忽略排序规则的代码
状态与转变
状态如何改变?是什么触发了这种改变?
一种能够在不遵循任何规则的情况下改变状态的代码
接口与合同
每个部分对其他部分有何承诺
那些能够展示模型所创造出的各种内容的代码
界限 系统并不具备的功能
不断扩展直至断裂的代码
错误处理
系统如何进行恢复
这种代码会在遇到第一个意外输入时立即崩溃。

这就是大型语言模型不会去关注的工作内容。如果不重视这类工作,那么生成的代码从长远来看是会出问题的。

一个系统不仅仅是其文本而已。

这一点非常重要,因为从长远来看,系统的安全性取决于:

  1. 始终成立的不变量

  2. 不可违反的约束条件

  3. 那些用于塑造业务逻辑和用户行为的耦合与排序规则

这个大型语言模型并不理解这一点。

为什么人工智能生成的代码会停滞不前,并导致系统变得脆弱?

人工智能生成的代码在长期使用过程中会陷入停滞,因为相关的工程决策并没有得到妥善执行。

当缺乏这样的决策时:

  • 各种特征相互碰撞并相互冲突

  • 系统状态变得难以预测

  • 这些部署变得脆弱且运行速度缓慢

  • 错误信息开始失去其意义了

  • 简单的功能越来越难以添加下去了。

对系统的信任崩溃了。

这个系统并非由你单独编写的代码所构成。它是那些代码在特定环境中协同运行的结果。

Demo很简单,而产品则不然。

给定一个简单的提示:

请编写 Python 代码来实现“将用户账户添加到网站上,以便人们能够登录”的功能。

该模型生成了一个小型的、可运行的基于 Flask 和 SQLite 的示例程序。对于演示来说,这已经足够了。不过,该模型并没有满足这五个要求:

  1. 电子邮件应该具有唯一性吗?

  2. 这些账户是否需要进行验证呢?

  3. 用户是否需要重置密码?

  4. 是否应该存在角色划分呢?

  5. 什么是安全模型?

解决方案并不是要编写更有效的提示。一个非软件工程师很可能不会意识到上述问题应该被提出来。

未经请求就提出的问题所带来的后果

如果代码不能确保电子邮件地址的唯一性,那么两个人就可以使用相同的电子邮件地址进行注册。如果他们在同一时间登录,那么用户的登录身份就会变得模糊不清。代码无法区分这两个人的区别。

当用户使用重复的电子邮件地址登录时,从数据库中查询该用户的注册信息会发现存在多个记录。因此,任何用于验证用户是否已注册的代码现在都必须妥善处理可能出现的多重结果情况。

由于缺乏独特的电子邮件地址,如果一个用户使用重复的电子邮件地址重置密码,那么所有使用相同电子邮件地址的用户都会面临密码被重置的问题。这种情况在生产环境中是无法容忍的。而且,如果有一个用户删除自己的账户,那么多个账户也会随之被删除。没有任何生产系统能够容忍这种情况的发生。

所谓“氛围编码”背后的误解

氛围编码假设人工智能具有类似工程师的“智能”。如果真是这样,那么遗漏的要求、模糊的规则以及隐藏的约束条件都将被自动发现。

但是,大型语言模型并不会做这些事情。它们不会针对你的系统进行推理分析;也不会构建关于你所在领域的模型来帮助理解你的系统。此外,它们也不会考虑变化的后果,或者确保不变性不被破坏。

大型语言模型能够生成可运行的代码,而无需进行任何必要的分析工作,这样就能确保这些代码能够在你的系统中安全、长期地运行。

因为生成的代码能够解决当前的问题,所以人们认为必要的分析已经完成了。他们相信,由于代码目前能够正常运行,因此最终的系统也会是稳定的。

在实际应用中,氛围编码方法会失败,因为那些被忽略的决策后来会以失败、不一致性和脆弱性等形式再次出现。这种模型无法预见那些需要被考虑的因素。使用氛围编码方式的人误以为模型已经考虑到了这些因素。

那么,应该做什么呢?

在生成任何代码之前,请先确定以下内容:

  1. 永远不变的真理/不变量

  2. 是什么让某事物成为“同一个实体”(身份规则)呢?

  3. 系统绝对不允许的情况(约束条件)

  4. 当系统出现故障时,其表现如何(故障模式)

大型语言模型能够生成代码。它们不会做出任何工程决策。这些代码最终会被保留下来。

总结

Vibe Coding技术可以让你获得一个Demo演示版本。这个演示版本是可以随意使用的。

要将那个演示版本转化为实际生产环境,就需要进行工程设计了。

‘码字派’译自:

https://phroneses.com/articles/build/notes/vibe-coding-is-not-engineering.html