标签归档:软件工程

[转译] Vibe Coding 不是工程

来源: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

【翻译】Programming Still Sucks:编程依然很糟糕

前言

文章来源:stvn.sh / Writing

原文作者:Jerome Choo

原文标题:Programming Still Sucks

原文链接:https://www.stvn.sh/writing/programming-still-sucks-fqffhyp

本文为全文翻译,译文由 AI 辅助整理,若有理解偏差欢迎指正。


2026 年 4 月 19 日 · 阅读约 8 分钟

编程依然很糟糕

编程 · 领导力 · AI

抱歉,Peter。

——

我在一个生日派对上。来的人大多数也都在科技行业工作,但这种场合里总会有那么一个“有正经工作的人”。你知道的,那种做实体工作的,真的在造某些人们需要的东西的人。而这个人总会问出某种变体的同一个问题:你不担心 AI 会抢走你的工作吗?我朝四周瞥了一眼,看见几张脸微微转过来,轻轻翻了个白眼,然后又回到他们原本的聊天里。对,又是这个问题。

他们有个外甥在帮人搭 Shopify 商店。他们听不懂那孩子嘴里一半的词,但他说自己麻烦大了,而且科技行业里所有人都一样。他的外甥是不是得去学一门“手艺”?我们是不是都得这样?

如果酒喝得够多,我就会认真回答,因为那时候我已经不在乎别人觉得我说的话有没有意思、是不是真的了。但通常我只会叹口气,说一句:“当然,会有一点。我们大多数人都会。不担心才奇怪吧,对吧?”他们点点头,然后就转去聊个更轻松的话题,比如我们会不会去核平伊朗。

但事实是,在科技行业工作一直都很糟糕,而且从来都不是他们以为的那个样子。

有些人以为,我的工作就是坐在一张干净的桌子前,待在一间角落办公室里,外面是开放式办公区,摆满长桌,上头放着一排排 MacBook 或 ThinkPad。在我的角落办公室里,我制定完美的计划,我那群完美的员工会为我鼓掌喝彩。没有任何东西能逃过我的目光,每一个决定都由我完美地做出,每一分钱、每一分钟都被精确记录。

当掌声散去,我的员工——或者叫下属,或者在我心情好的时候叫“我的团队”——就开始疯狂敲键盘。敲啊敲,敲啊敲。不久之后,完美的软件就诞生了。它从集体流水线上滚下来,像第一个孩子一样,绝不会出错。

但现实根本不是这么回事。是的,我确实也很不爽自己从来没混到一间角落办公室,但我更忙着陷入恐慌,因为我根本不知道自己在干什么,没人知道,而现在整辆车的轮子都已经飞出去了。CEO 说 AI 让他那位朋友 Jared 的团队生产力高得惊人,高到他能裁掉一半人;但他说这话时像是在炫耀,不是在威胁?我不知道,反正我是感到威胁了,不过这大概只是我的焦虑症又犯了。没事,我总能从那几个在厕所里哭的员工那里借一片 Xanax 吧。

想象一下,你接了一份船长的工作。第一天,你骑车来到港口,兴冲冲地准备见你的船员。你注意到船并不在那儿,但那个你之前聊过、情绪特别亢奋的招聘人员 Greg 朝你挥手,跟你保证这不是问题。接着你被绑到一台投石机上,竟然奇迹般地被发射到了船上。上一任船长在 Captainpalooza 2025 上听另一个船长给他解释了内燃机的概念,然后就想“朝着这个方向开始迭代”。于是他把船点着了。他后来被人从船上推了下去,但顺手把使用手册也一起带走了。这本来也不该是问题,偏偏整艘船都是专门为他定制打造的。船上倒是还有帆,可它们没连在桅杆上;而那台半固定在船尾的内燃机,零件还散落在甲板各处。

你走进甲板下方,想搞明白这艘船到底怎么运作,以及你们究竟要去哪儿。但当你沿着楼梯往下层走时,你却莫名其妙地走进了桅杆里?你问一个水手这是怎么回事。他卡顿了一下,然后说:“你说得完全对!我之前的方法有问题,不过这里有一个更好的楼梯实现方案。”接着桅杆啪地一下倒转过来,你又回到了甲板上,回到一开始站着的地方。帆现在也上下颠倒了,而你的“水手”还兴奋地等着你夸他干得多好。

