目录
[(一)「Java 工程师会不会被替代」?](#(一)「Java 工程师会不会被替代」?)
[(二)一个 Java 工程师的一周到底在做什么](#(二)一个 Java 工程师的一周到底在做什么)
[4、「会用 AI」本身不构成护城河](#4、「会用 AI」本身不构成护城河)
[2、Java 系统里典型的高闭合与低闭合任务](#2、Java 系统里典型的高闭合与低闭合任务)
[2、可逆性决定人在环的位置,而不是决定要不要用 AI](#2、可逆性决定人在环的位置,而不是决定要不要用 AI)
[四、把 Java 工程师的日常任务投影到判据上](#四、把 Java 工程师的日常任务投影到判据上)
[六、AI 生成的 Java 代码最常在哪些地方出错](#六、AI 生成的 Java 代码最常在哪些地方出错)
[1.1 自调用导致事务注解失效](#1.1 自调用导致事务注解失效)
[1.2 传播行为选错](#1.2 传播行为选错)
[1.3 事务边界包住了远程调用](#1.3 事务边界包住了远程调用)
[1.4 在事务提交之前发消息或写缓存](#1.4 在事务提交之前发消息或写缓存)
[2、N+1 与批量](#2、N+1 与批量)
[1、Mock 掉了出错的地方](#1、Mock 掉了出错的地方)
[3、判据设计是 AI 时代最高杠杆的技能](#3、判据设计是 AI 时代最高杠杆的技能)
[(四)AI 生成的测试的四种坏味道](#(四)AI 生成的测试的四种坏味道)
[2、Mock 到只剩下 Mock](#2、Mock 到只剩下 Mock)
[(三)JVM 现场的六类证据](#(三)JVM 现场的六类证据)
[(四)把 AI 用在排障上的四种正确姿势与两种错误姿势](#(四)把 AI 用在排障上的四种正确姿势与两种错误姿势)
[1、它直接决定 AI 的产能](#1、它直接决定 AI 的产能)
[2.1 直接成本](#2.1 直接成本)
[2.2 人力成本](#2.2 人力成本)
[2.3 风险成本](#2.3 风险成本)
[2.4 机会成本](#2.4 机会成本)
[2.5 退出成本](#2.5 退出成本)
[十三、Java 工程师的新增值区:把企业能力变成可被调用的东西](#十三、Java 工程师的新增值区:把企业能力变成可被调用的东西)
[(一)为什么这是 Java 后端的主场](#(一)为什么这是 Java 后端的主场)
[2、Java 后端具备的三个条件](#2、Java 后端具备的三个条件)
[1.1 第一周:把验证回路砍到十分钟以内](#1.1 第一周:把验证回路砍到十分钟以内)
[1.2 第二周:写下三条不变式](#1.2 第二周:写下三条不变式)
[1.3 第三周:写一份失效模式清单](#1.3 第三周:写一份失效模式清单)
[1.4 第四周:把清单变成检查](#1.4 第四周:把清单变成检查)
[2.1 第五、六周:完整委派三类任务](#2.1 第五、六周:完整委派三类任务)
[2.2 第七周:补齐上下文](#2.2 第七周:补齐上下文)
[2.3 第八周:复测一次通过率](#2.3 第八周:复测一次通过率)
[3.1 第九、十周:接一个升值区的任务](#3.1 第九、十周:接一个升值区的任务)
[3.2 第十一周:写一份决策记录](#3.2 第十一周:写一份决策记录)
[3.3 第十二周:复盘整个季度](#3.3 第十二周:复盘整个季度)
[3、用 AI 产出量作为绩效](#3、用 AI 产出量作为绩效)
干货分享,感谢您的阅读!
一个后端工程师在 2026 年最该焦虑的,不是「模型会不会写 Java」------它早就会写了,而且写得比大多数人快。
真正该问的是:当「写出一段候选实现」的成本塌陷到接近零之后,一条软件交付链上剩下的哪些环节还在收费,收多少。
本文给出的不是一份鼓励式的技能清单,而是一套可以自己动手算的估值方法:四条判据、三条成本曲线、一张把日常任务投影成三个价格档位的地图。
结论是可以落到下周一的------你手上正在做的十八类事情里,有六类值得立刻交出去,有五类必须自己重新学一遍,还有七类是你未来五年的定价权所在。
一、被替代的不是岗位,而是任务
(一)「Java 工程师会不会被替代」?
1、岗位不是替代发生的单位
技术替代从来不是按职位名称发生的。会计这个职位在电子表格出现之后没有消失,消失的是「手工过账与试算平衡」这一组具体动作;排版工人这个工种在桌面出版之后没有整体蒸发,蒸发的是「铅字捡排」这一组具体动作,而「版式判断」被并进了设计师的工作里,反而变贵了。
替代真正发生的单位是任务:一段有明确输入、明确产出、明确验收方式的工作。一个职位是几十种任务的组合包,其中一部分任务的完成成本被压到零,另一部分纹丝不动,还有一部分因为前一部分变便宜而需求量暴涨。职位的命运,是这几十种任务各自命运的加权结果,而不是一个整体判断。
所以「Java 工程师会不会被替代」这个问题,在提问的那一刻就已经把答案锁死成一个没有信息量的二元判断。把它拆成「我这一周做的这十八件事,每一件的完成成本、验证成本、后果成本各自发生了什么变化」,才会得到能指导行动的答案。
2、三个被反复混淆的说法
讨论这件事时,「写代码」「做软件」「交付系统」这三个说法经常被当成同义词,但它们的可替代性相差极远:
- 写代码指的是把一个已经想清楚的意图翻译成某种语言的合法语句。这件事的输入是清晰的,输出是可编译的,正确性在很大程度上机器自己就能判定。这是被压缩得最彻底的一层。
- 做软件指的是在一堆互相冲突的约束里选一条能走通的路,并为这条路上的每一个折中留下理由。它的输入是不完整的,输出是有争议的,正确性要等到几个月后才知道。
- 交付系统指的是让这套东西在真实流量、真实故障、真实合规要求下持续运转,并且在出事的时候有人能在半小时内说清楚发生了什么、要不要回滚、回滚会损失什么。它的输入是现场,输出是决策,正确性由后果检验。
把「写代码变便宜了」直接推成「做软件和交付系统也变便宜了」,是当前几乎所有夸张判断的来源;反过来,用「模型不懂我们业务」来否认第一层的塌陷,则是另一种自我安慰。
3、正确的问法长什么样
一个能得到有效答案的问法应该同时满足三点:以任务而不是职位为单位;区分「生成」「验证」「担责」三个环节;给出可以在自己的工作台上验证的判据,而不是依赖对模型下一代能力的猜测。
本文接下来的全部结构都建立在这个问法上。

(二)一个 Java 工程师的一周到底在做什么
1、把一周拆成十八类任务
在一家有一定规模的公司里,一名工作四到八年的 Java 后端工程师,一周四十小时的时间大致会散落在这些地方:需求沟通与澄清、方案设计与评审、库表与接口设计、编写业务逻辑、编写数据访问层、编写单元测试、编写集成测试、代码评审(看别人的)、响应评审意见(改自己的)、联调与自测、线上问题排查、性能分析与调优、发布与灰度值守、监控与告警维护、文档与变更记录、依赖与框架升级、技术调研与选型、跨团队对齐与答疑。
这十八类里,真正在编辑器里敲出新业务代码的时间,在多数团队的统计中落在 15% 到 25% 之间。这不是一个新现象,也不是 AI 带来的,它一直如此。但这个分布决定了一件重要的事:即使写代码这一项的成本降到零,一周也只省下四到十个小时,除非其他十七类任务的成本也跟着变化。
2、真正吃掉时间的是理解与确认
把上面十八类按性质重新归并,会得到一个更有解释力的分布:理解 (搞清楚要做什么、现状是什么、约束在哪里)大约占四成,生成 (把想清楚的东西变成代码、配置、文档)大约占两成,确认(测试、评审、联调、排查、值守)大约占四成。
编码助理直接命中的是中间那两成,并且对「理解」和「确认」的两头都有影响------但方向相反。它让「理解」这一头略微变轻(可以让它先读一遍陌生模块给出摘要),却让「确认」这一头显著变重(产出的候选变多了,每一份都要被判定)。
3、这份分布决定了替代的上限,也决定了机会的位置
如果一个团队只把 AI 用在「生成」那两成上,理论上限就是提效 20%,实际因为验证负担增加,净收益经常低于 10%,甚至为负。这解释了一个被反复观察到的现象:不少经验丰富的开发者在引入编码助理之后,主观感觉快了很多,实测完成时间却没有变短甚至更长------省下的敲键盘时间,被读、验、改、丢弃候选实现的时间吃掉了。
真正的机会在两头:把「理解」这一头的隐性上下文显性化,把「确认」这一头的判定自动化。这两件事恰恰不是模型能单方面完成的,它需要工程师去改造系统、改造流程、改造自己的工作方式。这也是本文后面十几章要展开的全部内容。

(三)本文成立的三条前提
1、以现有工程实践为坐标,不预测模型的下一代能力
本文所有判断都基于「一个足够强的编码助理」这一假设,即:它能读懂你给它的全部上下文,能生成语法正确、风格一致、在给定描述下逻辑自洽的代码,能调用工具运行测试并根据反馈迭代。这个假设在 2026 年已经基本成立。本文不假设它能自己知道你没告诉它的事,也不假设它能替你承担后果------这两条是本文全部结论的支点,而它们不是能力问题,是结构问题。
2、只推导价值转移,不做速度预言
「三年后还需不需要 Java 工程师」这类问题无法证伪,讨论它没有收益。可以讨论的是:在同一支团队里,两个人做同样的活,为什么其中一个的报价在涨、另一个在跌。价值转移的方向是可以从成本结构推出来的,转移的速度则取决于组织惯性、监管环境和事故的发生频率,那不是个人能控制的变量。
3、结论必须能落到下周一
任何一条「你要提升架构能力」式的建议都是废话,因为它不可执行。本文对每一项能力都会给出:它具体表现为什么动作、这个动作的产出物是什么、怎么判断你做到了没有。判断不了的,就不写进来。

二、三条成本曲线:为什么「会写」不再是核心资产
(一)生成成本:塌陷到接近零
1、塌陷的三个阶段
第一阶段是补全,单位是行,价值在于少敲几个字符;第二阶段是生成,单位是函数与类,价值在于跳过样板;第三阶段是委派,单位是一个可验收的变更,价值在于把「读需求、改多个文件、跑测试、修编译错误」这一整段循环交出去。三个阶段的关键差别不在于生成的代码量,而在于谁来跑那个循环。到了第三阶段,工程师的动作从「写」变成了「派活与验收」,这是职业形态的实质变化。
2、塌陷不是均匀的
生成成本的下降在不同类型的代码上差异极大。样板代码(DTO、转换器、构造器、基础的数据访问方法)下降了一到两个数量级;有明确规范可循的代码(按 OpenAPI 描述生成控制器、按建表语句生成实体)下降接近一个数量级;有清晰局部语义的算法实现(排序、解析、格式转换)下降明显;而涉及系统全局约束的代码(并发控制、事务边界、幂等设计、跨服务一致性)下降有限,因为瓶颈从来不在打字速度,而在于把约束想清楚。
这个不均匀性非常重要:它意味着「AI 提效多少」这个问题没有统一答案,答案取决于你的工作构成里样板代码占多大比例。一个每天写增删改查的人和一个每天处理一致性问题的人,感受到的冲击完全不是一回事。
3、一个容易被忽略的副作用:候选数量爆炸
生成成本下降的直接后果不只是「同样的东西更快做完」,而是「同样的时间产生了更多候选」。过去评估三个方案要一天,现在半小时能拿到八个可运行的原型。这是好事,但它把压力精确地转移到了下一环:你要在八个都能跑的东西里挑一个,而挑选依据是什么,模型不会替你定。

(二)验证成本:几乎没有下降,还被产量推高
1、验证成本的构成
确认一段代码「在我们的系统里是对的」,需要付出四种成本:读懂它的成本、判断它是否符合未写下来的约束的成本、构造能暴露问题的输入的成本、在真实环境中确认没有副作用的成本。
这四项里,只有第一项被 AI 显著降低了(它可以解释代码)。第二项完全没有降低,因为「未写下来的约束」按定义不在它的上下文里。第三项部分降低(它能生成测试用例),但生成的用例质量高度依赖于对失效模式的理解,而这正是它最弱的地方。第四项一点没降,因为那需要真实流量。
2、产量上升让总验证成本上升
单位验证成本没变,待验证的产出翻了几倍,总验证成本就上升了。这是很多团队引入编码助理之后「代码评审排队」「测试环境抢不到」「发布窗口不够用」的直接原因。瓶颈从写移到了验,而验的产能没有同步扩张。
这也解释了为什么「AI 编程效率提升」的实测数据经常令人失望:在受控实验里,让熟悉自己项目的资深开发者使用 AI 工具完成真实任务,完成时间不降反升的情况被反复观察到,而参与者主观上普遍认为自己变快了。主观加速与客观减速同时存在,差额就落在验证环节。
3、验证成本的不可压缩部分
有一部分验证成本在原理上不可能被生成方自己消化:判断一个产出是否正确,需要一个独立于产出方的判据来源。如果判据也由同一个模型给出,那么它只能保证「自洽」,不能保证「正确」。这是「谁来做判据」这件事在 AI 时代身价飙升的根本原因,本文第七章会专门展开。
(三)后果成本:一分没少,还被变更速率放大
1、后果成本与生成成本无关
一次错误的资金入账、一次误删的用户数据、一次泄漏的密钥、一次没有兼容窗口的接口变更,它们的代价由业务规模和法规环境决定,与这段代码是人写的还是模型写的毫无关系。生成侧的成本降低了三个数量级,后果侧的成本一分没变。
2、变更速率上升会放大后果的期望值
如果单次变更的出错概率不变,而单位时间的变更次数翻了三倍,那么单位时间内的事故期望值也翻了三倍。这是一个纯粹的算术事实。要抵消它,只有两条路:把单次出错概率压下去(更强的验证),或者把单次事故的后果压下去(更强的可逆性与隔离)。这两条路都需要工程投入,而且都不是模型能自己完成的。
3、三条曲线合在一起给出的价值转移公式
把三条曲线放到同一张图上:生成成本断崖下降,验证成本横盘微升,后果成本横盘但被速率放大。一项能力的价格,正比于它在「验证 + 担责」这条链上的不可替代程度。
用一句可以背下来的话概括:写得出来,不再值钱;说得清楚「对不对」,开始值钱;扛得住「错了怎么办」,最值钱。

(四)这条公式解释的四个反直觉现象
1、越是标准化的技术栈,冲击越大
Java 生态的规范性、框架的成熟度、代码风格的统一程度,在过去是优势------上手快、协作顺。在生成侧,这些恰恰是让模型表现最好的条件:训练语料多、模式清晰、约定俗成。所以 Java 工程师在「样板代码」上受到的冲击,比小众语言的从业者更大。
2、越是复杂的企业系统,人的价值越高
同一个 Java 生态里,一个跑了八年、有三百张表、二十个上下游、一堆没人敢动的历史分支的核心交易系统,其上下文的绝大部分从未被写下来。在这种系统里,模型的表现会急剧退化到「能写出漂亮的、错的代码」。这类系统恰恰是 Java 的主场。
3、初级岗位的挤压比高级岗位严重得多
初级工程师的任务组合里,样板代码、基础测试、简单缺陷修复占比最高,这三项正是塌陷最彻底的。而这三项过去还承担着「培养通道」的功能------人是靠写了两年 CRUD 才建立起对系统的直觉的。通道被压缩,会在三到五年后变成一个组织级问题,第十五章会专门讨论。
4、「会用 AI」本身不构成护城河
工具的使用门槛在快速下降,提示词技巧的半衰期以月计。真正拉开差距的不是会不会用,而是你有没有能力判断它给的东西对不对 ,以及你所在的系统是否被改造成了它能发挥作用的形态。前者是个人能力,后者是工程投入,两者都不是靠背几个提示词模板能得到的。
三、四条判据:怎么判断一项能力会不会贬值
(一)判据一:上下文闭合度
1、定义与打分方法
上下文闭合度衡量的是:完成这项任务所需要的全部信息,有多大比例是可以被写进提示词、代码库、文档或工具返回值的。
打分可以很粗糙但必须可操作:把这项任务需要的信息逐条列出来,标记每一条的来源。来源是代码、注释、配置、接口文档、数据库结构的,记为「可写入」;来源是某个人的记忆、某次会议的口头结论、某个上下游团队的习惯、某条没有落到文字的监管要求的,记为「不可写入」。可写入的条目占比就是闭合度。
2、Java 系统里典型的高闭合与低闭合任务
高闭合:把一个 POJO 转换成另一个 POJO;为一个已有接口补全参数校验;按数据库表结构生成实体类与基础查询;把一段 for 循环改写成流式写法;给一个纯函数补单元测试。这些任务所需的信息全部在仓库里。
低闭合:搞清楚「订单状态为什么会有一个叫 PARTIAL_SETTLED 的值,什么情况下能进这个状态」;判断「这个字段现在还有没有下游在读」;决定「这次扣减能不能放在事务里」;回答「运营说的这个『有效用户』和报表里的那个『有效用户』是不是一回事」。这些问题的答案分散在人的脑子里、历史工单里、和外部系统的默契里。
3、闭合度是可以被主动提高的
这是四条判据里唯一一条可以由工程师自己改变的。把口头约定写成契约测试、把状态机画进代码注释、把「为什么这么做」写成决策记录,都是在把不可写入的信息变成可写入的。这项工作本身在过去优先级不高(因为人可以互相问),现在它直接决定了你的团队能从 AI 那里拿到多少产能。第十章会把它单独当成一个架构指标来讲。
(二)判据二:正确性可判定性
1、定义与三个层级
可判定性衡量的是:这项任务的产出是否正确,能否被一个独立的、自动的、快速的机制判定。
第一层是编译器与静态检查能判定的(类型错误、空指针可达性、资源未关闭);第二层是测试能判定的(给定输入是否得到预期输出);第三层是只有生产环境的真实流量、真实数据分布、真实并发才能判定的(性能是否达标、一致性是否成立、长尾行为是否可接受)。
层级越高,判定越慢越贵,人的介入越不可省。
2、可判定性差的任务不能委派,只能协作
一个关键推论:可判定性差的任务,即使模型能做,也不该无监督地交给它做。因为你没有便宜的办法知道它做错了。并发代码是最典型的例子------一段有竞态的代码可能通过一万次单元测试,然后在生产环境的第三天崩掉。在这类任务上,模型的作用应该是「提出候选与提醒风险」,而不是「产出最终答案」。
3、可判定性是可以被设计出来的
和闭合度一样,这一条也不是天生的。给账务系统加一条「借贷必相等」的在线校验,就把一类原本只能靠对账发现的错误变成了可以在秒级判定的错误;给一个重构加一套录制回放的对拍,就把「行为是否等价」从人工判断变成了自动判断。把不可判定的东西改造成可判定的,是 AI 时代最高杠杆的一类工程投入,因为它同时提高了人的效率和 AI 的可用范围。
(三)判据三:后果可逆性
1、四档可逆性
第一档,完全可逆:本地代码改动、未合并的分支、可以随时回滚的无状态服务发布。第二档,代价可控地可逆:已经上线但可以回滚的变更,代价是几分钟的抖动。第三档,部分不可逆:数据库结构变更、数据回填、缓存预热、消息已经投递给下游。第四档,完全不可逆:资金已划出、通知已发给用户、数据已删除、密钥已泄漏、外部系统已收到并处理了你的请求。
2、可逆性决定人在环的位置,而不是决定要不要用 AI
一个常见的误解是「重要的事不能让 AI 做」。更准确的说法是:可逆性决定的是「人在哪一步必须亲自按下确认」,而不是「哪一步不能由 AI 起草」。让模型写一份数据回填脚本完全没问题,问题在于这份脚本执行前必须有人读懂它、在影子库上跑过、确认了回滚方案。人在环的位置应该卡在不可逆的那一步之前,而不是笼统地卡在整件事之前。
3、把不可逆改造成可逆,同样是高杠杆投入
软删除代替硬删除、发件箱模式代替直接调用、双写与影子表代替原地改写、发布加灰度与快速回滚------这些做法的共同点是用一点复杂度和存储成本,换回一个「反悔窗口」。在变更速率提高的前提下,反悔窗口的价值随之上升。
(四)判据四:责任可归属性
1、签字权无法外包
在受监管的行业里,每一次生产变更、每一份对外披露、每一次数据处理,最终都要落到一个具体的人或角色上。模型不能承担法律责任,不能被审计约谈,不能在事故复盘会上解释自己当时怎么想的。因此,任何需要「有人签字」的环节,人都不可能被移出流程。
2、这不是形式主义,它有实质内容
签字这个动作背后是三件实事:签字人事前理解了这个变更的风险边界;事中有能力监控它是否越界;事后有能力在最短时间内把它撤回或止损。一个只是在流程系统里点了「同意」而不具备这三项能力的签字,是假的,而且在事故后会被立刻识别出来。
所以「责任可归属」这条判据带来的不是一个免死金牌,而是一个能力要求:你必须真的看得懂你签的东西。这一点在 AI 产出占比上升之后变得更难,也因此更值钱。
3、责任链的重构是组织级议题
当一次变更里 80% 的代码由模型生成、由一名工程师提交、由另一名工程师评审时,责任怎么分配?多数团队目前的答案是「提交者全责」,这个答案在短期是对的(它保证了有人认真看),但它会随着产出量上升而崩溃------一个人一天认真读不了三千行代码。第十五章会讨论替代方案。

(五)四条判据怎么合成一个档位
1、合成规则
把一项任务在四条判据上分别打「高 / 中 / 低」,然后按下面的规则归档:
- 贬值区:闭合度高、可判定性高、可逆性高、无需签字。四条全绿,这类任务的生成侧价值会归零,人的价值只剩下「定义验收标准」这一点点。
- 重估区:四条中有一到两条是中或低。这类任务不会消失,但完成它的方式会彻底改变------从「亲手做」变成「定义判据、抽样验证、处理异常」。这一区的能力需要重新学,学不会的人会误以为自己的能力贬值了,实际上是形态变了。
- 升值区:有两条以上是低,尤其是闭合度低或不可逆。这类任务的单价会上涨,因为供给(有能力做的人)没有增加,而需求(因为变更速率提高)在增加。
| 档位 | 上下文闭合度 | 可判定性 | 可逆性 | 需要签字 | 价格走势 | 你该做的事 |
|---|---|---|---|---|---|---|
| 贬值区 | 高 | 高 | 高 | 否 | 向零逼近 | 主动交出去 |
| 重估区 | 中或高 | 中 | 中或高 | 视情况 | 先跌后稳 | 主动转换形态 |
| 升值区 | 低 | 低或中 | 低 | 是 | 持续上行 | 主动多要这类活 |
2、一个必须强调的动态性
档位不是永久的。今天在重估区的任务,可能因为你把上下文写下来了、把判据自动化了,明年就滑进贬值区------这不是坏事,这正是你应该主动做的事。把自己的重复工作推进贬值区,然后去做升值区的事,是唯一正确的姿势。担心「写下来就被替代了」而故意保留信息不对称,是短期自保、长期自杀的策略:信息不对称保护不了你三年,而它会让你三年都在做同一件低价值的事。
3、判据打分的实操建议
不要试图给全部任务打分,那会变成一次没有产出的形式主义。正确做法是:拿最近三个月你实际做过的事,挑出耗时最多的八件,只给这八件打分。八件里通常会有三到四件落在贬值区------那就是你下个季度应该想办法自动化或委派掉的;有一到两件落在升值区------那就是你应该主动多要的活。

四、把 Java 工程师的日常任务投影到判据上
(一)贬值区:六类应该主动交出去的任务
1、清单与判据得分
第一类,结构化转换代码。实体到数据传输对象、数据传输对象到视图对象、两个版本接口之间的字段映射、枚举与编码的互转。四条判据全高:所有信息都在类型定义里,正确性用一个往返测试就能判定,写错了编译期就报,没有任何需要签字的成分。
第二类,规范驱动的骨架代码。有接口描述文档就能生成的控制器与客户端、有建表语句就能生成的持久层基础方法、有协议定义就能生成的序列化代码。这一类的正确性由规范本身保证,人的价值全部前移到「规范写得对不对」。
第三类,机械重构 。改名、提取方法、内联变量、调整包结构、把匿名内部类换成 Lambda、把 Date 换成 java.time、批量替换过时的 API。这类工作的判据是「行为等价」,而行为等价可以用测试与字节码比对来判定。
第四类,基础用例的单元测试。对纯函数、对无副作用的工具类、对边界清晰的解析器写测试。注意限定语:一旦被测对象有外部依赖、有并发、有时间语义,这项任务立刻离开贬值区,理由见第七章。
第五类,模板化的说明性文档。接口说明、变更日志、发布公告、依赖清单、从代码反推出来的时序描述。这些文档的信息源全部在仓库里,人写它纯粹是在做搬运。
第六类,常规依赖升级的机械部分。读发布说明、找出被移除的 API、逐个替换、跑一遍测试。注意「机械部分」这个限定:判断这次升级值不值得做、有没有传递性的行为变化、要不要为它单独排一次发布,不在贬值区。
2、交出去之前必须补的一件事
上面六类之所以能交出去,前提是你有办法在三十秒内知道它做错了。如果你的项目连一次可靠的构建加测试都跑不起来,或者跑一次要四十分钟,那么这六类任务在你这里并不真的处于贬值区------你只是把「写」的时间换成了「反复读和猜」的时间。
所以对多数团队而言,进入贬值区的入场券是:一条五分钟以内能跑完的、结果稳定的、覆盖了主干行为的验证流水线。没有这条流水线,谈委派都是空的。
3、不要为了「显得没被替代」而抓着不放
一个真实存在的心理陷阱是:明知道这些活可以交出去,但因为它们是自己「熟练且有安全感」的部分,于是继续亲手做,并用「AI 写的我不放心」来合理化。判断这种合理化是否成立,只需要问一句:你不放心的具体是哪一条判据?如果说不出来,那就是习惯,不是判断。

(二)重估区:五类不会消失但形态彻底改变的任务
1、测试:从「写用例」到「设计判据」
写测试代码这个动作贬值了,但决定测什么这件事升值了。一套测试的价值不取决于它有多少行、覆盖率多少,而取决于它能不能在你改错的时候红。让模型生成的测试往往覆盖率漂亮、断言空洞,因为它不知道你们系统真正会在哪里出事。
新的工作形态是:工程师给出失效模式清单与不变式,模型把它们展开成可执行的用例,工程师抽查其中最关键的三到五条,并额外手写那些「只有懂这个业务才想得到」的用例。
2、代码评审:从「看写法」到「找会错的输入」
风格、命名、格式、常见坏味道,这些评审意见的生成成本已经归零,应该全部前移到静态检查与生成阶段。人的评审必须升级到另一个问题上:这段代码在什么输入、什么并发、什么故障下会给出错误结果,而现有测试发现不了?
这是一个明显更难的问题,需要评审者对系统有全局理解。这也是为什么在 AI 产出占比上升之后,「谁来评审」变成了一个比「谁来写」更紧张的资源问题。
3、性能分析:从「凭经验猜」到「设计可观测性并读证据」
模型对 JVM 性能问题的回答质量参差不齐,因为这类问题的答案高度依赖现场:同样是「接口变慢」,可能是 GC、可能是锁竞争、可能是连接池耗尽、可能是下游抖动、可能是某个正则回溯。它能给出的是「统计上常见的原因排序」,而你需要的是「这一次的原因」。
新的工作形态是:工程师负责让现场留下足够的证据(分层耗时、线程状态、GC 日志、连接池指标、慢查询),并负责读懂这些证据;模型负责在你给出证据之后帮你做假设枚举与文档检索。这个分工非常清晰,第八章会展开。
4、技术选型:从「比功能」到「比失效模式与退出成本」
功能对比表的生成成本归零了,任何人都能在五分钟内拿到一张十行八列的对比。但选型真正的难点从来不是功能对比,而是三个问题:这个东西在我们的负载特征下会怎么坏;坏了之后我们有没有人能修;三年后要换掉它需要付出什么。这三个问题的答案不在文档里。
5、库表与接口设计:从「画字段」到「定不变式与演进路径」
生成建表语句和接口定义已经很便宜。但一个表设计的好坏,取决于它的唯一键约束是否真的表达了业务上的唯一性、它的状态字段是否允许非法迁移、它在数据量涨一百倍之后要怎么分、它的字段被删除时下游怎么办。这些判断需要对业务演化的预判,而预判来自经验。

(三)升值区:七类定价权所在的任务
1、清单
约束发现与需求证伪:把业务方没说出口的约束挖出来,并在动手之前证明某些需求彼此矛盾或者根本不该做。
领域建模与口径统一:让「一个订单」「一个有效用户」「一笔已完成的交易」在全公司只有一个定义,并让这个定义落到代码和数据里。
系统边界与不变式设计:决定哪些东西必须在一个事务里、哪些必须异步、哪些必须幂等、哪些绝不能重试,并把这些决定表达成代码能检查的形式。
故障归因:在信息不完整、时间紧迫、多方推诿的现场,用有限的证据收敛到一个可行动的结论。
不可逆操作的治理:资金、数据删除、对外通知、密钥、合规披露------设计这些操作的授权、闸门、审计与止损路径。
容量与成本判断:把技术方案折算成机器、带宽、人力和风险敞口,并在几个都能跑的方案里选出代价最合适的那个。
跨团队的技术协商:在两个都不想改的团队之间找到一个双方都能接受的契约,并让它被写下来。
2、这七类的共同结构
它们共享同一个结构:输入不完整、判据需要自己造、后果由自己承担。这正好是四条判据里最差的那几格。模型在这些任务里不是没有用,它是极好的枚举器、检索器和草稿机;但收敛到一个决定并为之负责的那一步,没有别人可以替你走。
3、供给为什么不会增加
一个自然的疑问是:既然这些能力这么值钱,为什么供给不会跟上?因为这些能力的养成路径正在被压缩。过去一个人是通过写两年 CRUD、排三年线上问题、被两次事故打醒,才慢慢长出这些判断的。当基础任务被大量交给模型之后,这条养成路径变窄了。供给端的收缩与需求端的扩张同时发生,价格自然上行。这对已经具备这些能力的人是利好,对刚入行的人是一个必须被正视的结构性难题,第十七章会给出应对。

(四)三张清单之外:一个容易被误判的灰色地带
1、「看起来在贬值区,其实不是」的三种任务
第一种,看似机械的数据订正。写一条 UPDATE 语句是贬值区的活,但判断「这条语句会影响多少行、这些行里有没有正在被并发修改的、执行完之后哪些缓存要失效、如果发现改错了怎么改回来」,是升值区的活。这两者经常被打包成一个任务,于是整体被误判。
第二种,看似标准的接口对接。按文档写一个客户端是贬值区的活,但判断「这个下游超时了我该重试还是该失败、它的幂等语义到底是什么、它返回的这个错误码在什么情况下出现」,需要真实的对接经验和对文档不可信程度的判断。
第三种,看似简单的配置修改。改一个线程池大小、一个超时时间、一个缓存过期时间,动作是一行,判断是一整套容量模型。
2、拆开再判定
对付灰色地带的方法只有一个:把任务拆到「单一判据」的粒度再打分。一个任务如果在四条判据上给不出一致的评分,说明它还不是一个任务,而是几个任务的打包。拆开之后,机械的那部分交出去,判断的那部分自己做,效率和安全同时到位。
五、编码能力的重估:从「写得出」到「说得清、验得准」
(一)「写得出」与「说得清」的分离
1、两种能力过去被绑在一起
在没有生成工具的年代,能把一个复杂并发控制写对的人,几乎必然也理解它为什么对------因为不理解就写不出来。写的能力与理解的能力天然绑定,前者是后者的可靠代理指标,面试考手写代码在那个年代是合理的。
现在这两种能力被解绑了。一个人可以在完全不理解 happens-before 的情况下,产出一段用了 volatile、CountDownLatch 和 ConcurrentHashMap 的代码,而且它在测试里能跑。代理指标失效了。
2、失效带来的两个后果
对个人:如果你的能力自我评估还建立在「我能写出来」上,你会严重高估自己。检验方式很简单------把你刚生成的那段代码里的每一个关键决定拿出来问自己「换成另一种写法会怎样、为什么不用那种」。答不上来三个以上,说明这段代码你只是拥有它,并不理解它。
对组织:招聘和晋升如果还在考「写得出来」,会大量选进无法承担验证与担责工作的人。这个问题的显性化通常滞后半年到一年,直到第一次由生成代码引发的生产事故。
3、新的能力代理指标
更可靠的三个替代指标:能不能在读一段陌生代码时指出它的失效输入 ;能不能在一个方案被否掉时说清楚被否的具体理由 ;能不能把一个模糊需求转写成一组可判定的验收条件。这三项都不能靠生成工具代劳,也都能在四十分钟的交流中被观察到。
(二)代码生成的四层,以及正确率与验证成本的反向关系
1、四层划分
语法层:语言本身的合法性与惯用法。正确率极高,验证成本极低(编译器)。
框架层:Spring、MyBatis、JPA、消息中间件客户端等框架的正确使用方式。正确率中等偏高,验证成本中等------很多错误编译期不报、单测里因为 Mock 掉了框架而暴露不出来,要到集成环境才现形。
系统层:并发、事务边界、幂等、超时与重试、缓存一致性、资源生命周期。正确率明显下降,验证成本高------很多错误只在特定时序下出现。
业务层:这段逻辑符不符合业务规则、口径对不对、边界条件业务上怎么定义。正确率完全取决于你把业务写清楚了多少,验证成本最高------经常只有业务方看到结果才知道错了。
2、反向关系的含义
层级越往上,生成的正确率越低,而验证成本越高。这两条曲线的乘积就是「这一层的风险」。风险的峰值不在最上层也不在最下层,而在框架层和系统层之间------那里的代码看起来最正常,错得最隐蔽,测试最容易漏。这也是下一章要专门列举的地方。
3、由此推出的审阅顺序
评审一段生成代码时,正确的注意力分配不是从上往下读,而是按层级从高到低分配精力:先问业务口径对不对,再问系统级约束有没有被违反,再看框架用法,最后才看代码风格。多数人的习惯正好相反,于是把注意力花在了机器早就能管的那一层。

(三)仍然必须自己写(或逐行读懂)的四类代码
1、涉及资金与权益计算的代码
一分钱的舍入方向、一次重复入账、一个漏掉的冲正,其代价远大于写这段代码省下的时间。这类代码的每一行都应该被人逐行读过,并配有独立于实现的对账机制。
2、涉及并发与共享状态的代码
原因在第六章第四节详述:这类错误的可判定性最差,通过测试不代表正确。
3、涉及安全边界的代码
鉴权、越权校验、加解密、签名验签、敏感数据脱敏、外部输入的反序列化。生成代码在这里的典型问题不是写错,而是写了一个「能跑通正常流程」的版本,而把攻击面留在了异常分支。相关实证研究反复发现,在使用编码助理的情况下,开发者产出的代码在安全性上未必更好,而对自己代码安全性的信心却明显更高------这个「信心与实际的反向差」本身就是风险。
4、涉及不可逆副作用的代码
删除、划账、对外发送、状态终态迁移。这类代码不仅要自己写,还要专门为它设计「执行前的确认」和「执行后的补偿」。
| 代码类别 | 为什么不能只靠委派 | 最低验证要求 |
|---|---|---|
| 资金与权益计算 | 一分钱的舍入方向、一次重复入账的代价,远大于写它省下的时间 | 逐行人工阅读 + 独立于实现的对账机制 |
| 并发与共享状态 | 可判定性最差:通过测试不代表正确 | 不变式断言 + 并发压力测试 + 尽量用设计消除并发 |
| 安全边界 | 典型问题不是写错,而是「正常流程能跑通、攻击面留在异常分支」 | 越权用例与恶意输入用例必须人工设计 |
| 不可逆副作用 | 错了没有第二次机会 | 执行前确认材料 + 执行后补偿路径 + 审计留痕 |
(四)读代码的能力反而更贵了
1、读的总量在上升
产出变多,评审量上升;模型会引用你没读过的库和模式,理解成本上升;一次委派回来的变更经常横跨五六个文件,需要在脑子里重建它的整体意图。读的能力从一项辅助技能变成了主线技能。
2、读的方式也要变
过去读代码是线性的:从入口跟到出口。现在更有效的方式是假设驱动:先根据变更描述列出三到五个「如果他做错了,最可能错在哪」的假设,然后带着假设去定点查证。这种读法的效率是线性读法的数倍,但它要求你先有失效模式的储备------又回到了同一件事上。
3、把模型用在读上,收益大于用在写上
一个被低估的用法:让它解释一段你不熟悉的历史代码、画出调用关系、列出某个字段的全部写入点、总结一次大变更的意图。这些任务闭合度高(信息都在仓库里)、可判定性尚可(你可以抽查)、完全可逆(读不改),是四条判据上最适合委派的一类。很多人把大量精力花在调教它写代码,却没有用它来解决自己最耗时的读代码问题。
六、AI 生成的 Java 代码最常在哪些地方出错
(一)语言与类库层的高频陷阱
1、精度与数值
new BigDecimal(0.1) 与 BigDecimal.valueOf(0.1) 的区别、除法不指定舍入模式导致的 ArithmeticException、用 double 存金额、用 == 比较包装类型、Integer 缓存范围之外的比较失败、除法的舍入方向与业务约定不一致。生成的代码在这些地方经常「看起来很专业」(用了 BigDecimal)但细节是错的。
2、时间与时区
SimpleDateFormat 被声明成静态字段共享(它不是线程安全的)、LocalDateTime 与 Instant 混用、数据库存的是 UTC 而代码按系统默认时区解析、跨日结算的「今天」边界没有明确定义、夏令时地区的时间加减。时间问题的特点是平时都对,在特定日期集中爆发。
3、集合与相等性
自定义对象作为 HashMap 的键却没有正确实现 equals 与 hashCode、在遍历中修改集合、Arrays.asList 返回的固定长度列表被 add、subList 的视图语义、Collectors.toMap 遇到重复键抛异常、流式操作里对可变外部状态的写入。
4、异常与资源
吞掉异常只打一行日志、把受检异常包成 RuntimeException 后丢失原始堆栈、在 finally 里 return 覆盖了异常、没有用 try-with-resources 导致连接泄漏、捕获 Exception 的同时把 InterruptedException 也吃掉却不恢复中断标志。
(二)框架语义层:最危险的一层
1、事务相关的四个经典失效
1.1 自调用导致事务注解失效
同一个类里 A 方法调用带 @Transactional 的 B 方法,调用不经过代理,事务根本没开。这个失效的隐蔽之处在于:代码看起来完全正确,注解也确实写了,只有在真正发生异常需要回滚时才会暴露。生成代码在按「一个方法只做一件事」拆分方法时,极容易制造出这个结构。
1.2 传播行为选错
需要「主流程失败时不影响日志记录」的场景用了默认传播,结果日志记录的异常把主事务一起回滚;或者反过来,需要与主流程共存亡的操作用了 REQUIRES_NEW,主流程回滚了它却留下了。传播行为的选择依据是业务上的「这两件事要不要同生共死」,而这个信息通常不在代码里。
1.3 事务边界包住了远程调用
一个方法里既有数据库写入又有远程调用与消息发送,事务的持有时间被外部依赖的延迟绑架。平时下游响应 20 毫秒,一切正常;下游抖动到 2 秒时,数据库连接被长时间占用,连接池在几十秒内耗尽,故障从一个下游扩散成整个服务不可用。
1.4 在事务提交之前发消息或写缓存
事务回滚了,消息已经出去了,下游按「已成功」处理,两边状态永久分叉。正确做法是发件箱模式或事务同步回调,但生成代码几乎总是把发送写在业务逻辑的自然位置上------也就是紧挨着数据库操作的那一行。
java
// 生成代码里非常常见的结构:三个问题同时存在
@Service
public class OrderService {
public void placeOrder(OrderCmd cmd) {
validate(cmd);
doPlace(cmd); // ① 自调用:@Transactional 不生效
}
@Transactional
public void doPlace(OrderCmd cmd) {
orderRepo.insert(cmd.toOrder());
inventoryClient.deduct(cmd.getSkuId(), cmd.getQty()); // ② 事务里做远程调用
mqTemplate.send("order.created", cmd.getOrderNo()); // ③ 提交前发消息
}
}
上面这段代码能编译、能通过把 inventoryClient 和 mqTemplate 都 Mock 掉的单元测试、在测试环境低并发下也跑得好好的。它在生产环境的表现是:库存扣了订单没落库、或者订单回滚了下游已经收到消息、或者高峰期数据库连接池被 RPC 超时拖垮。三种故障都不会在提交代码的那天出现。

2、代理与生命周期
@Async 同类调用同样失效;@Cacheable 的键生成没有考虑参数对象的 equals;@PostConstruct 里使用了尚未初始化完成的依赖;单例 Bean 里放了有状态的成员变量;@Value 注入的配置在构造器里读不到;条件装配导致本地跑得通线上少了一个 Bean。
3、配置与自动装配
生成代码倾向于给出「教科书式」的配置,而实际项目往往有一层公司内部的启动器与约定。表现是:加了一个看起来正确的配置类,覆盖了公司框架的默认行为,本地无感,上线后某个链路的追踪、鉴权或者序列化行为悄悄变了。
(三)数据与持久层
1、查询与索引
生成的查询语句在语法上无懈可击,但对索引没有概念:在索引列上套函数、用 LIKE '%xx'、隐式类型转换导致索引失效、深分页用 LIMIT 1000000, 20、IN 里放了几千个值、没有分页的全表查询被写成「先查出来再在内存里过滤」。
2、N+1 与批量
在循环里逐条查询、逐条更新、逐条调用远程接口。这是最常见也最容易被测试环境掩盖的问题------测试数据只有十条,生产数据有十万条。
3、幂等与并发更新
生成的更新逻辑常见「先查后改」而没有版本号或条件更新,两个并发请求都读到旧值,后写的覆盖先写的。或者以为「加了唯一索引就幂等了」,但没有处理唯一键冲突时应该走的分支(是当成成功返回,还是当成失败?这两种选择对上游的语义完全不同)。
4、迁移脚本
生成的建表与变更语句经常缺少:大表加字段的在线变更方式、加索引的锁影响、字段类型变更的兼容窗口、回滚脚本。这些不是语法问题,是运维现实问题。
(四)并发与资源层:可判定性最差的一层
1、错误的形态
竞态条件、可见性问题(缺 volatile 或错误使用双重检查)、死锁(加锁顺序不一致)、活锁与饥饿、线程池的拒绝策略选错、CompletableFuture 用了默认的公共线程池导致互相拖累、虚拟线程里执行了阻塞在 synchronized 上的代码、ThreadLocal 在线程池复用场景下没有清理导致数据串到别的请求。
2、为什么这一层最危险
因为测试通过与正确之间没有关联。一段有竞态的代码在单线程测试里百分之百通过,在压测里可能一万次里错一次,在生产环境高峰期每分钟错三次。你不能通过「跑一遍看看」来判定它,而「跑一遍看看」恰恰是委派模式下最主要的验证手段。
3、正确的处理方式
对并发代码,把模型的角色限定为三种:帮你回忆某个并发工具的语义细节;帮你枚举「这段代码可能的交错执行顺序」;帮你把一段并发逻辑改写成更容易验证的形式(例如把共享可变状态换成不可变对象加原子引用)。最终的正确性判断必须由人给出,并且应该配上更强的手段:不变式断言、并发压力测试、以及尽可能地用设计消除并发(单线程处理某个分区、用数据库的条件更新代替应用层锁)。

(五)为什么这些错误单元测试发现不了
1、Mock 掉了出错的地方
生成的单元测试倾向于把所有外部依赖 Mock 成「返回正常值」。而上面列举的框架层与数据层问题,恰恰全部发生在被 Mock 掉的那个边界上。测试通过只证明了「在假设依赖行为完美的情况下,业务分支是通的」。
2、断言写在了不该断言的地方
一种典型的坏味道是断言 Mock 被调用了几次(这只是把实现细节复述了一遍),或者断言返回值不为空。这类断言在代码被改错之后仍然是绿的。
3、测试数据规模与生产不在一个量级
N+1、深分页、大对象序列化、内存占用,这些问题在十条测试数据下全部不可见。
4、时序与并发不在测试模型里
绝大多数单元测试是单线程、确定性、瞬时完成的。而生产环境的错误来自多线程、非确定性、跨越时间窗口。
这四条合起来解释了一个关键结论:在生成代码占比上升的情况下,如果验证手段不升级,缺陷逃逸率必然上升。 这就是下一章的主题。


七、验证能力:从写测试到设计判据
(一)判据是什么,为什么它比测试更根本
1、一个定义
判据(也叫测试预言)是一种独立于被测实现的、能够回答「这个产出是否正确」的机制。测试是判据的一种实现形式,但不是唯一形式,也常常不是最好的形式。
区分这两者很重要:写测试是在实现判据,而设计判据是在决定「什么叫对」。前者的成本已经塌陷,后者没有。当有人说「让 AI 写测试」时,如果判据本身没有被想清楚,那么产出的只是一堆把当前实现行为固化下来的断言------实现错了,测试也跟着错,而且以后没人敢改。
2、判据缺失的三个症状
第一,测试是在代码写完之后照着代码写的。这种测试的信息量为零,它只能防止未来的回归,不能发现当前的错误。
第二,没有人能说清楚某个模块「什么情况下算坏了」。问一个团队「你们的对账系统出错了会怎么被发现」,如果答案是「客服会反馈」,那就是判据缺失。
第三,线上问题的第一发现人长期是业务方或用户。这是判据缺失最直接的度量。
3、判据设计是 AI 时代最高杠杆的技能
理由是结构性的:生成侧的产能已经过剩,瓶颈全部在判定侧;而判定侧的杠杆倍数极高------一条好的不变式断言可以持续拦截未来两年里所有触碰它的错误,无论那些错误是人写的还是模型写的。你每设计一条可自动执行的判据,就把一片原本不可委派的区域变成了可委派的。
(二)判据的五种来源
1、规范与契约
接口定义、协议描述、状态机定义、数据库约束。这一类判据的好处是可以直接机器化:契约测试、模式校验、状态迁移表驱动的断言。前提是规范真的被写下来了,而且被当成唯一真相。
2、不变式
系统在任何时刻都必须成立的性质。账务系统的「借贷相等」、库存系统的「可用量加锁定量等于总量」、订单系统的「不存在两条同一外部单号的记录」、缓存的「缓存里有的值必须与数据库一致或已过期」。
不变式的威力在于它不依赖具体用例:它不是在检查某一次调用对不对,而是在检查系统整体有没有偏离。它可以同时用在测试里、在预发环境的巡检里、在生产的对账任务里,甚至在关键路径上以断言形式在线执行。
3、参照实现与历史行为
重构与迁移场景下最有效的判据:拿新旧两套实现跑同一批输入,比对结果。录制生产流量回放到新版本上、双写两套存储后比对差异、保留一个慢但显然正确的实现作为对照。这类判据的建立成本中等,但收益极高,尤其是在「把一段没人看得懂的历史逻辑重写一遍」这种任务上------而这种任务恰恰是最想交给 AI 的。
4、性质与元关系
不检查具体输出值,而检查输出应该满足的性质:编码后再解码应该等于原值;排序结果的长度不变且有序;同一请求重复提交结果不变(幂等);输入放大一倍输出不应放大十倍。这类判据可以用基于性质的测试框架自动生成大量随机输入去撞,特别擅长发现人想不到的边界。
5、人的领域判断
有一部分判据无法机器化:这个文案是否会引起误解、这个风控策略是否过于激进、这个降级行为对用户是否可接受。它们只能由人给出,而且应该被明确标注为「人工判据」,进入发布检查清单,而不是假装它们不存在。

(三)验证阶梯的七级
1、七级从便宜到昂贵
- 第一级,编译与静态分析。类型、空值可达性、资源泄漏、常见坏味道、依赖合规。特点是秒级、零成本、可以对每一次生成结果无条件执行。
- 第二级,单元测试。纯逻辑、边界值、异常分支。
- 第三级,契约与模式校验。接口的请求响应结构、消息体结构、数据库约束、状态迁移合法性。
- 第四级,集成测试。带真实数据库、真实消息中间件的容器化测试。前面提到的框架层与数据层错误,绝大部分要在这一级才现形。
- 第五级,对拍与回放。新旧实现比对、生产流量录制回放、双写比对。
- 第六级,影子与灰度。让新逻辑在生产环境处理真实流量但不产生副作用,或者只对一小部分流量产生副作用。
- 第七级,在线不变式与对账。持续运行的一致性校验,是最后一道也是唯一能覆盖「未知未知」的防线。
2、阶梯的使用原则
尽可能把判定下沉到便宜的层级。每一个能在第一级发现的问题,就不该留到第四级;每一个能在第四级发现的,就不该留到第七级。层级每上升一级,发现同一个缺陷的成本大致上升一个数量级。
每一级都必须有明确的准入与准出。「集成测试跑通」不是准出标准,「集成测试覆盖了这次变更涉及的三条主链路且全绿」才是。
3、生成代码对阶梯的具体要求
在 AI 产出占比高的团队里,这条阶梯的前四级必须是全自动、快速、每次提交都跑的,否则委派模式无法成立。第五级到第七级则决定了你能委派多大颗粒度的任务:只有第一到四级的团队,只能委派单个方法级的改动;建立了第五级的团队,可以委派整个模块的重写;建立了第六七级的团队,才敢让自动化流程直接推进到生产。
验证阶梯的高度,直接决定了这支团队能从 AI 拿到多少产能。 这是一个可以量化、可以立项、可以排期的工程目标,比「提升团队 AI 使用率」这种指标有意义得多。

(四)AI 生成的测试的四种坏味道
1、同义反复
测试只是把实现逻辑用另一种语法重写了一遍。典型形态是:实现里写 if (a > b) return X,测试里就断言「当 a 大于 b 时返回 X」。如果实现的条件写反了,测试也会跟着写反。识别方法:把实现故意改错一处,看测试是否变红。这就是变异测试的思路,值得在关键模块上真正跑起来。
2、Mock 到只剩下 Mock
被测方法的每一个依赖都被打桩,断言的内容是「某个桩被调用了几次、参数是什么」。这种测试在重构时必然大面积失败(因为它固化了实现细节),却在逻辑写错时保持绿色。
3、断言过弱
断言「结果不为 null」「列表非空」「没有抛异常」。这类断言的通过率接近百分之百,信息量接近零。
4、覆盖率幻觉
行覆盖率很高,但分支、边界、异常路径没有覆盖;或者覆盖了代码却没有断言(执行到了但没检查结果)。覆盖率是一个「低了一定有问题、高了不能说明问题」的指标,把它当成 KPI 会直接催生这种幻觉,而在生成工具的加持下,刷覆盖率的成本已经低到可以忽略------这意味着覆盖率作为质量指标已经彻底失效。
5、正确的用法
把模型用在测试上的正确姿势是:人给出失效模式清单和不变式,模型负责展开为大量用例、准备测试数据、补齐边界组合;人负责抽查、负责补上「只有懂业务才想得到」的那几条、负责定期跑变异测试来验证这套测试本身还有没有效力。

(五)可判定性要设计进系统,而不是事后补
1、三类改造
结构化改造:把散落的副作用集中到少数出口(发件箱表、统一的对外调用网关),这样「有没有多发一次」就有了唯一的查证点。
语义化改造:给每一次业务动作分配可追踪的业务标识(外部单号、幂等键、请求标识),并让它贯穿全链路日志与数据表。没有这个标识,任何事后核对都要靠时间戳和金额去猜。
在线校验改造:把最重要的三到五条不变式做成常驻任务,按分钟级或小时级在生产上跑,偏差超过阈值直接告警。这类任务的实现成本通常不到一周,而它带来的效果是把「几个月后被用户发现」变成「二十分钟内被自己发现」。
2、优先级排序
不要一次性铺开。排序方法是:按「这一类错误发生时的后果」乘「过去一年它实际发生过几次」,从高到低做。多数团队做完前三项就能覆盖八成风险。
3、这项投入的第二重收益
除了减少事故,它还有一个直接的经济收益:每提高一分可判定性,就多一片区域可以安全地交给自动化。这项收益在传统的成本核算里看不见,在 AI 时代必须被算进立项理由。

八、调试与归因:现场是模型猜不出来的地方
(一)模型给的是统计上常见的答案,现场是你这台机器上的答案
1、两种答案的区别
问「Java 服务响应时间突然从 50 毫秒涨到 800 毫秒可能是什么原因」,能得到一份质量相当高的清单:GC 停顿、锁竞争、连接池耗尽、慢查询、下游抖动、线程池排队、大对象序列化、日志同步写盘、网络重传。这份清单有价值,它是一个不错的假设空间。
但真实的排障需要的是收敛:在这九个假设里,用现有证据排除掉七个,把剩下两个用一次定向观测分开。收敛依赖的是这台机器此刻的证据,而证据不在模型的上下文里------除非你把它放进去,而这需要你先知道该采集什么。
2、一个具体的分工
会用工具的人和不会用工具的人,在排障上的差距体现在这里:
不会用的人:把现象描述给模型,拿到九条可能原因,然后一条条去试,试到第五条时故障已经持续四十分钟。
会用的人:先看分层耗时确定慢在自己还是下游,再看 GC 日志排除停顿,再看线程栈确定是排队还是阻塞,三步之内把假设空间从九个压到两个,然后把这两个的证据贴给模型,让它帮忙回忆某个具体参数的语义、检索某个已知缺陷、生成一段定位脚本。
差距不在工具,在于有没有一条自己的收敛路径。
3、这项能力为什么在升值
变更速率提高、生成代码占比提高,两者叠加的直接后果是线上异常的频次上升、且异常的成因更难从代码意图倒推(因为写它的不是你)。同时,能快速收敛的人数量没有增加。这是一个典型的供需剪刀差。

(二)归因回路的五步
1、第一步:统一口径
在动手之前先问清楚「变慢」指的是什么:是平均值、95 分位还是 99 分位?统计口径是客户端观测还是服务端观测?分母是全部请求还是某一类?时间窗口是多长?
大量排障时间浪费在这一步的缺失上:两个人对着两张不同口径的图争论,而两张图都是对的。
2、第二步:确定变更集
「什么变了」是命中率最高的一个问题。自己的发布、依赖的发布、配置变更、数据量增长、流量结构变化、上游行为改变、定时任务、外部环境(证书过期、磁盘满、节点重启)。把变更集按时间对齐到现象的起点,通常能直接圈定范围。
3、第三步:分层定界
按「客户端 → 网关 → 应用 → 中间件 → 数据库 → 下游服务」逐层看耗时归属,把问题定位到某一层。这一步的前提是每一层都有可比的耗时数据------这是平时的可观测性投入在此刻兑现。
4、第四步:证据充分性检查
在下结论之前问自己:这个结论能解释全部现象吗?有没有反例(比如「是 GC 导致的」,但那台没有发生 Full GC 的机器同样变慢了)?如果我的结论是对的,还应该能观测到什么,我看到了吗?
这一步是区分「猜对了」和「归因了」的分水岭。跳过它的代价是:处置动作做了,故障没好,而你已经用掉了所有人的耐心。
5、第五步:形成可行动的结论
结论必须包含三部分:直接原因、处置动作、以及「如果处置无效下一步做什么」。只有原因没有动作的结论在故障现场没有价值。
(三)JVM 现场的六类证据
1、六类证据各自回答什么
分层耗时与链路追踪 回答「慢在哪一段」;GC 日志与内存指标 回答「有没有停顿、内存是否在持续增长」;线程栈快照 回答「线程在等什么、有没有阻塞在同一把锁上」;堆转储 回答「什么对象占了内存、被谁引用」;CPU 采样与火焰图 回答「时间烧在哪个方法上」;中间件与连接池指标回答「资源是否耗尽、排队多长」。
2、采集的时机决定证据的价值
这六类证据里有四类是瞬时的:线程栈、堆转储、CPU 采样、连接池瞬时状态。故障过去之后再采集,拿到的是恢复后的现场,价值接近零。所以真正决定排障效率的,是有没有在故障发生的那几分钟内把该抓的抓下来。
这带来一个非常实际的建议:把「故障现场自动采集」做成一个按钮或者一条自动触发规则,而不是每次靠人在慌乱中回忆命令行参数。这件事本身可以完全交给 AI 去写,闭合度高、可逆、可判定。
3、证据与模型的配合方式
把原始证据(GC 日志片段、线程栈、火焰图的文本形式、慢查询执行计划)交给模型做初步归类和异常点标注,效率很高;让模型在没有证据的情况下猜原因,效率很低。这个分界线值得记住:模型擅长在给定证据下做解释与检索,不擅长在没有证据时做判断。

(四)把 AI 用在排障上的四种正确姿势与两种错误姿势
1、四种正确姿势
一是证据解读 :把 GC 日志、线程栈、执行计划贴进去,让它标注异常点和给出解释候选。二是知识检索 :某个框架参数的确切语义、某个版本的已知缺陷、某个错误码的含义。三是脚本生成 :临时的日志聚合命令、数据核对语句、批量采集脚本。四是复盘撰写:在你给出时间线和结论之后,让它整理成规范的复盘文档。
2、两种错误姿势
一是无证据猜测 :把一句「接口变慢了」丢进去要答案,然后按它给的顺序盲试。二是让它直接生成处置命令并执行:重启、扩容、清缓存、改配置、执行数据订正。这些动作大多是不可逆的,属于必须人在环的类型------生成可以,执行前必须有人读懂并确认影响面。
九、架构能力的重估:从画图到定边界与不变式
(一)架构工作里贬值的那一半
1、图与文档的生成
架构图、时序图、部署图、组件说明、技术方案模板,这些产出物的生成成本已经很低。一个能读懂仓库的助手可以直接从代码反推出相当准确的组件关系图,而且比人画的更新更及时。
2、方案的枚举与对比
「这个问题有几种做法」这个环节,模型的表现优于多数人的临场回忆------它不会遗漏那些你没用过但确实存在的方案。把它当成方案空间的枚举器,是一个很划算的用法。
3、规范的编写与检查
编码规范、接口规范、命名约定的文本编写,以及把这些规范落成静态检查规则,成本都已经大幅下降。这意味着「团队有没有规范」不再是一个借口问题,而纯粹是一个是否愿意做的问题。
(二)架构工作里升值的那一半
1、定边界
哪些能力归哪个服务、哪些数据归谁所有、哪些调用允许同步哪些必须异步、哪两个模块之间只允许通过契约通信。边界的本质是对未来变化的预判:把大概率一起变的放在一起,把大概率独立变的分开。这个预判来自对业务演化路径的理解,而业务演化路径是没有写下来的。
2、定不变式
前面第七章已经讲过不变式作为判据的价值。在架构层面,不变式还承担另一个角色:它是团队之间的共同语言,也是防止系统随时间腐化的锚。一个写下来的不变式(「同一笔外部单号在系统内最多产生一条记录」)会被写进代码断言、写进对账任务、写进接口文档、写进新人培训,它比任何架构图都更能约束实现。
3、定演进路径
一个架构决定的好坏,很大程度上取决于它留下的退出成本。选一个组件的时候要同时想清楚:三年后要换掉它,需要改多少处代码、迁移多少数据、协调多少团队。这个判断需要经验,且几乎不可能从公开资料里查到。
4、抑制熵增变成了第一职责
生成成本下降带来一个副作用:代码总量的增长速度提高了,而重复实现、抽象泄漏、依赖膨胀的增速比代码总量更快。原因很直接------生成一段新代码比找到并复用一段已有代码更省事,而模型在缺少全局视野时倾向于「就地实现」。
于是架构师的工作重心必须前移到三道抑制闸门:一,同类能力必须收敛到唯一实现 (工具类、客户端封装、通用校验);二,跨模块调用必须走显式契约 ,禁止直接依赖内部类;三,新增依赖必须有准入,包括许可证、维护活跃度、传递依赖体积与安全公告响应速度。
这三道闸门在过去靠人的自觉与评审,现在必须尽可能变成自动检查,因为提交量已经超出了人工评审的处理能力。

(三)技术选型判据的重写
1、旧判据的失效
「学习成本低」「社区活跃」「文档齐全」这三条传统判据的权重在下降。原因是学习成本已经被大幅摊薄------一个陌生框架的上手时间从两周变成两天,文档可以被即时检索和解释。这意味着为了「团队熟悉」而选择一个明显不合适的技术,理由变弱了。
2、新判据的三条
一,失效模式是否清晰且可观测。这个组件坏的时候会怎么坏,有没有指标能提前发现,出问题时能不能拿到证据。这一条的权重应该被显著提高,因为它直接决定了排障成本,而排障是升值区的工作,很贵。
二,退出成本是否可估。数据能不能导出、协议是否标准、有没有可替代实现。
三,能否被写进上下文。这是一条新判据:一个技术选择如果它的关键约束可以被清晰地写成规则文件、契约与检查项,那么围绕它的开发工作就能大比例地委派出去;反之,如果它的正确使用方式高度依赖口口相传的经验,那么它会持续消耗你最贵的资源------人的注意力。
3、一个具体推论
在同等条件下,约定清晰、行为显式、失败可见的技术方案,其价值相对于「灵活、隐式、自动」的方案在上升。因为前者的约束可以被写下来,后者的约束在人的脑子里。这是一个方向性的变化,值得在下一次选型时明确地放进权重表。

十、上下文可写入性:一个应该被正式承认的架构指标
(一)为什么它值得单独成为一个指标
1、它直接决定 AI 的产能
同一个模型,在两个不同的 Java 代码库上工作,产出质量的差距可以达到数倍。差距的来源不是模型,是代码库:一个把约束写下来了,一个没有。既然差距这么大,而且这个变量完全在团队的控制之下,它就应该被当成一个可度量、可立项、可验收的架构指标。
2、它对人同样有效
需要强调一点:提高上下文可写入性,收益并不只在 AI 侧。一个新人上手时间从三周降到五天,一次跨团队对齐从三轮会议降到一封邮件,这些收益一直存在,只是过去没有足够的压力去兑现它。AI 提供了这个压力,也提供了一个新的、更容易被管理层理解的立项理由。
3、它不是「多写文档」
必须把这件事和「写文档」区分开。文档会过期,而过期的文档比没有文档更糟------它会把错误的约束喂给模型和新人。可写入性追求的是约束的可执行化:能变成测试的变成测试,能变成静态检查的变成检查,能变成类型的变成类型,实在不行才变成文字,而变成文字的部分必须有明确的失效日期和责任人。
(二)六个可以打分的维度
1、命名与结构的一致性
同一个概念在全代码库里是不是同一个名字;分层结构是否统一;一个新功能应该放在哪里是否不言自明。不一致的命名是模型犯错的第一大来源,因为它无法判断 userId、uid、memberNo 是不是同一个东西。
2、契约的显式程度
接口的输入输出、错误码、幂等语义、超时约定,是写在代码与规范里,还是靠联调时口头确认。
3、副作用的集中度
数据写入、消息发送、外部调用是否集中在可枚举的少数位置,还是散落在各处。集中度高的系统,模型改动时踩到副作用的概率显著下降。
4、不变式的可执行化程度
关键业务规则有多少条被写成了断言、约束或校验任务,而不是只存在于某个人的记忆里。
5、决策记录的完整度
「为什么不这么做」这类信息是最容易丢失也最有价值的。没有它,模型(和新人)会反复提出你三年前已经否掉的方案,而你要反复解释。架构决策记录的价值在 AI 时代被显著放大了,因为它是唯一能跨越会话保存否定性知识的载体。
6、验证回路的速度与可靠性
从改一行代码到知道它对不对,需要多久,结果稳不稳定。这一条前面已经反复出现,它是可写入性的兑现通道------写下来的约束如果不能被快速检验,等于没写。

(三)把隐性约束写下来的四种载体
1、可执行的检查
优先级最高。静态检查规则、架构约束测试(例如「领域层不允许依赖基础设施层」这类可以用工具直接断言的规则)、契约测试、数据库约束、自定义的编译期注解处理。它们的共同点是不会过期:约束变了,检查就红了。
2、类型与结构
用类型表达约束是成本最低的一种:用值对象代替裸 String(OrderNo 而不是 String orderNo)、用枚举代替魔法值、用密封类穷举状态、用不可变对象表达「这个东西创建后不能变」。这类表达一旦写下,任何人(和任何模型)都无法绕过。
3、仓库内的规则文件
给编码助理准备的项目说明:技术栈与版本、目录约定、必须遵守的模式、明确禁止的做法、常用命令、领域术语表。它的作用相当于新人手册,但被高频使用。这个文件的质量应该被当成团队资产来维护,而不是某个人随手写的。
4、决策记录与术语表
用轻量格式记录每一个重要决定:背景、备选方案、选择、后果、有效期。术语表则解决口径问题:一个业务名词的准确定义、它对应的数据字段、它不包含什么。

(四)这项投入的回报怎么算
1、三笔可量化的账
第一笔,委派成功率。同一类任务,改造前后「一次通过评审」的比例。这个数字通常能从三成提升到七成以上,直接对应节省的往返时间。
第二笔,新人上手时间。从入职到独立提交第一个有实质内容的变更需要多久。
第三笔,缺陷逃逸率。进入生产才被发现的缺陷占总缺陷的比例。可写入性提高会同时降低生成缺陷和人工缺陷。
2、投入的节奏
不要试图一次性把整个代码库改造好,那是一个永远做不完因而永远不会开始的项目。可行的节奏是:每次做业务需求时,顺手把这次触碰到的那一小块的约束写下来。半年之后,被高频改动的那 20% 代码会自然完成改造,而那 20% 承载了 80% 的变更。
3、一个警告
可写入性的提高会让一部分任务从重估区滑进贬值区,包括一部分你自己现在还在做的任务。这是预期内的、也是正确的结果。抗拒它没有意义:你不做,别人做了,差距只会更大;你做了,省下的时间可以投到升值区。
十一、领域与业务能力:错误需求的成本被放大了
(一)放大效应从哪里来
1、实现速度提高,纠错窗口反而变短
过去一个需求从确认到上线要三周,这三周里有大量非正式的纠错机会:设计评审时有人提出疑问、开发到一半发现逻辑不通、测试时业务方看到原型改了主意。慢本身是一种容错机制。
现在同样的需求两天就能上线。纠错机会被压缩,一个想错了的需求会以极高的保真度被快速实现出来。它跑得很好,代码质量也不错,唯一的问题是不该存在。
2、返工的成本并不对称
写一个功能变便宜了,但撤销一个已经上线的功能没有变便宜:数据已经产生、用户已经习惯、下游已经对接、报表已经在用。一个错误需求的总成本 = 实现成本(下降了)+ 运行期间产生的脏数据与错误决策的成本(没变)+ 下线成本(没变,甚至上升,因为系统里的东西更多了)。第一项占比很小,所以总成本几乎没降。
3、结论
在实现变快的世界里,「做对的事」相对于「把事做对」的权重上升了。这直接抬高了需求分析、领域理解与证伪能力的价格。

(二)需求证伪的五个必问
1、这个需求要解决的问题,用现有功能能不能解决
大量需求的本质是「使用者不知道已有能力的存在」或者「已有能力的入口太深」。这一问平均能砍掉一到两成的需求量,而且回答它的人必须对系统现状有全局了解------这正好是模型帮不上忙的地方(它不知道你们的运营实际怎么用)。
2、这个需求的成功怎么度量,不成功怎么下线
要求提出方给出一个可观测的指标和一个下线条件。给不出来的需求,通常是「某个人觉得应该有」。这一问的价值不在砍需求,在于它把一个模糊愿望转成了一条可判定的判据------又回到判据这件事上。
3、边界条件业务上怎么定义
跨天的订单算哪一天、退款后原来的优惠券要不要退回、部分成功怎么展示、并发操作以谁为准、历史数据要不要处理。这些问题的答案不在需求文档里,必须问出来。它们也正是生成代码最容易随便编一个答案的地方------模型会给出一个合理的默认行为,而合理不等于符合你们的业务约定。
4、这个需求和现有的哪条规则冲突
新需求与既有规则的冲突是系统腐化的主要来源。发现冲突需要记住既有规则,而这一点在系统足够大之后只有少数几个人能做到。把这些规则写下来(第十章的工作)会让这一问变得可以分担。
5、如果这个需求做错了,我们怎么发现、怎么撤
对不可逆的需求(涉及资金、对外通知、数据删除、对外披露)必须提前回答。答不上来就不该开始。

(三)口径统一与领域建模
1、口径问题是企业系统的第一大坑
「有效用户」在增长团队、财务团队和风控团队各有一个定义;「订单完成」在交易系统指支付成功、在履约系统指签收、在结算系统指对账通过。这些差异平时被人工翻译掩盖,一旦要做自动化、做报表、做对外接口,冲突立刻爆发。
在 AI 参与开发之后,这个问题会被加剧:模型会按照它见过的最常见定义来实现,而不知道你们内部的特殊约定。口径不统一的系统,交给自动化的风险显著高于口径统一的系统。
2、领域建模的价值在上升
统一口径的工程手段就是领域建模:为每个核心概念找到一个明确定义、一个负责的模块、一套不变式,并让其他所有模块通过契约访问它,而不是各自复制一份理解。
这项工作在过去经常被认为「投入产出比不明确」,因为它的收益是长期且分散的。现在它的收益多了一项非常直接的部分:它把「业务规则」这个最不可写入的东西变成了可写入的,从而把一大片工作从升值区(贵、只能自己做)转移到贬值区(便宜、可以委派)。这是一笔明确可算的账。
3、建模能力具体表现为什么动作
不是画类图。是这三个动作:给一个模糊的业务名词下一个能被两个不同团队同时接受的定义;找出两个看起来一样的概念之间的真实差异并决定是合并还是分开;判断一条业务规则应该表达成数据约束、状态机、还是运行时校验。
(四)把技术方案折算成钱
1、为什么这项能力在升值
当方案枚举变便宜之后,「哪个方案更好」的判断权重上升。而「更好」在企业里最终要折算成成本:机器与带宽、人力与时间、风险敞口与合规代价、以及未来的维护与退出成本。
2、一个可用的折算清单
2.1 直接成本
新增的计算、存储、带宽、许可证与第三方服务费用。这一项最容易算,也最容易被当成全部------事实上它在多数方案里只占总成本的一小部分。
2.2 人力成本
实现工时、后续维护工时、对其他团队的对接与答疑成本、以及新人理解它所需要的时间。维护工时是最容易被低估的一项:一个「省了两周实现时间」的取巧方案,可能在之后三年里每季度都要花两天去处理它带来的怪异问题。
2.3 风险成本
失效概率乘失效后果,再加上一个常被忽略的问题:这个方案有没有把一个原本可逆的操作变成了不可逆的。把可逆变成不可逆,等于凭空增加了一笔无法定价的负债。
2.4 机会成本
做这件事就不能做的另一件事。在资源紧张的团队里,这一项经常大于前三项之和,但它几乎从不出现在方案文档里。
2.5 退出成本
三年后要换掉它,需要改多少处代码、迁移多少数据、协调多少团队、承担多长的双跑期。这一项决定了这个决定的可逆性,因此应该在选型时就被明确写下来。
3、这项能力的稀缺性
多数工程师能说清楚一个方案的技术优劣,能说清楚它的钱的人少得多。而正是后者决定了你在什么层级参与决策。这项能力的养成不需要天赋,只需要在每次方案里强制自己算一遍,算错了下次修正。
十二、不可逆操作与责任:签字权不能外包
(一)不可逆清单:每个团队都应该有一份
1、清单上应该有什么
资金划转与账务记账;用户数据的物理删除与匿名化;对外通知(短信、推送、邮件、站内信);对外披露与报送;密钥与凭据的变更;数据库结构的破坏性变更(删列、改类型、删表);消息的投递(一旦下游消费就无法收回);缓存与索引的重建(重建期间的不一致窗口);对外部系统发起的、对方会真实执行的调用。
2、清单的用法
清单不是用来吓唬人的,它是用来给流程分岔的:清单上的操作走一套严格路径(双人确认、预演、灰度、可回滚方案、审计留痕),清单外的操作走快速路径。没有这个分岔,团队要么处处慢(把所有变更都当成高危),要么处处快(直到出事)。
在 AI 参与之后,这个分岔变得更加必要:快速路径可以大胆地自动化,严格路径必须保留人在环。分不清两者的团队,最终会选择整体保守,从而拿不到自动化的收益。
3、清单要定期重审
新功能会引入新的不可逆操作,而它们经常悄悄进来。一个实用做法是把「这次变更是否引入了新的不可逆操作」放进设计评审的固定问题里。
(二)人在环的闸门怎么设计
1、闸门要卡在正确的位置
卡得太早(任何 AI 参与的变更都要人工审批)等于放弃收益;卡得太晚(执行之后再审计)等于没有闸门。正确位置是在不可逆动作发生前的最后一步,且在那一步之前,所有可以自动完成的准备工作都已经完成。
2、闸门必须给出足够的判断材料
一个只显示「是否确认」的按钮不是闸门,它是一个仪式。有效的闸门要在同一屏给出:这次操作会影响多少条记录、影响哪些用户或账户、预计执行时长、执行期间的副作用、失败时的状态、回滚方式与回滚耗时。
准备这些材料的工作,恰好是极适合委派给自动化的------它闭合度高、可判定、完全可逆(只是查询)。所以正确的分工是:机器准备判断材料,人做判断。
3、闸门要有时效与撤销
授权应该有有效期(批准了不等于三天后还能执行),应该可以撤销(在执行开始后仍能中止并处理已产生的部分副作用)。这两点在批量操作里尤其重要。

(三)责任模型:谁写、谁审、谁签字、谁值班
1、四个角色必须分清
写 :产出变更的人或工具。审 :独立于产出方,负责找出问题。签字 :为这次变更的后果负责,通常是模块的负责人。值班:变更上线后的一段时间内负责观测与处置。
在传统流程里,这四个角色经常由一两个人兼任,问题不大。在 AI 参与之后,「写」这个角色的产能暴涨,如果「审」和「签字」的产能不变,整条链会堵在后面,然后开始走形式。
2、三种可行的调整
一,按风险分级配置审查强度。低风险变更(贬值区任务、完全可逆、有自动判据覆盖)只做自动检查加抽样人工审查;高风险变更保持甚至加强人工审查。这要求先有分级标准,而分级标准就是本文第三章的四条判据。
二,把审查前移到判据。与其在每次变更时人工找问题,不如一次性把这类问题变成自动检查。评审中每发现一个可以规则化的问题,就应该顺手把它变成规则------这是把评审产能从线性变成累积的唯一办法。
三,明确「签字人必须能解释」的红线。任何一个签字人如果无法解释这次变更的关键决定,就不能签。这条红线看起来会降低速度,实际上它会倒逼变更颗粒度变小、说明变清晰,长期反而更快。
3、事故复盘要改的两处
第一,不要把「AI 生成的」当成原因。它是背景,不是原因。原因永远是「我们的验证体系为什么没拦住」。把矛头指向工具,会让团队错过真正的改进点。
第二,要新增一个固定追问:这个缺陷本可以被哪一级验证拦住,为什么没有? 然后把答案变成下一次的自动检查。这条追问会让复盘的产出从「加强意识」变成具体的工程项。

十三、Java 工程师的新增值区:把企业能力变成可被调用的东西
(一)为什么这是 Java 后端的主场
1、需求正在出现
企业开始让智能体访问内部系统:查订单、改配置、发起流程、生成报表、执行运维动作。这些能力大多已经存在于既有的 Java 服务里,但它们的现有形态是「给前端页面用的接口」,不是「给自动化调用者用的能力」。这两者的差别很大,把前者改造成后者是一项实打实的后端工程工作。
2、Java 后端具备的三个条件
一是这些系统本来就是你们写的,改造的上下文成本最低;二是这类改造的核心是权限、幂等、审计、限额、事务边界,恰好是企业级 Java 工程师最熟悉的领域;三是这类系统对稳定性和合规的要求高,正是 Java 生态最擅长的场景。
3、这是一条真实的增量赛道
它不同于「学会用 AI 写代码」------后者是所有人都会做的事,不构成差异。把企业能力安全地暴露给自动化调用者,是一项有明确交付物、有明确难点、目前供给不足的工作。
(二)一个能被自动调用的接口,和一个普通接口差在哪
1、语义必须自解释
普通接口靠联调时的口头解释补全语义;被自动调用的接口必须把语义写在定义里:每个参数的含义与取值范围、返回值的每一种情况、错误码分别代表什么、哪些错误可以重试哪些不能。描述质量直接决定调用正确率,这是一个可以度量的东西。
2、粒度必须合适
太细(一个动作要连续调五个接口)会让调用方大量出错;太粗(一个接口做十件事)会让影响面无法评估。合适的粒度是「一个有业务意义、可以独立验收、失败后状态明确」的动作。
3、失败必须清晰
不能有「返回成功但实际没做」的情况,不能有「超时了但不知道有没有执行」的情况。后者尤其要命:自动化调用方遇到超时的默认行为通常是重试,如果接口不幂等,重试会造成重复执行。
4、必须能被沙箱化
要有一个「只读」或「预演」模式,让调用方可以先看看这个动作会做什么再决定要不要真的做。这既是安全要求,也是前面第十二章「闸门要给出判断材料」的实现方式。
(三)四条硬要求
1、幂等
每个有副作用的能力都必须接受一个幂等键,并保证同一个键重复调用只生效一次、且返回相同结果。这是所有其他保障的基础------没有幂等,重试、超时、断线重连全都会变成事故。
2、权限与最小授权
调用者的身份必须可追溯到一个具体的人或服务账号;权限必须按能力粒度授予而不是按系统粒度;高危能力必须单独授权且可随时撤销。
3、限额与熔断
按调用者、按时间窗口、按影响记录数设置限额。一个自动化调用者出错时的行为特征是高频重复同一个错误动作,没有限额就意味着放大器。
4、审计
每一次调用都要留下:谁在什么时候、用什么参数、调用了什么、结果是什么、影响了哪些数据。审计记录必须与业务数据分开存储、不可篡改、可按人和按对象两个维度检索。这一条在受监管行业不是可选项。

(四)这条路径上的三种角色
1、能力封装者
把既有服务改造成可被安全调用的能力,负责语义描述、幂等改造、权限模型、审计埋点。这是门槛最低、需求量最大的一个角色,适合作为切入点。
2、运行时治理者
负责调用的准入、限额、观测、成本归账、异常处置。这个角色的技能栈与传统的服务治理高度重叠------注册发现、熔断限流、链路追踪、配额管理,Java 工程师的既有积累可以直接迁移。
3、判据与围栏设计者
负责定义「自动化调用者做到什么程度算做对了」、设计不可逆动作的闸门、设计异常行为的检测规则。这是三个角色里最难也最值钱的,它本质上是把本文第七章和第十二章的能力用在了一个新场景上。
十四、人机协作的三种模式与它们的准入条件
(一)三种模式
1、副驾模式
人主导,工具在旁边提供补全、解释、局部改写。人对每一行都有直接的认知。适用于:不可判定的任务(并发、一致性)、不可逆的任务、以及你自己也还没想清楚的任务------因为在这类任务里,写的过程本身就是想的过程,把它交出去等于放弃了思考。
2、委派模式
人给出一个可验收的任务描述,工具完成整个「读---改---跑---修」的循环,人验收结果。适用于:闭合度高、有自动判据覆盖、可逆的任务。这是当前收益最大的模式,也是多数团队应该重点建设的。
委派模式成立的关键不在于提示词写得多好,而在于验收标准是否清晰、验证是否自动。一个说不清验收标准的任务,无论怎么描述都委派不出去。
3、自治模式
自动化流程在预设的边界内持续工作,人只在边界被触碰或结果异常时介入。适用于:范围明确、判据完备、副作用可控的持续性工作,例如依赖升级、静态检查修复、测试补齐、文档同步。
自治模式的准入条件比多数人想象的严格:必须有完整的自动判据、必须有明确的权限边界、必须有可靠的中止机制、必须有审计。缺一条就不该开。
(二)准入条件与模式错配的代价
1、准入条件对照
副驾模式没有准入条件,任何时候都可以用。委派模式要求:一条五分钟内跑完的可靠验证流水线、清晰的验收标准、任务本身可逆。自治模式在委派的基础上追加:判据覆盖完备、权限最小化、可随时中止、全量审计、以及一个负责人。
| 模式 | 人的位置 | 准入条件 | 适用任务 |
|---|---|---|---|
| 副驾 | 人主导,逐行有认知 | 无 | 不可判定、不可逆、自己也还没想清楚的任务 |
| 委派 | 人定验收标准并验收 | 五分钟内跑完的可靠流水线 + 清晰验收标准 + 任务可逆 | 闭合度高、有自动判据覆盖、可逆的任务 |
| 自治 | 人只在边界被触碰时介入 | 委派全部条件 + 判据覆盖完备 + 权限最小化 + 可随时中止 + 全量审计 + 一个负责人 | 依赖升级、静态检查修复、测试补齐、文档同步 |
2、错配的两种代价
该副驾却委派:把一个并发改造整体交出去,拿回来一段看起来很专业、跑得通测试、埋着竞态的代码,几周后在生产上以最难排查的形式爆发。代价是一次事故加上对工具的过度不信任。
该委派却副驾:明明是一个批量的机械改造,坚持一个个手改,花掉三天。代价是隐性的、不会有人指出来的、但会持续存在的效率损失。
在现实里,第二种错配比第一种更常见,也更容易被忽视,因为它不产生事故。
3、模式升级需要证据
从委派升到自治,不能靠感觉,要靠数据:这类任务在过去 N 次委派中的一次通过率是多少、逃逸到生产的缺陷有几个、每次的人工介入时长是多少。当一次通过率稳定在高位、且逃逸缺陷为零时,才可以考虑放宽。这个过程和服务上线前的灰度验证是同一个逻辑。

(三)关于提示词的一句话
值得单独澄清:提示词技巧不是能力,把约束说清楚才是能力。前者的半衰期以月计,随着模型和工具演进不断失效;后者是「明确表达一个工程意图」的能力,它在任何时代都有效,且它的产出(写下来的约束)会沉淀成团队资产。
一个简单的检验:如果你的提示词换一个模型就大幅失效,那说明你依赖的是技巧;如果换一个模型效果基本不变,说明你依赖的是把问题描述清楚这件事本身。后者才值得投入时间。
十五、组织与流程:评审、度量与培养通道必须跟着改
(一)评审要改的三件事
1、把可规则化的意见彻底移出人工评审
命名、格式、日志规范、空指针、资源关闭、常见坏味道------所有能被静态检查覆盖的意见,出现在人工评审里都是浪费。每出现一次,就应该有人把它变成规则。这项工作现在很便宜,没有理由不做。
2、评审要求提交者附上「验证说明」
不是「跑了测试」,而是:这次变更可能在哪里出错、我用什么手段确认了它没错、哪些部分我没有验证到。这段说明的价值在于它强迫提交者自己先过一遍判据,同时让评审者知道该把注意力放在哪。在生成代码占比高的团队里,这一条几乎是最有效的单点改进。
3、评审要按风险分级
低风险变更走轻量流程,高风险变更配足够的评审时长和合适的评审人。把所有变更一视同仁,结果一定是高风险的没被认真看。
(二)度量要改的六个指标
1、必须废弃的三个
代码行数 :生成时代它已经完全失去意义,甚至是负相关指标。提交次数 :同上。测试覆盖率作为 KPI:刷它的成本已经趋近于零。
2、应该采用的六个
变更前置时间 :从开始做到上线的时长。部署频率 :单位时间的上线次数。变更失败率 :上线后需要回滚或紧急修复的比例。恢复时长 :出问题到恢复的时间。这四个是被长期研究验证过的交付效能指标,它们的好处是无法通过增加产出量来刷。
再加两个针对 AI 时代的:缺陷逃逸率 (进入生产才被发现的缺陷占比,直接反映验证体系的有效性)与一次通过率(委派任务无需返工即通过评审的比例,直接反映上下文可写入性的水平)。
3、指标的用法
这六个指标应该被用来评估系统与流程,而不是评估个人。用它们考核个人会立刻产生扭曲:为了降低变更失败率而拒绝改动、为了提高部署频率而拆分无意义的提交。

(三)绩效与晋升的判断标准
1、旧标准的失效
「独立完成了某个复杂模块」这类描述的信息量在下降,因为完成的方式发生了变化。继续用它作为判断依据,会系统性地高估那些擅长产出、不擅长判定的人。
2、三个更有区分度的问题
这个人签过字的变更,事后回看的质量如何? 这是对判定能力最直接的度量。
这个人有没有把一次性的判断变成可复用的判据? 写下一条静态检查规则、建立一套对拍、设计一个在线不变式------这类产出的杠杆远高于完成一个需求。
这个人在多大程度上降低了别人的理解成本? 写下的决策记录、统一的口径、清理掉的重复实现,这些是团队资产。
(四)被打断的培养通道
1、问题的本质
工程判断力来自于「做错---承担后果---修正」的循环。当基础任务被大量交给工具之后,新人接触到的循环次数减少,判断力的养成会明显变慢。这不是危言耸听,它是一个可以预期的结构性后果。
2、三种可行的补偿
一,把「读与判」变成正式任务。让新人负责评审生成的变更、负责为某个模块补齐判据、负责梳理某条链路的失效模式。这些任务的学习密度不低于自己写。
二,保留「必须手写」的清单。团队约定某几类代码(并发、资金、安全边界)在入职第一年必须手写并由资深工程师逐行讲评。这是刻意练习,不是效率损失。
三,让新人参与真实的故障处置。以观察者和记录者的身份进入现场,事后独立写一份复盘并与资深工程师的版本对照。一次真实故障的信息量抵得上三个月的常规开发。
3、这件事的紧迫性
它的后果滞后三到五年才显现,因此最容易被推迟。但恰恰因为滞后,现在不做的团队在三年后会同时面临「资深工程师不够用」和「没有人接得上」两个问题,而那时再补已经来不及。
十六、能力地图:四域三档与三年走势
(一)四域三档总表
1、编码域
贬值 :样板代码、机械重构、模板文档、基础用例、常规依赖升级的执行部分。重估 :测试设计、代码评审、缺陷修复、性能调优的执行部分。升值:读懂陌生代码并指出失效输入、并发与一致性代码的设计、安全边界代码、资金与权益计算代码。
2、架构域
贬值 :架构图与方案文档的绘制、方案空间的枚举、规范文本的编写。重估 :技术选型、模块划分、接口设计的执行部分。升值:边界与不变式的定义、演进路径与退出成本的判断、熵增抑制机制的设计、上下文可写入性的改造。
3、验证域
贬值 :用例代码的编写、测试数据的准备、覆盖率的补齐。重估 :测试策略、评审流程、发布检查清单。升值:判据设计、可判定性改造、在线不变式与对账、变异测试与对拍体系的建设。
4、业务域
贬值 :需求文档的整理、原型的产出、业务流程图的绘制。重估 :需求评审、口径核对、方案与业务方的对齐。升值:约束发现与需求证伪、领域建模与口径统一、成本折算、不可逆操作的治理、跨团队技术协商。

(二)三年走势的判断
1、会继续下跌的
所有「上下文可以完全写下来 + 正确性可以自动判定」的工作,价格会继续向零逼近。不要在这些地方建立身份认同。
2、会先跌后稳的
重估区的工作会经历一个尴尬期:旧形态在贬值,新形态还没建立,从业者会经历一段「感觉自己在被淘汰」的时期。度过这个时期的方法是主动转换形态------从执行者变成判据的定义者。转换完成后,这些能力会稳定在一个不低的位置,因为它们是连接生成侧与担责侧的桥梁。
3、会继续上涨的
升值区的七类工作,供给收缩、需求扩张,中期内看不到反转的迹象。其中涨得最快的应该是「判据设计」与「不可逆操作的治理」这两项,因为它们的稀缺性最高,且它们的价值随着自动化程度提高而线性增长。
4、一个不确定项
「上下文可写入性改造」这项工作有可能在若干年后被工具大幅自动化------从代码自动抽取约束、自动生成不变式候选。即便如此,「判断哪条候选是真的约束」仍然需要人。所以这项工作的形态可能变,价值不会消失。
(三)三种最危险的能力组合
1、只会写、不会验、不担责
这是被冲击最直接的组合。特征是:熟练使用框架、能快速完成功能、但说不清自己的代码会在什么情况下出错,也从未主导过一次故障处置。这个组合在过去是一个稳定的中级工程师画像,现在它的市场价格正在快速下滑。
2、只会说、不会做
另一个极端:能讲架构、能画图、能引用各种方法论,但已经很久不碰代码、不进现场。在生成时代,「说」的部分贬值最快(因为方案枚举与文档产出已经很便宜),而这个组合恰恰没有验证与担责的落地能力支撑。
3、拒绝改变工作方式
坚持全部手写、拒绝使用工具、以「我写得比它好」为理由。这个判断在具体某段代码上可能是对的,但作为整体策略必然失败------因为竞争对手不是模型,而是「同样有你的判断力、同时把机械工作交出去了」的人。

十七、成长路径:九十天、分级建议与四个反模式
(一)九十天可执行清单
1、第一个月:把验证回路建起来
1.1 第一周:把验证回路砍到十分钟以内
让你的项目具备一条五分钟内跑完、结果稳定的构建加测试流水线。如果现在跑一次要四十分钟,这一周的目标就是把它砍到十分钟以内(并行、分层、只跑受影响的部分)。这件事本身可以大量借助工具完成。
1.2 第二周:写下三条不变式
给你负责的模块写下三条不变式,并把其中至少一条做成可以自动执行的检查。
1.3 第三周:写一份失效模式清单
给你负责的模块写一份失效模式清单------列出「这个模块会以哪些方式出错」,至少十条。这份清单是你后续所有测试设计与评审的依据。
1.4 第四周:把清单变成检查
把这份清单里能自动检查的部分变成静态规则或测试。
2、第二个月:把委派跑通
2.1 第五、六周:完整委派三类任务
挑三类你确认属于贬值区的任务,完整地委派出去,记录每一次的一次通过率与返工原因。返工原因会精确地告诉你上下文缺在哪里。
2.2 第七周:补齐上下文
根据返工原因,补齐仓库里的规则文件、术语表与关键约定。
2.3 第八周:复测一次通过率
再跑一轮同类任务,对比一次通过率。如果没有提升,说明补的东西不对,回到第七周。
3、第三个月:把能力投到升值区
3.1 第九、十周:接一个升值区的任务
主动接一个你平时不接的任务类型------一次故障归因的主导、一次跨团队接口协商、一次不可逆操作的方案设计。
3.2 第十一周:写一份决策记录
写一份决策记录,把这次做出的关键判断和被否掉的方案记下来。
3.3 第十二周:复盘整个季度
复盘整个季度:省下了多少时间、这些时间投到了哪里、你的判断被证明对了几次错了几次。这一步不能省,它是把经历变成经验的唯一途径。

(二)分级建议
1、入行一到三年
核心风险:你的日常任务与贬值区高度重合,而判断力尚未建立。
优先级:一,保持手写关键代码的习惯,尤其是并发、事务、资金相关的部分,不要为了快而跳过理解;二,把大量精力放在读代码上,读历史模块、读评审中的变更、读开源项目的核心实现;三,主动参与故障处置,哪怕只是旁观和记录;四,训练「说清楚为什么」的习惯,每一个技术决定都要能给出理由。
不要做的:用产出量证明自己;用工具跳过理解;回避需要沟通的任务。
2、三到八年
核心风险:能力形态停在「执行者」,而执行者这个位置正在被压缩。
优先级:一,完成从「写代码」到「定判据」的形态转换,具体动作是本文第七章的全部内容;二,把你所在系统的上下文可写入性提上去,这是当前投入产出比最高的工程项;三,开始主动承担不可逆操作的设计与签字;四,训练成本折算能力,每个方案都算一遍钱。
3、八年以上
核心风险:远离现场,判断退化为经验的复述。
优先级:一,保持进现场的频率,至少每季度亲自主导一次归因;二,把个人判断变成组织的判据------你的经验只有变成自动检查、变成决策记录、变成新人的训练材料,才能规模化;三,重新设计团队的评审、度量与培养通道(第十五章);四,为团队找到 Agent 工具化这类新增量赛道,而不是只做存量优化。
(三)四个反模式
1、把提示词当护城河
理由见第十四章第三节。技巧会过时,把约束说清楚的能力不会。
2、全盘信任或全盘拒绝
两者都是放弃判断。全盘信任的人会在第一次事故后转向全盘拒绝,全盘拒绝的人会在同事效率明显更高时被动接受。正确的姿势是按四条判据逐任务判断,这需要动脑子,但没有别的办法。
3、用 AI 产出量作为绩效
这会立刻催生「大量生成、草率验证」的行为,把风险从个人转移给系统,且后果在几个月后才出现。度量应该用第十五章的六个指标。
4、为了保住位置而故意保留信息不对称
不写文档、不统一口径、让关键约定只存在于自己脑子里。这个策略的保质期大约是两年,代价是这两年你都在做同一件低价值的事,而且你会成为团队的瓶颈------瓶颈在组织里从来不是一个安全的位置。
(四)最后一句判据
如果只能记住一句话,就记这一句:
当「写出来」的成本趋近于零,你的价格由三件事决定------你能不能说清楚它对不对,你能不能在它错的时候第一个发现,以及你敢不敢为它签字。
这三件事,第一件叫判据,第二件叫可观测性,第三件叫责任。它们都不是新东西,Java 工程师在企业系统里做了二十年。只是过去它们被「会写代码」这件事掩盖了,现在掩盖物被拿走了,剩下的就是真正的能力本身。

参考资料
实证研究与效能数据
- METR:AI 工具对资深开源开发者生产力影响的随机对照实验 ------ 主观加速与客观耗时之间的反向差
- SWE-bench:真实软件工程任务上的模型评测基准
- SWE-bench 论文:Can Language Models Resolve Real-World GitHub Issues?
- Evaluating Large Language Models Trained on Code(HumanEval 与代码生成评估的起点)
- Do Users Write More Insecure Code with AI Assistants?
- DORA:软件交付效能研究与四项关键指标
- Stack Overflow 开发者调查
- Martin Fowler:Exploring Generative AI(生成式 AI 在软件工程中的实践观察)
验证、测试与质量
- Google 工程实践:代码评审指南
- Martin Fowler:测试金字塔
- PIT:Java 变异测试工具
- jqwik:Java 基于性质的测试框架
- Testcontainers:容器化集成测试
- JaCoCo:Java 代码覆盖率工具(以及为什么覆盖率不能当 KPI)
- ArchUnit:把架构约束写成可执行测试
- Google SRE Book:可靠性工程与事故处置
Java 与 JVM 官方资料
- Java Language Specification
- HotSpot 虚拟机垃圾回收调优指南
- JEP 444:虚拟线程
- JSR 133:Java 内存模型与线程规范
- JMH:Java 微基准测试工具
- Spring Framework:声明式事务管理
- Spring Framework:AOP 代理与自调用问题
架构、上下文与决策记录
智能体、工具化与安全