最近在使用 Codex 推进开发时,我越来越强烈地感受到一件事:

AI 改变了软件开发的生产方式,但它并没有让过去几十年形成的软件工程思想失效。

恰恰相反。

当 Agent 能够越来越快地理解需求、修改代码、运行测试,甚至独立推进一个复杂任务以后,过去很多为了“提升开发效率、控制复杂度”而形成的软件工程方法,开始表现出新的价值。

最直观的感受是:

更省 Token,也更不容易跑偏。

但如果继续往下看,会发现 Token 只是表象。

真正发生变化的是:

软件工程正在从“管理人的复杂度”,进一步变成“管理 Agent 的不确定性”。

而 Agent 越强,这件事情反而越重要。

从我以前做过的 ProTable 说起

很多年前,我做前端架构时,开发过类似 ProTable 这样的基础组件。

当时的目的很简单。

业务系统里有大量列表页面:用户列表、订单列表、客户列表、审批列表……

如果每一个开发人员拿到需求以后,都重新实现一次查询、分页、筛选、Loading、异常处理、权限控制,那么不仅开发效率低,最后每个人写出来的东西也很容易不一样。

所以我们会把这些已经反复出现的问题抽象掉。

一个新的业务页面真正需要关心的,只应该是:

  • 查询什么数据;
  • 展示哪些字段;
  • 有哪些业务操作;
  • 当前业务有哪些特殊规则。

分页怎么处理、查询参数怎么组织、错误状态怎么展示,这些问题不应该每次都重新解决。

过去我们通常把这种价值叫作:

代码复用。

但今天重新回头看,我觉得这个描述其实并不完整。

因为真正被复用的,从来不只是代码。

被复用的还有过去已经做过的那些工程判断

为什么分页这样设计?

为什么查询参数这样组织?

为什么组件开放这些扩展点,而不是另外一些?

这些问题曾经被人思考过、讨论过、踩过坑,最终才形成了一套稳定结构。

代码只是这些判断留下来的载体。


AI 会写代码以后,为什么还需要这些东西?

Agent 出现以后,一个很自然的想法是:

既然 Codex 可以很快写一个 Table,我们为什么还要花时间抽象?

下次需要的时候,再让 Agent 生成一次不就好了?

对于 Demo、原型、一次性脚本,我认为这种思路完全成立。

但对于一个需要持续演进几个月、几年甚至更久的复杂系统,我越来越不认同这种做法。

因为:

代码生成变便宜了,不代表重新理解和重新决策也变得免费。

假设系统里没有稳定的 Table 基础能力。

今天让 Agent 做用户列表,它需要搜索现有代码,理解项目怎么处理分页、接口、状态和权限。

明天做订单列表,它又会重新做一遍类似的事情。

换一个 Thread 再做客户列表,它仍然需要重新读取上下文、重新理解约定、重新判断应该怎么实现。

即使最终三次都写对了,Agent 也完成了三次高度重复的推理。

这些重复推理会表现为:

更多搜索、更多文件读取、更大的 Context、更多 Token,以及更多需要 Agent 自己判断的地方。

而如果系统已经存在一个成熟的 ProTable,Agent 面对的问题就从:

我应该怎么实现一个企业级 Table?

变成:

当前这个业务应该如何映射到现有的 ProTable?

任务空间一下就小了很多。

这时候节省的已经不仅是代码。

更重要的是:

减少了 Agent 的重复推理。


Architecture is cached reasoning

这让我逐渐形成了一个新的理解:

Architecture is cached reasoning.

架构,在某种意义上就是被缓存下来的工程推理。

一个成熟组件,是一组被固化的工程判断。

一个稳定 API,是一组被固化的系统边界。

一个 Schema,是一组被显式表达的数据约束。

一套测试,是一组关于“什么才算正确”的可执行判断。

一个领域模型,则是一组被长期维护的业务认知。

这些东西过去主要服务于人。

今天,它们同时开始服务 Agent。

当这些结构存在时,Agent 不需要每次重新回答:

这个问题应该怎么解决?

它只需要判断:

当前问题应该如何放进已经存在的结构?

这是完全不同的复杂度。

所以我越来越认为,AI 时代的软件工程有一个很重要的原则:

不要让 Agent 重复思考已经解决过的问题。

凡是稳定、高频、反复出现的问题,都应该逐渐从 Prompt 和 Agent 的临时推理中移出去,沉淀成更加稳定的工程结构。

它可以是组件、框架、SDK、Schema、API、测试、规范、领域模型,或者其他基础设施。

这其实是一种新的:

认知复用。


软件工程正在减少 Agent 的不确定性

如果从这个角度重新看过去几十年的软件工程思想,会发现很多东西都没有过时,只是价值表现发生了变化。

软件工程思想 过去主要解决什么 Agent 时代新增的价值
代码复用 / 抽象 减少重复开发 减少重复推理
模块化 降低耦合、方便协作 缩小 Agent 的搜索范围和 Context
API / 类型 / Schema 减少接口误解 缩小 Agent 的解释空间
自动化测试 防止回归 给 Agent 提供客观反馈闭环
Git 版本管理与协作 提供状态边界、审计和恢复能力
文档 / Spec 知识传递 提供稳定的外部 Context
领域模型 建立统一业务语言 给 Agent 提供稳定的业务语义

比如模块化。