你又去问另一个人:“等等,我们到底是要去哪儿?”太好了,是个人类!没有卡顿,没有热情却没帮助的回答,是真正的人。她已经一周没睡了。她几乎没看你,只是说:“去问领航员。”
“领航员?”你问。
她抬手一指。那个领航员,是一个按下背后按钮就会说“勇往直前,步步高升”的娃娃。

那娃娃着火了。

这就是现在的工作。你站在一艘着火的船上,手里拿着一张地图,试图搞明白我们他妈到底要去哪里,以及我们到底要怎么去。

你知道这艘船。有些人曾经就在一艘一模一样的船上当工程师。有些人曾经就是那个离开的船长。我不是写给生日派对上的那个“有正经工作的人”看的。我是写给你的。

你曾经也是工程师。你记得代码评审原本是用来做什么的。你记得自己也曾是那个新人,第一份 PR 被某个资深工程师撕得粉碎,但对方愿意花时间解释“为什么”。你不是在 2024 年某天早上醒来后,突然决定要废掉这一切的。

真正发生的是:跑道被砍掉了。董事会会议里压根没有出现“价值观”这个词。CFO 手里拿着一张电子表格。CEO 则刚从一次线下管理层 retreat 回来,有人在那里给他看了一个 agent 在十四分钟里写完一整个功能的演示,而他竟然信了——就像人们在想相信某件事的时候,总是特别容易相信那样——然后他告诉董事会,到第二季度之前,他可以把工程团队裁掉 30%。现在,你的工作就是想办法把这件事做成。

你告诉自己,新人不会有事的。他们会适应,会重新学习技能,会找到别的出路。你告诉自己,资深工程师可以吸收掉少掉的人手,agent 会把缺口补上。你告诉自己,下个季度再回头看看。你在那张名单上签了字。你回了家。你比平时多喝了一点。然后你上床睡觉。

你知道的。

你知道,因为你也曾经是那个工程师——那个不得不去收拾上一位被“简单答案”忽悠瘸了的领导留下烂摊子的工程师。你看着 Goodhart 定律一口一口吞掉速度指标、故事点、测试覆盖率;几乎所有非工程背景的人手里拿过、并当成“工作一切顺利”证据的数字,最后都被它吃掉。你知道,当你引入工具的速度快于培养判断力的速度时,DORA 指标早就在告诉你部署稳定性会发生什么。你知道,当那些本来会发现错误的人被挤出去,或者学会了不再发现错误时,代码库会变成什么样。

你知道。可你还是签字了。因为不这么做的代价,可能就是丢掉工作;而工作背后是房贷、学费、签证,以及那个“等局势稳定下来、以后再把事情修好”的你自己。

可“以后”从来不会来。我们都知道。我也签过一张名单。直到现在,我们还在互相指责到底是谁那张名单更糟。

已经没有新人了。2024 年,我们为他们的消失办过一场葬礼。没人来。机器现在在做他们做的事,而且更便宜。当然,新人的价值从来都不在于他们眼下能产出什么,而在于他们将来会成为什么:那个知道“尸体埋在哪儿”的资深工程师。我们为产出做了优化,于是废除了学徒制。再过几年,我们会一脸困惑地问:那些资深工程师都去哪儿了?是我们亲手把他们打死了。没人会记得。

可即便如此……

在你的某处基础设施里,一定有一个 cron job。它在凌晨 3 点运行。从 2016 年起,它就一直在跑。它做着某件关键的事情。你没法准确告诉我它到底做什么,但你知道有一个人肯定知道,而那个人在 2019 年就离职了。文件开头的注释写着:# DO NOT CHANGE!!! Ask Ben。Ben 联系不上了。过去四年里的每一次路线图规划会议上,“modernize legacy cron(现代化改造遗留 cron)”都会作为候选项目出现。它从来没排上优先级。你甚至亲手把它从列表里删掉过两次。

但总有人让它继续跑着。她叫 Sara。你并不知道这件事。

她五十多岁。她没去过 Captainpalooza。她以前在离总部三条街外的一间小办公室上班。去年,为了省钱,有人把那间办公室关掉了。离她最近、同时有桌子和网络连接的地方就是这艘船,所以她现在会自己带午餐,然后顺着舷梯走到甲板下的一间小舱室。船上没人知道她在那里。还记得 Ben 吗?Ben 从 1998 年开始带她,她后来从 Ben 那里接过了这个 cron job。

她知道 Ben 几年前已经去世了。她还参加了他的葬礼。你不知道这件事。

