跳到主要内容

一次性软件:编写、运行、删除

· 阅读需 11 分钟
Tian Pan
Software Engineer

上个月,我需要核对两个列规范略有不同的 CSV 导出文件——这项任务我通常会通过找一个 diff 工具、阅读其文档并与其设定的规则缠斗 20 分钟来解决。相反,我让一个 Agent 为我写了一个 50 行的脚本。它运行了一次,得出了答案,然后我就把它删除了。总共耗时:90 秒。这个脚本从未进入版本控制,从未被命名,也永远不会再出现。

这种交易模式——编写、运行、删除——正悄然成为一整类工作的默认模式。当代码生成的成本趋近于零时,最廉价的正确做法往往是定制的单次尝试,而不是通用的工具。寻找现有的实用程序意味着搜索、评估、安装、配置和信任它。而生成一个即用即弃的程序则意味着描述你想要什么。对于定义明确的窄任务,第二条路径现在在除了一个维度外的所有维度上都胜出了:没有人关注到底创造了什么。

最后一部分正是耐人寻味之处。一次性软件消除了维护负担,这确实是革命性的——软件生命周期的大部分成本都在维护上,而这种短暂的代码则无需支付任何维护费。但它也删除了两个我们之前没意识到是起支撑作用的东西:组织学习和安全审查关卡。这篇文章将探讨这种新的经济学究竟为你换来了什么,它们在无声中付出了什么代价,以及如何决定何时一个随手抛弃的方案有资格成为真正的产品。

经济学天平确实发生了倾斜

七十年来,软件创作一直受限于 ROI。每一行代码都必须证明其成本的合理性,这就是为什么该行业早期的产出是工资单、税务和 ERP 系统——针对永久性问题的永久性软件。Anish Acharya 的视角捕捉到了这种转变:过去创作受限于财务合理性;现在则仅受限于想象力。他的例子刻意选得微不足道——一个用来限制孩子屏幕时间的定制数学游戏,一个专门用于分享他家猫照片的应用。这两个应用在 2020 年的“自研还是外购”分析中都无法幸存。现在也没必要。

风投界对此的预测非常激进——Tomasz Tunguz 预计短暂型应用的数量将超过 SaaS 应用,“比例可能达到数百万比一”,而 Andrej Karpathy 则主张“默认采用超定制、超短暂的一次性应用”。但你不需要相信这种极致的版本也能看到其中的机制。Geoffrey Litt 在 2023 年就指出了这一点:终端用户编程的历史瓶颈在于将模糊的意图转化为正式的、可执行的代码,而 LLM 溶解了这个瓶颈。

结果不仅是专业人士编程更快了。而是能够编写可用软件的人群规模扩大了一个数量级,并且一个软件的最小可行受众缩减到了一个人。

对于工程师来说,这种权衡体现在日常的小决策中。你需要调整一批图片的大小、转换一个 JSON 转储文件,或者搭建一个简单的内部仪表盘。旧的决策树——是否有现成工具?它还在维护吗?它的许可证允许这样做吗?它能处理我的边缘情况吗?——现在坍缩成了一个简单的 prompt。生成的脚本能精准处理你的情况,使用你的列名、你的目录结构、你怪异的日期格式。通用工具背负着满足所有人需求的复杂性税收。而一次性脚本则完全没有。

你究竟交易掉了什么

诚实的账本有三行,而大多数对即用即弃软件的热衷者只读了第一行。

优势:零维护负债。 这个行业最古老的智慧是代码是负债,而不是资产——你每年都要为它的存在支付费用,包括依赖项更新、安全补丁以及每个阅读它的人的认知负荷。一次性软件是真正逃脱了这一规律的唯一类别。不再存在的代码不会腐烂,明年不会被攻击,也不会让未来的维护者感到困惑。删除脚本不是浪费;这正是其核心价值。

第一个损失:组织学习。 当团队维护一个共享工具时,该工具会积累知识。生产环境意外后修复的每一个 Bug,处理客户投诉后的每一个边缘情况,事故后的每一次性能优化——这些都是编码成代码的经验教训。Andreas Kirsch 对短暂软件假说的批评在这里最为有力:“测试捕捉你预料到的。生产环境捕捉你没预料到的。”

每次重新生成的脚本都会让这些积累归零。如果你的团队中有五位工程师在本季度各生成了自己的 CSV 核对程序,那么第六位工程师的版本将不包含前五位发现的任何修复。组织一直在重新学习同样的教训,并为同样的细微错误买单——每个错误都微小到难以察觉,但集合起来就是一笔实实在在的税。

第二个损失:审查关卡。 传统的安全工具共享一个假设:代码会进入仓库。代码审查、SAST 扫描、依赖项审计、许可证检查——整个治理管道都在提交时触发。一次性软件诞生在仓库之外,并在任何人看到之前就死去了。它使用你的凭据,在你的笔记本电脑上运行,调用生产环境的 API,且不留任何可供审计的痕迹。关卡没有变快;它被跳过了。

一次性代码,持久的副作用

一旦你注意到这种不对称性,治理问题就会变得尖锐:代码是短暂的,但其副作用却不是。

