AI Coding 之后,我为什么越来越少亲自写代码,却越来越重视测试和可观测性

当代码生成变得便宜,验证就变得昂贵:从代码 Review 转向系统验证,用集成测试与可观测性建立反馈闭环。

2026/08/15更新于 2026/08/157 分钟

AI 编程工具刚开始普及时,大部分讨论集中在一个问题:

AI 写代码到底有多强?

但我实际在生产项目里使用一段时间以后,越来越觉得,这个问题的重要性正在下降。

因为代码生成已经足够便宜。

真正开始变贵的是:

验证。

也就是:

AI 写出来的代码,我凭什么相信它?

这件事正在改变我的工程习惯。

「能写出来」已经不是主要瓶颈

以前开发一个模块,代码本身就是主要工作量。

例如一个后端功能可能需要:

  • 设计接口;
  • 建表;
  • 写 Repository;
  • 写 Service;
  • 写参数校验;
  • 写错误处理;
  • 写测试。

很多工作都需要程序员亲自完成。

今天,如果需求明确、项目结构清楚,这些实现类工作已经可以大量交给 AI。

尤其是:

  • CRUD;
  • 数据转换;
  • 常规业务逻辑;
  • 重构;
  • 测试样板;
  • 重复代码修改。

AI 的效率已经很高。

这时候继续优化“代码生成速度”,收益开始下降。

因为一个新的问题出现了:

AI 可以一次修改很多代码,但我没有能力用同样的速度 Review。

于是软件开发里的生产能力开始失衡:

Generation Capacity
>>>>>>>>>
Verification Capacity

生成能力快速增加。

验证能力没有同步增加。

这就是新的瓶颈。

为什么 AI 很容易制造「看起来正确」的代码

AI 生成代码最大的风险,并不是代码一定很差。

相反,它经常:

看起来非常合理。

变量名正确。

代码结构正确。

测试甚至可以通过。

但它仍然可能违反系统真实约束。

例如一个会员系统中的“增加会员时长”,表面逻辑可能非常简单:

查询当前会员
+
增加时长
+
保存

但生产环境真正的问题可能包括:

  • 同一个 Webhook 是否会重复到达?
  • 一个事件重复执行两次怎么办?
  • 更新失败以后是否会重试?
  • 重试是否会产生重复发放?
  • 老系统是不是还在写同一份数据?
  • 数据迁移过程中两个系统是否同时存在?
  • 用户已经过期和仍然有效的处理逻辑是否一样?
  • 第三方状态和本地状态不一致怎么办?

这些信息并不一定存在于某一个函数里。

它们分散在:

  • 历史代码;
  • 数据库;
  • 产品规则;
  • 第三方协议;
  • 线上运行状态;
  • 运维配置。

所以即使 AI 完全理解了当前文件,也不意味着它理解了整个系统。

这就是为什么:

局部代码正确,不等于系统正确。

我开始减少代码 Review,增加系统验证

传统代码 Review 很大程度上依赖:

人阅读代码,然后判断它有没有问题。

但当 AI 一次产生大量代码时,这种模式开始变得昂贵。

例如 AI 修改了:

  • 15 个文件;
  • 800 行代码;
  • 20 个测试。

如果我要逐行阅读,我实际上并没有节省多少认知资源。

于是我开始改变策略。

相比于问:

这 800 行代码是不是每行都写得很好?

我更愿意问:

这个系统必须满足哪些不变量?

例如:

同一个订单不能重复发权益。

会员时长不能因为重试重复增加。

余额不能出现负数。

迁移前后的总会员时长必须一致。

旧接口不能继续修改新系统的数据。

然后尽可能通过自动化测试证明它们。

这实际上是在从:

Code-oriented Verification

转向:

Invariant-oriented Verification。

我认为这非常适合 AI Coding。

Hurl 和 Testcontainers 为什么对我很重要

后来我开始大量使用集成测试。

其中两个工具对我的工作方式影响比较明显。

一个是 Hurl。

它适合快速描述 HTTP 场景,例如:

注册
↓
登录
↓
兑换激活码
↓
查询会员状态
↓
验证权益

相比于手动打开 Postman 点接口,这种测试:

  • 能进入 Git;
  • 可以重复执行;
  • 可以被 AI 修改;
  • 可以进入 CI;
  • 可以作为系统行为文档。