那个任务卡住的时候——而且它经常会卡住——她就轻轻推它一下,它就会再试一次。电话响了。她确认告警。她推一下。这个任务依赖一个早已失落于时间洪流中的模块。嗯,也不算完全失落,因为 Ben 去世后,她在他的办公桌里找到了一根 U 盘,里面正好有一份备份。没有 agent 碰过它。以后也不会有。

她不是这个行业里“最安全”的人。她代表着一种你无法触碰的东西。她就是你那场转型刚刚删除掉的所有组织记忆,装在一个五十五岁的身体里四处走动。她正是从你亲手废掉的那条学徒制管道里成长出来的:Ben、1998 年、那根 U 盘。她就是那条管道。当她死去时,那个能生产出像她这样的人才的系统,也早就已经不存在了。三年前,是你亲手杀掉它的。你根本不可能再招到一个能替代她的人,因为制造她的机器已经被你砸烂了。

她就像那个拿着勺子在魔多地下挖隧道的人。勺子是她的,隧道也是她的。没有别人想要这把勺子,也没有别人想要这条隧道。而等她死了,这个 cron job 也会死,工资发放会停摆,一家有三万名员工的公司将不得不想办法重新给所有人发薪水,而到那时,只会剩下一个答案:去找一个手里有勺子的人。你找不到的。是你自己确保了这一点。

那个 cron job 负责发工资。你并不知道这件事。

生日派对上的那个家伙还在等我回答。现在我已经喝得太多,没法再撒谎了。我告诉他:不是 AI 抢走了我们的工作。是贪婪。是同一种贪婪——那种把工厂迁去孟加拉、让刚果钴矿里继续存在奴工的贪婪——只不过现在换上了一张新面具。告诉你那个外甥,去做点别的吧。做什么都行。那也未必救得了他,但至少他不用假装,摧毁他生活的东西是一台机器人。

除了 Sara。她在甲板下,带着她的 U 盘。他们动不了她,因为他们甚至不知道她在那里。

而我们其余的人,都在甲板上,盯着那些上下颠倒的桅杆,琢磨那边那个娃娃到底是干什么的。

那娃娃着火了。

Refs

【翻译】如果你以为写代码速度是你的问题,那你还有更大的问题

前言

文章来源:Andrew Murphy

原文标题:If You Thought the Speed of Writing Code Was Your Problem You Have Bigger Problems

原文链接:https://andrewmurphy.io/blog/if-you-thought-the-speed-of-writing-code-was-your-problem-you-have-bigger-problems

本文为博主翻译,若有理解偏差欢迎指正。


周二早上,你们 VP of Engineering 站在投影前,兴奋得像刚在 2017 年买到第一枚加密货币。TA 刚从某个大会(或者厂商晚宴)回来,三杯黑皮诺下肚,看完一场 Demo,然后带回了“好消息”:

“我们要给所有团队上线 AI 编码助手。早期数据显示,代码产出提升 40%。这会彻底改变我们的研发速度。”

会议室里就会出现那种经典场面:一半人在点头,另一半人突然对自己的笔记本屏幕产生了浓厚兴趣。资深工程师脸上写着“要不要现在说真话,还是回去更新 LinkedIn”。

但没有人问最关键的问题:

你说的速度,是朝着什么目标在加速?

因为你们刚刚做了一件事:在整个交付系统里,挑中了本来就不慢的一环,然后把它继续加速。你们给“非瓶颈”砸了钱。

而系统论告诉我们,这不仅不会帮到你,甚至会让情况更糟。

Goldratt 会想跟你聊聊

1984 年,Eli Goldratt 写了《The Goal》。这是一本讲制造业的小说,却对软件交付异常适用。

核心思想是约束理论(Theory of Constraints)

  • 每个系统只有一个真正约束(瓶颈);
  • 整体吞吐量由这个瓶颈决定;
  • 在瓶颈解决前,优化别的环节意义不大。

很多人理解到这里就停了。真正可怕的是下一句:

当你优化的不是瓶颈时,你得到的不是“更快系统”,而是“更坏系统”。

很直观:A 工位更快了,但瓶颈 B 速度不变,于是 A 和 B 之间堆起半成品;库存上升,交付周期变长,B 工位被淹没,优先级更混乱,质量也会下降。

你并没有提速,你只是制造了一场交通堵塞,并把它叫做“生产力”。

恐怖现场:当你“3 倍代码产出”后会发生什么