以前我们强调高内聚、低耦合,很重要的原因是方便多人协作。

到了 Agent 时代,它又多了一层很直接的价值:

让 Agent 每次只需要理解有限的问题空间。

如果一个业务修改涉及十几个目录,Agent 就不得不到处搜索:

这个状态在哪里修改?

这个字段是谁生成的?

这里改了会不会影响其他地方?

即使 Context Window 足够大,也不意味着应该把整个仓库都塞进去。

大量无关信息本身就是噪声。

而清晰的模块边界,本质上是在告诉 Agent:

这个任务主要发生在这里。

再比如类型、Schema 和接口契约。

如果一个字段能不能为空、一个状态有哪些枚举、一个 ID 代表什么都没有明确规定,Agent 就只能自己猜。

Agent 足够强,很多时候确实能猜出来。

但问题在于:

能猜出来,不代表应该让它猜。

软件系统很多错误并不是因为 Agent 不够聪明,而是因为系统允许它做出的“合理解释”太多。

好的软件工程,就是在不断减少这种解释空间。


Token 少了,只是表象

为什么好的工程结构往往更加节省 Token?

其实并不神秘。

如果架构清楚,Agent 搜索得更少。

如果模块边界明确,Agent 读取的文件更少。

如果接口和 Schema 清楚,Agent 猜测得更少。

如果领域模型稳定,Agent 不需要反复从代码和文档里重建业务认知。

如果测试充分,Agent 验证修改的路径也更短。

所以 Token 的减少,并不是因为我们专门做了什么“Prompt 优化”。

它更像是一个结果。

真正被降低的是:

搜索空间、解释空间和决策空间。

可以简单理解成:

软件工程结构

缩小 Agent 搜索空间

缩小 Context

缩小解释空间

缩小决策空间

减少 Token 和重复推理

降低跑偏概率

所以我现在并不太把“节省 Token”理解成一个单纯的成本问题。

很多时候,它其实是系统是否具有良好结构的一种外在表现。


Agent 越强,混乱传播得也越快

这可能才是我认为最值得警惕的一点。

过去,一个开发人员一天能够完成的代码修改是有限的。

即使工程结构很差,混乱的增长速度也受到人的生产力限制。

但 Agent 改变了这个上限。

一个能力足够强的 Agent,可以在很短时间内:

创建大量文件、修改多个模块、完成一次大规模重构、调整接口、补测试,甚至继续自主修复自己制造的问题。

这种生产力当然很有价值。

但生产力本身是中性的。

如果方向正确,它会放大正确的结构。

如果方向错误,它也会极快地放大错误。

如果一个仓库边界混乱、缺少测试、缺少明确规则、领域语义模糊,那么越强的 Agent,越可能以更高速度继续扩散这种混乱。

所以这里其实存在一个很反直觉的关系:

Agent 能力越强,对工程约束的要求反而越高。

因为我们正在把越来越强的执行能力交给它。

过去糟糕的软件工程可能只是拖慢一个团队。

到了 Agent 时代,它还可能让混乱以过去数倍、数十倍的速度扩散。


但好的软件工程,也会被 Agent 成倍放大

事情的另一面其实更加值得期待。

Agent 不只会放大坏工程的风险。

它同样会放大好工程的收益。

一个结构良好的代码库,Agent 更容易理解。

一个边界清晰的模块,Agent 更容易修改。

一个测试充分的系统,Agent 可以自主推进更长的任务链路。

一个稳定的领域模型,可以让新的 Thread 很快重新获得业务认知。

一个成熟的组件体系,也可以让 Agent 快速完成大量业务功能,而不用不断重新解决基础问题。

也就是说:

过去软件工程是在放大人的生产力。

今天,它开始同时:

放大 Agent 的生产力。

这可能才是传统软件工程在 AI 时代真正值得重新理解的地方。


从代码复用,到认知复用

所以如果一定要总结我最近的一个感受,我会把它称为:

从代码复用走向认知复用。

过去我们把已经写好的代码留下来,不希望下一个程序员重新实现。

今天我们还应该进一步思考:

哪些问题,是不是也不应该让下一个 Agent 重新思考?

如果一个工程判断不断出现,就应该尝试把它沉淀下来。

如果一个业务概念不断需要解释,就应该让它拥有稳定的模型。

如果一个错误不断需要 Agent 自己发现,就应该把它变成测试或者静态约束。

如果一个操作不断依赖 Prompt 提醒,也许就应该把它变成工程规则或者自动化机制。

Prompt 很适合告诉 Agent:

这一次要做什么。

而软件工程更擅长告诉 Agent:

在这个系统里,事情应该怎样被做。

AI 正在让代码本身变得越来越便宜。

但代码变便宜,并不意味着复杂系统也因此变得简单。

当生成代码不再是主要瓶颈以后,真正困难的问题反而会越来越集中到:

如何保持结构,如何维护长期一致性,如何控制 Agent 的不确定性,以及如何避免越来越高的执行速度演变成越来越快的混乱。

这些问题最终仍然会回到软件工程。

所以真正值得讨论的问题,从来都不是:

AI 会不会让软件工程过时?

而应该是:

当 Agent 已经可以如此快速地生产代码,我们是否已经准备好了与这种生产力相匹配的软件工程体系?

至少到目前为止,我自己的答案越来越明确:

Agent 越强,我们越需要软件工程。