一个给客户列表发送邮件的一次性脚本,已经永久地发送了这些邮件。一个向生产数据库写入数据的临时迁移助手,留下的数据行将被未来的某个系统视为权威数据。Ken Huang 的表述非常准确:AI 生成的一次性代码的风险在于“虽完整但不理解”——其输出表现得像生产软件,但没有人能对其安全状况负责。具体的失效模式很平凡且已有记录:生成的服务器绑定到 0.0.0.0 而非 localhost,从而接受来自咖啡馆 Wi-Fi 的连接;幻觉产生的包名被攻击者利用进行抢注(即 “slopsquatting” 模式);凭据被粘贴到本意是“仅运行一次”的脚本中,却残留在 shell 历史记录或临时目录里。

统计数据表明,这并非假设。IBM 的《2025 年数据泄露成本报告》首次列出了影子 AI(shadow AI):涉及未经授权的 AI 工具的事件占研究中泄露事件的 20%,并使平均泄露成本增加了约 67 万美元。63% 的被攻击组织根本没有 AI 治理政策。单次使用软件是影子 AI 增长最快的表现形式——它不是报销单中未获批准的 SaaS 订阅,而是在两次审计间隔之间凭空出现、执行并消失的代码。

一个令人不安的启示是:你无法用现有的流水线来治理它,因为流水线的触发事件——代码进入代码库——从未发生过。定期审查对生命周期短于审查队列的软件无效。控制措施必须从“产物”转向“爆炸半径”(blast radius):生成的脚本可以使用哪些凭据,可以触达哪些网络,可以接触哪些数据。沙箱执行环境、限权的短期令牌以及出口监控,能以代码审查永远无法做到的方式治理临时代码——它们不需要查看代码,只需限制其行为。这种从审查产物到约束能力的转变,对于任何负责 AI 智能体(agent)处理琐碎事务的工程团队负责人来说,都是最有用的思维转变。

晋升问题

更微妙的失效模式不是只运行一次的脚本,而是“原本”打算只运行一次的脚本。

每个操作过真实系统的人都熟悉这种生命周期:一次性脚本运行了第二次,然后加入到了 cron 任务中,接着 Slack 频道里有人请求增加一个小功能;18 个月后,一个没有测试、没有维护者、没有错误处理的“临时”脚本成了承重级的核心基础设施。一次性软件并没有消除这种失效模式,而是将其工业化了,因为现在一次性脚本的数量增加了百倍,而且每一个都足够胜任,以至于能在未经审查的情况下存续。

因此,重要的纪律不是“永远不要写一次性代码”,而是要有明确的晋升标准——即通过清单将临时方案有意识地转变为产品,而不是任其野蛮生长。我的清单如下:

  • 第三次运行规则。 第一次运行是偶发,第二次是巧合。如果你第三次使用同一个生成的脚本,它就是一个工具,需要代码库、维护者和名称。每次重新生成看似免费,但会默默丢弃上一次运行带给你的所有修复经验。
  • 他人使用规则。 一旦有第二个人使用它,你脑中关于它功能的模糊定义就会变成他们的生产事故。共享使用要求书面化的行为规范——至少需要一个 README 和固定的依赖版本。
  • 状态规则。 一旦一次性脚本向任何其他系统读取的持久存储写入数据,无论它运行频率如何,它都不再是“可丢弃的”。Kirsch 关于集成边界的观点完全适用:系统间的薄弱代码最难测试,且出错后果最严重,无声的数据损坏比明显的崩溃要糟糕得多。
  • 无人值守规则。 任何计划任务——cron、CI、webhook——都是一项服务,毫无例外。服务需要监控、报警和值班人员。一个没有这些配置、按计划运行的生成脚本,就是一个带延迟定时器的故障。

清单的目的不是搞官僚主义,而是让晋升变得“可见”。失败不在于编写了一次性代码,而在于一次性代码在无人决策的情况下获得了永久地位。

两类代码,两套规则

最终会走向何方?并非“所有软件都会变成临时的”——最强有力的反驳依然成立。具有持久状态、用户已建立心理模型的稳定接口以及审计合规要求的系统将保持持久性,因为代码是具体解决操作歧义的地方,重新生成代码会重新开启旧版本已经回答过的每一个问题。默认重新生成只是重现了经典的重写失败,只是速度更快。

但“单次使用软件只是昙花一现”的观点同样错误。经济效益是真实的,且不可逆转。事实是软件正在分化为具有不同规则的两类。持久性软件沿用旧规则:仓库、审查、测试、维护者、变更日志。临时性软件采用新规则:沙箱执行、限权凭据、受控的爆炸半径,以及任何试图跨入持久类别的显式晋升标准。

能够处理好这一趋势的团队,不是那些禁止生成一次性代码的团队——那场战斗已经输了,而且其生产力价值太高,无法禁止。成功的团队是那些能让这两类代码清晰可辨的团队:为一次性工作提供廉价、安全、真正可丢弃的路径,并为极少数重要的一次性代码建立一个慎重且低摩擦的准入门槛。编写、运行、删除——并且确切知道哪些是不允许被删除的。

References:Let's stay in touch and Follow me for more thoughts and updates