开发者 PR 提交更快了,听起来很好。但评审人数没变,没人去扩容 reviewer。

于是 PR 堆在队列里:一天、两天、一周。作者已经上下文切换去写下一个 AI 加持功能,回头再看第一个 PR 时,连自己都快不认识了。为了赶队列,评审开始“橡皮图章式”通过;CI 跑 45 分钟,偶发失败,重跑通过;发布还需要人工审批,而审批人正在开“关于会议的会议”;功能在 staging 再躺三天,因为没人真正对“尽快上线”负责。

同时,开发者已经又提了两个 PR。队列越来越长,在制品(WIP)爆炸,人人手里都有 6 件“进行中”,但“真正完成”的反而更少。真正衡量价值交付速度的 cycle time 不降反升。

你会得到一个很荒诞的局面:

  • 代码更多;
  • 软件交付更少;
  • 仪表盘显示“生产力 +40%”。

你们建成了一个世界级工厂:特别擅长生产会堆在地上腐烂的库存。

更糟的是,很多 AI 生成代码没有被任何人真正理解。提示词的人不一定真正“写过”它;值班排障的人也不一定懂它。于是系统可出故障面积变大,而能推理系统的人变少。

更多代码,更少理解。这不是生产力提升,这是定时炸弹。

那真正的瓶颈在哪?

沿着价值流走一遍:从“有人提出想法”到“用户真正获得价值”。瓶颈会自己跳出来。

1. 你根本不清楚该做什么

PM 两个月没访谈真实用户;需求是三句 Jira + 一个 Figma;工程师每天要替产品做几十个没人定义的细节决策。大家在猜。

结果是:你可能用 6 周做了一个功能,最后只有 11 个人用,其中 9 个还是内部 QA。

这不是“交付慢”,而是“我们到底在干嘛”。

在这种环境里加速写代码,只会更快把错误功能做完。

瓶颈是“理解问题”,不是“敲键盘速度”。

2. 代码“写完”之后的所有环节

在多数组织里,写代码可能只占 20%,其余 80% 都在排队。

评审、CI、staging、QA、安全审查、产品验收、发布窗口、灰度……代码在各个环节之间静止等待。很多功能代码半天写完,却两个月后才到生产。

你看见过“紧急修复”9 天才上线,就知道瓶颈根本不在编码。

想提速,先看“等待时间”,而不是“编码时间”。

3. 发布信任的恶性循环

测试不稳定、可观测性混乱、灰度流程没人信,团队越来越怕发布。越怕越攒大包,包越大风险越高,风险越高就更怕。

这时再提高代码产出,只会把“恐惧文化”喂得更肥:更多代码、同样恐惧、更大批次、更低发布频率。

4. 上线了,但到底有没有效果?没人知道

功能发布后,没有像样分析、没有用户回访、没人复盘“问题是否被解决”。于是下一个需求继续猜。

你只是更快地重复“做了—发了—耸肩”的循环。

5. 你的日历才是承重墙

有时瓶颈不是技术,而是协作:

  • 等一个决策会议;
  • 三个团队一个月没对齐 API;
  • 某架构师成了所有设计的单点审批;
  • 季度规划流程太重,紧急事项也要排队。

这都是组织问题、人问题、协调问题。

写代码更快,对这些问题的作用是 0

应该做什么(不性感但有效)

  • 画出价值流:把一个功能从想法到上线的每一步写下来,也写下步骤之间“等了多久”。
  • 衡量 cycle time,不是产出量:别再盯代码行数、PR 数、故事点;看从提交到用户拿到价值要多久。
  • 消灭等待态:评审慢就改评审机制;发布卡人工审批就自动化或降低摩擦;决策依赖会议就拆小决策。
  • 少开工,多完工:限制 WIP,3 个真正完成比 10 个进行中更有价值。
  • 听一线团队的:开发者早就知道瓶颈在哪,只是通常没人认真听。

结语

如果真的想加速交付,正确的管理台词不该是“代码产出提升 40%”,而应是:

“我们做了价值流分析,发现功能平均在流程间等待 9 天。接下来我们要把这个时间砍半。”

写代码速度从来不是大多数团队的核心问题。真正的优势不属于“写得最快”的团队,而属于能持续做到这三件事的团队:

  1. 搞清楚该做什么;
  2. 把它做出来;
  3. 快速、稳定地送到用户手里。

修瓶颈。瓶颈不在键盘。