另一个是 Testcontainers。

它解决的是另外一个问题:

测试不能只 Mock 掉所有真实基础设施。

真实项目经常依赖:

  • PostgreSQL;
  • Redis;
  • MQ;
  • 其他服务。

如果所有东西都 Mock 掉,很容易出现:

单元测试全绿,上线以后 SQL、事务、约束或者序列化直接出错。

Testcontainers 让我可以用真实数据库执行测试。

这对 AI 代码尤其重要。

因为 AI 经常能生成“逻辑上正确”的数据库代码,却容易忽略:

  • 真实 schema;
  • constraint;
  • transaction;
  • nullable;
  • index;
  • isolation;
  • migration。

这些问题必须让真实环境参与验证。

测试仍然不够

后来我又碰到另外一个问题:

测试通过,也不能证明生产环境没有问题。

生产系统会多出非常多变量:

  • 用户历史数据;
  • 网络抖动;
  • 第三方异常;
  • 重试;
  • 并发;
  • 长尾请求;
  • 配置错误;
  • 部署差异。

所以测试之后,下一层能力自然变成:

Observability。

也就是系统上线以后,我能否快速回答:

  • 哪个用户出了问题?
  • 哪个请求失败?
  • 失败经过了哪些服务?
  • 错误比例是否突然增加?
  • 哪个版本开始出现问题?
  • 数据库是不是变慢?
  • 某个业务错误到底发生了多少次?

这也是为什么我开始关注:

  • Error Tracking;
  • Logs;
  • Metrics;
  • Trace。

过去我会把这些东西理解成:

运维设施。

现在我更倾向于把它理解成:

AI Coding 的验证系统。

AI 让 Change Velocity 上升。

Change Velocity 越高,对 Feedback Loop 的要求就越高。

一个简单的公式

我现在会这样理解 AI Coding:

有效生产力
=
代码生成速度
×
正确率
×
反馈速度

如果只提高第一项:

代码生成速度 × 10

但是:

错误发现需要 3 天

那么整体效率未必提高。

甚至可能因为变化过快,制造更多问题。

真正理想的系统是:

AI 10 分钟完成修改
↓
自动测试 3 分钟发现问题
↓
AI 自动修复
↓
CI 验证
↓
上线
↓
Observability 持续观察

人的任务主要集中在:

定义什么叫正确。

这比不断亲自写代码重要得多。

AI 时代,测试的价值反而提高了

以前很多开发者不愿意写测试,一个现实原因是:

写测试也需要大量时间。

现在这个约束已经发生变化。

AI 非常适合:

  • 根据现有代码生成测试;
  • 枚举边界条件;
  • 建立测试数据;
  • 补充失败案例;
  • 修改大量重复测试。

也就是说:

测试代码本身的生产成本正在降低。

那测试的 ROI 就会明显提高。

以前:

写功能 2 小时
写测试 1 小时

很多人会觉得成本太高。

未来可能变成:

AI 写功能 15 分钟
AI 写测试 10 分钟
CI 自动验证

这个时候,不建立测试体系反而越来越不合理。

我现在更关心「反馈闭环」

现在评价一个项目工程质量时,我越来越少只看:

  • 代码漂不漂亮;
  • 抽象是不是高级;
  • 架构是不是复杂。

我反而更关心几个非常朴素的问题:

改坏以后多久能知道?

出事故以后多久能定位?

重复执行会不会产生脏数据?

有没有办法自动证明关键业务链路正常?

某个用户反馈问题以后,能不能追溯完整上下文?

这些问题决定了:

AI 到底能不能安全地提高开发速度。

如果答案都是否定的,那么 AI 越强,风险反而越高。

最后的判断

AI Coding 让我越来越少亲自写机械代码。

但与此同时,我开始越来越重视:

  • 测试;
  • 数据一致性;
  • 幂等;
  • 日志;
  • Trace;
  • Metrics;
  • Error Tracking;
  • CI/CD;
  • 发布验证。

这看起来像是从“开发”走向了“工程治理”。

但我认为这恰恰是 AI 编程发展以后很自然的结果。

因为:

当代码本身越来越便宜,证明代码正确的能力就越来越贵。

未来一个高效的软件工程师,也许并不是一天能亲手写多少代码。

而是:

能以多低的认知成本,让大量机器生成的代码持续保持正确。

评论