来源:Vibe Coding Is Not Engineering - Phroneses
作者:Jh Evans
说明:本文为 AIGC 辅助翻译版本,已进行简单人工校对,具体细节请自行甄别。
Vibe Coding 不是工程
Vibe coding 能产出代码。工程则产出系统,因为工程会定义那些位于生成代码之外、却能让解决方案长期在生产环境中持续运行的要素。
这并不是反对 AI 的论证,而是支持工程的论证。
模型可以在几秒钟内生成一个登录系统。但它不会主动询问:邮箱是否应该唯一?如果邮箱应该唯一,而生成的代码没有强制保证这一点,那么这一个缺失的需求就可能导致生产环境停机。
LLM 看不见那些让软件保持安全的问题类别。
Vibe coding 能给你什么
这里所说的 vibe coding,指的是由非软件工程师通过提示词自动生成代码。
Vibe coding 会给你代码,但不会给你长期在生产环境中运行代码所需的一致性。
代码会被部署到运行时生产系统中,而这个系统构成了代码运行时的上下文。大型语言模型无法知道这个正在运行的系统究竟是什么,因此也无法提供具备系统感知能力的代码。此外,LLM 看不到业务需求,所以生成的代码也不会覆盖这些需求。
缺少业务与运行时上下文意识,被遗漏的需求就会造成失败。
在任何代码出现之前,工程师已经在做那些让系统保持安全的决策。
| 主题 | 描述 |
|---|---|
| 问题界定 | 定义问题、用户、约束和预期结果。 |
| 需求工程 | 引出行为、不变量、边界情况和验收标准。 |
| 系统建模 | 状态模型、数据流、序列图与因果推理。 |
| 架构设计 | 边界、职责、接口、故障模式与权衡。 |
| 非功能需求定义 | 性能、可靠性、安全、合规、可运维性与成本。 |
| 风险识别 | 未知项、依赖、故障点与缓解措施。 |
| 接口与契约设计 | 定义 API、模式与行为保证。 |
| 计划与排序 | 将工作拆分为连贯且可交付的单元。 |
工程实际上是什么
当工程师写代码时,他们并不只是在敲字。他们在:
- 消除歧义;
- 定义边界;
- 建模行为;
- 决定系统在压力下如何表现。
其中大多数工作发生在第一行代码出现之前。这些工作让系统保持连贯。
Vibe coding 跳过的工程工作
LLM 会跳过工程学科中的这些部分。
| 领域 | 工程师决定什么 | LLM 生成什么 |
|---|---|---|
| 不变量 | 什么必须始终为真 | 假设一切正常的代码 |
| 身份与唯一性 | 什么让一个实体被视为“同一个东西” | 把所有东西都当作可互换对象的代码 |
| 约束 | 系统绝不能允许什么 | 没有意识到越界的代码 |
| 故障模式 | 系统在压力下如何表现 | 只在顺利路径上有效的代码 |
| 耦合与顺序 | 什么依赖什么,以及以什么顺序依赖 | 完全忽略顺序的代码 |
| 状态与转换 | 状态如何改变,以及由什么触发 | 没有规则地修改状态的代码 |
| 接口与契约 | 每个部分向系统其余部分承诺什么 | 暴露模型随手编出的接口的代码 |
| 边界 | 系统不做什么 | 不断扩张直到崩溃的代码 |
| 错误处理 | 系统如何恢复 | 遇到第一个意外输入就崩溃的代码 |
这些工作是 LLM 不会主动询问的。若不关注这些工作,生成的代码长期来看就会失败。
系统不只是文本
这一点很重要,因为从长期看,系统安全依赖于:
- 必须始终成立的不变量;
- 不能被违反的约束;
- 塑造业务逻辑和用户行为的耦合与顺序规则。
LLM 并不理解这些。
为什么 AI 生成的代码会停滞并制造脆弱性
AI 生成的代码之所以长期会停滞,是因为必要的工程决策没有被做出。
当这些决策缺失时:
- 功能彼此冲突并相互破坏;
- 系统状态变得不可预测;
- 部署变得脆弱而缓慢;
- 错误信息开始失去意义;
- 添加简单功能也变得越来越困难。
人们对系统的信心会崩塌。
系统不是你生成出来的代码。系统是这些代码在某个环境中运行时形成的组合体。
演示很容易,产品并不容易
给定一个简单提示词:
编写 Python 代码:“给网站添加用户账户,让人们能够登录。”
模型生成了一个小型、可运行的 Flask 和 SQLite 示例。作为演示,这可以接受;但它没有询问以下五个需求:
- 邮箱是否应该唯一?
- 账户是否应该经过验证?
- 用户是否应该能够重置密码?
- 是否应该存在角色?
- 安全模型是什么?
解决办法并不是写出更好的提示词。非软件工程师很可能并不知道上面这些问题本来就应该被提出。
未被提出的问题会带来什么后果
如果代码没有确保邮箱唯一,那么两个人就可以用同一个邮箱注册。如果他们同时登录,用户登录身份就会变得含糊不清。代码无法区分他们。
当用户使用重复邮箱登录时,从数据库中检查该用户注册信息会返回多个值。任何用于检查注册用户的代码,都必须安全处理可能出现多个结果的情况。
缺少对邮箱唯一性的考虑,意味着如果某个使用重复邮箱的用户重置密码,vibe coding 生成的实现可能会重置所有共享该邮箱用户的密码。这在生产环境中是不可接受的。如果其中一个用户删除账户,多个账户也可能被删除。没有任何生产系统能容忍这种情况。
Vibe coding 背后的误解
Vibe coding 假设 AI 拥有类似工程师的“智能”。如果这是真的,缺失需求、含糊规则和隐藏约束就会被自动捕获。
但 LLM 不会做这些事。它们不会围绕你的系统进行推理。它们不会建立领域模型来帮助推理你的系统。它们不会追踪变更的后果,也不会确保不变量不被破坏。
LLM 会生成能够运行的代码,却不会完成为了让这些代码在你的系统中长期、安全使用所必需的分析。
因为生成的代码解决了眼前问题,人们便以为必要分析已经完成。他们会假设结果系统是连贯的,只因为当前代码看起来能正常执行。
Vibe coding 在生产环境中失败,是因为那些缺失的决策会在之后以故障、不一致和脆弱性的形式重新出现。模型看不到本该被询问的那类问题,而进行 vibe coding 的人则以为模型已经看到了。
应该怎么做
在生成任何代码之前,先决定:
- 什么必须始终为真,即不变量;
- 什么让某个东西成为“同一个”实体,即身份规则;
- 系统绝不能允许什么,即约束;
- 当事情出错时,系统如何表现,即故障模式。
LLM 生成代码。它们不会做工程决策。这项工作仍然存在。
底线
Vibe coding 能给你一个演示,而这个演示是一次性的。
要把这个演示推进到生产环境,需要工程。
相关阅读
- The Big AI Gains Come From Teams, Not Individuals
- Agents Cannot Maintain Systems
- What Software Engineers Need to Know About LLMs
- Latency Is Architectural
![[转译] Vibe Coding 不是工程](https://i-cdn.frytea.com/2026/04/30/d17a529dbb0ce3cde8989e62631efa3e.jpg)