1. 从一次代码评审说起
上个月评审一段 AI 生成的 EF Core 查询,需求简单到不能再简单:“根据企业 ID 查企业信息”。AI 给出的代码是这样的:
public async Task<Enterprise> GetEnterpriseAsync(int id)
{
return await db.Enterprises.FirstAsync(x => x.Id == id);
}
语法零错误,逻辑"看起来"完全正确,单元测试也跑得过。但我盯着这段代码看了两分钟,脑子里自动弹出一串问题:
- FirstAsync 查不到数据会抛异常——这里"找不到"到底是业务错误还是正常情况?该不该用 FirstOrDefaultAsync?
- 没有 CancellationToken——我们船端走卫星链路,请求可能挂 90 秒,用户取消了,数据库查询还在跑吗?
- 没有 AsNoTracking——这是只读查询,变更跟踪器正白带走一堆实体引用,高频调用下内存和 CPU 双重浪费
- 直接返回实体——实体上有软删除字段 IsDelete,这个查询会不会把已删除的数据查出来?有没有不该返回给前端的字段?
- x.Id == id——多租户系统,ShipId/TenantId 过滤在哪?会不会查出别的船的数据?
注意,这些问题没有一个是语法问题,全是上下文问题。AI 不知道这个查询跑在卫星链路上、不知道系统有软删除约定、不知道这是多租户环境、不知道它是每秒调用几百次的热路径还是一天跑三次的管理接口。
那段代码最后改成什么样不重要。重要的是我意识到一件事:AI 把"写代码"这件事的成本打到了接近零,但"判断这段代码能不能上生产"的成本,一分没降,甚至更贵了——因为 AI 生成的代码比初级工程师手写的"看起来专业"得多,错误也藏得深得多。
这篇文章想讲清楚的就是:当生成不再稀缺,开发者的价值到底落在什么地方。我的答案是五个字之外的五种能力——机制判断、边界判断、业务判断、安全判断、验证判断。
💬 互动一下:回想你最近一次采纳 AI 生成的代码,是"看懂了所以采纳",还是"看不懂但好像挺有道理所以采纳"?后者,就是判断力缺口出现的时刻。
2. 先立观点:生成廉价,判断稀缺
我用 AI 做得最重的一件事,是扫描本地一套船舶 PMS 系统——17 个项目、5000 多个源文件、250 多个 Controller、938 个实体——让它逆推出完整的需求规格说明书。这件事如果纯人工做,按老规矩得读几个月代码。AI 几天就出了 1646 行文档。
但紧接着发生了什么?我花了同样多甚至更多的时间去验证:
- 它归纳的审批流"Manager1-4 四级审批"对不对?我去翻 WF5 工作流引擎源码核对节点执行器工厂的真实逻辑
- 它说的多币种字段(Currency/CurRate/UsdRate)之间的换算关系,和实体里的真实语义一致吗?
- 它漏掉的那些"代码里没有但业务上必须有"的规则,怎么发现?
这件事给我的启发是:AI 时代的工作流不是"我提需求 → AI 交付 → 我验收",而是"AI 生成候选 → 我判断对错 → 共同收敛"。在这个闭环里,生成端的能力每三个月翻一倍,判断端的能力却只能靠一个人的工程积累慢慢长。此消彼长,判断力就是那个越来越稀缺、越来越值钱的东西。
下面逐一讲这五种判断力。每一种我都用系列博客里写过的真实事故来说——因为判断力这东西,空谈概念没用,得看它在事故现场长什么样。
3. 机制判断力:知道代码在运行时到底发生了什么
AI 能写出 HttpClient client = new HttpClient(),语法完全正确,教程里也都这么写。它不会主动告诉你的是:
- 每次 new 一个 HttpClient,底层占用一个 socket,连接关闭后进入 TIME_WAIT 状态 2-4 分钟才释放
- 高并发下,2.8 万个临时端口被占满,服务开始批量抛"端口耗尽"
- 你凭直觉改成 static 单例,端口问题没了,但 DNS 永不更新——蓝绿切换到新地址后,旧实例 100% 请求失败,重启才恢复
- 真正的解法是 IHttpClientFactory:Handler 以 2 分钟为周期轮转,旧 Handler 等飞行请求完成后回收,同时治住端口耗尽和 DNS 陈旧两个病
这是 HttpClient 篇的开篇事故。注意它的特征:AI 给的代码在单次运行、低并发、短时间窗口里永远正确,错误只在高并发、长时间运行、特定网络条件下才暴露。
同类的例子在系列里比比皆是:
- DI 篇:Scoped 服务被注入 Singleton,代码跑得好好的,直到某个偶发时刻,单例捕获了上一个租户的 ShipContext——跨船数据串了
- 异步并发篇:async/await 一个没写错,但某处同步阻塞 .Result,线程池在高峰期被慢慢饿死,整个服务从响应慢到彻底卡死,重启又好
- 线程安全集合篇:ConcurrentDictionary.AddOrUpdate 做计数器,API 名字绝对正确,结果丢了 37 次更新——因为工厂委托在竞争时会被多次执行,写在里面的"读取-累加-写回"不是原子的
这些问题的共同点:语法层面无懈可击,运行时层面暗流涌动。机制判断力,就是拿到一段代码能在脑子里"模拟"它在高并发、长运行、资源受限条件下的行为——线程怎么调度、内存怎么分配、连接怎么复用、GC 什么时候介入。
这种能力 AI 不是不能给你答案,你问它它也知道。问题在于:你不知道该问什么。 端口耗尽之前,你根本意识不到 socket 和 TIME_WAIT 是个需要问的问题。机制判断力的价值,是让你在事故发生之前就知道该往哪看。
自查:这段代码在 1000 并发下跑 72 小时,会怎样?资源会泄漏吗?状态会串吗?如果答不上来,这段代码还不属于你。
4. 边界判断力:知道一个方案在什么条件下不成立
AI 回答技术问题有个倾向:给标准答案,但不标注标准答案的失效条件。而工程上,"什么时候不能用"往往比"怎么用"更重要。
分布式锁就是个典型。你问 AI 怎么防超卖,它熟练给出 Redis SET NX PX,上心一点的还会推荐 RedLock 算法。但它很少会主动告诉你:
- RedLock 假设时钟可靠,而 GC 暂停、虚拟机挂起都会让持有锁的进程"失活"却不自知——这是分布式系统领域著名的争议,RedLock 并不解决这个问题
- 单 Redis 实例锁,TTL 设 30 秒,业务里混了一个 35 秒的慢查询,锁过期后第二个请求拿到锁,库存双份冻结;更糟的是第一个请求醒来后还会用自己的 token 删掉别人的锁
- 所以我们在项目里的结论是:Redis 锁只是"高并发闸门",不是正确性防线。真正兜底的是 Fencing Token(单调递增令牌)+ 数据库条件更新(WHERE fencing_token < @token),过期写入被数据库拒绝
Saga 分布式事务同理。AI 能把编排式状态机和补偿动作写得很漂亮,但"空补偿"(补偿先于原操作到达,比如原操作超时实际未执行)、“悬挂”(补偿执行完原操作才到)、"补偿重复执行"这些边界,全是线上血泪——不踩过或者没认真研究过别人怎么踩的,写出来的 Saga 在故障注入测试下一戳就破。
限流(系列最新一篇)也是:AI 给你一段按 IP 限流的中间件,标准做法。但我们的船端场景里,42 条船可能共用一个卫星地面站的 NAT 出口 IP——按 IP 限流等于一次误伤整个船队。分区键必须用认证之后的 ShipId。这种边界,通用模型不可能知道,它不在任何教科书里,在你的部署拓扑里。
自查:AI 推荐一个方案时,你能不能立刻说出"它在什么三个条件下会失效"?说不出来,你就还在"信它"而不是"用它"。
💬 互动一下:你有没有遇到过"标准答案在我的环境里是错的"这种时刻?我的经验是,这种时刻出现的频率,和一个系统的业务独特性成正比——船岸卫星链路这种环境,几乎每条标准答案都要打个折。
5. 业务判断力:知道代码要保护的到底是什么
技术是通用的,业务约束不是。AI 的训练数据里有全世界的限流教程,但没有你公司的业务规则。
我们那套 PMS 系统里,有些东西是任何通用模型不可能"知道"的:
- 备件申请数量不能超过可用库存——但紧急维修可以超领后补单,这条例外在任何库存系统教程里都没有
- 审批流是 Manager1-4 四级硬编码,但不同船东的流程不一样:有的要会签(一票否决)、有的或签(一人同意即可)、还有加签、转办、驳回到发起人/驳回上级/作废三种完全不同语义
- 船端时钟可能不准、船可能离线 40 天,船岸数据同步必须用单调版本号防乱序,还要容忍"旧版本数据晚到"
- 金额字段是多币种的(Currency/CurRate/UsdRate),汇率必须随单据固化快照,不能在报表统计时按今天的汇率重算——否则三个月前的申请单金额会"自己变化"
AI 能给你写出一个结构完整的审批引擎,但"驳回到发起人后重新提交,流程从哪个节点开始"这种问题,它给的答案取决于你问的方式,而正确答案取决于你的业务。引擎和业务聚合的边界划在哪、流程状态以流程引擎表还是业务表为准、两边对不上账怎么平——这些判断里没有技术难点,全是业务理解。
我在做逆向需求分析时对这一点感受最深:AI 能把代码里"写了什么"归纳得又快又全,但"代码里没写、但业务上天经地义"的规则,它一条都编不出来——而那些规则,往往才是需求文档的灵魂。业务判断力就是你对"这套系统到底在保护什么"的理解:库存数字背后是船舶安全库存红线,审批流背后是船东的权责划分,汇率快照背后是财务合规。
自查:AI 生成的业务代码,你能不能指出"哪条业务规则它理解错了或者漏掉了"?指不出来,不是它写得好,是你对业务的理解还没到位。
6. 安全判断力:知道攻击面在哪
安全是 AI 生成代码"看起来对、实际上漏"的重灾区。
最经典的例子是 JSON 反序列化。Newtonsoft.Json 时代很多人用 TypeNameHandling.All 图方便,让序列化数据自带 $type 类型信息——这本质上是远程代码执行漏洞,攻击者在 JSON 里指定任意类型,反序列化时就被实例化。System.Text.Json 的多态反过来:要求你用 [JsonPolymorphic] + [JsonDerivedType] 显式声明每一个允许反序列化的派生类型,多一个字都不认。这不是麻烦,这是安全特性。但从 Newtonsoft 迁过来的人如果不懂这层,要么多态失效丢数据,要么图省事绕回危险写法。AI 能写出两种代码,它未必主动提醒你差异背后的攻击面。
再看几个系列里反复出现的:
- RAG 应用(现在 AI 项目的标配):检索阶段如果不做租户权限过滤,A 船的维修手册会被向量检索捞出来喂给 B 船的用户——权限过滤必须在敏感内容进入模型之前完成,不是在回答之后脱敏
- 限流:登录接口不限流等于敞开大门给密码爆破;但限流维度选错(IP)又会误伤
- 日志:AI 写的异常日志经常把整个请求对象打出来——里面有 Token、有船员个人信息、有船位数据
- 多租户:EF Core 全局过滤器是第一道,但 IgnoreQueryFilters、原生 SQL、 Hangfire 后台任务(没有 HTTP 上下文)都是过滤器管不到的角落,每一处都要单独证明不会串租户
安全判断的特殊性在于:你不能靠 AI"也许会写对"。功能写错了,测试会红;安全写错了,系统安静地运行着,直到有人利用它。这件事的验证逻辑和功能完全不同——你要假设输入是恶意的,然后问自己"最坏能怎样"。
自查:一段处理外部输入的代码,在不依赖 AI 自查的情况下,你能独立列出它的攻击面清单吗?
7. 验证判断力:知道怎么证明它是对的
五种能力里,这是最被低估的一种。
大多数人拿到 AI 代码后的验证方式是:跑一下,返回 200,界面显示正常,收工。但"能跑"和"对"之间隔着整个生产环境:
- 分布式锁对不对?正常流程永远对。要在"获取锁"和"写库"之间注入 35 秒延迟,人为制造锁过期,验证第二个请求会不会造成超卖、第一个请求醒来会不会误删别人的锁——故障注入测试
- Saga 补偿对不对?happy path 永远对。要构造"补偿消息先于原操作到达""补偿重复投递三次"这些异常时序,看空补偿和幂等守不守得住
- 限流阈值合不合理?拍脑袋设的 100 次/秒,要么松到没效果要么紧到误杀。得压测出单实例处理能力,阈值 = 能力 × 实例数 × 0.7 安全水位,再用实测流量校准
- 流式 JSON 解析省不省内存?不能凭"用了流式应该省了吧"就上线。我们那次 350MB 同步文件 OOM 的修复,是用 dotnet-counters 实测内存峰值从 1.2GB 降到 50MB 才算数
- 工作流引擎推进算法对不对?要用 Given-When-Then 把或签、会签、加签、驳回、超时升级每一条路径走一遍,包括"会签中一人驳回,其他待办任务是否被正确取消"这种细节
AI 会写测试,但它默认写的是"证明代码能工作"的测试——给正常输入、断言正常输出。而生产事故全部发生在边界和异常时序里。设计出让错误主动暴露的验证手段(故障注入、异常时序、压测、资源观测),是人类的活,因为这需要你先预判"它可能在哪里错"——而那又回到了前四种判断力。
验证判断力还有一层:可观测性。出了问题,你的日志、指标、链路追踪能不能让你 5 分钟内定位?AI 写的代码默认是"黑盒能跑",你要主动要求它是"白盒可查"——关键路径有结构化日志、关键指标有 Prometheus 埋点、跨服务有 traceId 串联。
自查:这段代码上线后,如果凌晨两点出问题,你靠什么定位?如果答案是"看日志再想",那你既没有验证判断力,也没有可观测性。
💬 互动一下:五种判断力——机制、边界、业务、安全、验证——你最强的是哪一种?最容易被 AI"架空"的是哪一种?我的观察是:工作年限长的人业务和边界判断强,但容易在机制层(新运行时、新框架的底层行为)被 AI 反超;新手反而机制学得快,但业务和安全直觉要靠事故喂。
8. 那到底该怎么学?
判断要落地到行动。我自己这大半年的学法,总结成三条。
第一,停止用"背 API"的方式学习。
具体类型叫什么、扩展方法怎么调、当前 SDK 推荐哪种写法——这些全部交给 AI 查,不要占用你的记忆。要搞明白的是上层的东西:这个概念在系统里解决什么问题、什么时候该用、出了问题从哪里开始排查。
- 学 Channels,不用背 Channel.CreateUnbounded 的重载,要懂"生产者速度持续大于消费者时,背压怎么传导、队列怎么有界、满了怎么办"
- 学 Polly,不用背策略的 Fluent API,要懂"重试为什么会放大故障(重试风暴)、熔断和限流分别在保护谁"
- 学 Native AOT,不用背 rd.xml 格式,要懂"反射为什么在裁剪后失效、源生成器为什么是 AOT 时代的官方路径"
知识的半衰期在缩短,但原理的半衰期很长。API 文档三个月一换,"无锁队列靠 CAS 和内存屏障工作"十年不会变。
第二,用"小项目 → AI 第一版 → 顺着问题补原理"的路径学。
不要再找一本厚书从第一页读到最后一页。我的实际做法:选一个足够小但真实的项目目标(比如"给船端同步接口加限流"),让 AI 出第一版能跑的实现,然后沿着它必然暴露的问题往回刨:
- 为什么 429 必须带 Retry-After?(客户端退避协调问题)
- 为什么按 IP 分区错了?(NAT 拓扑问题)
- 为什么固定窗口在整点会放过双倍流量?(窗口算法的临界突发问题)
每刨出一个"为什么",就是一块真正长在你身上的判断力。项目做完,验收标准不是"代码跑起来了",而是:脱离代码,能把整条链路从头到尾给别人讲清楚。讲不清楚的那段,就是还欠着的。
第三,建立你自己的事故档案。
这个系列阅读量最高的几篇——线上排障的并发资源篇、数据一致性篇、内存 GC 篇、网络通信篇——全是事故驱动的。我越来越确信,事故是 AI 最喂不饱你的东西:
- AI 的训练数据里有海量"正确做法",但缺少"我在这个具体业务里踩的具体坑"
- 事故上下文(卫星链路、42 条船、工业平板 2GB 内存、多版本客户端碎片化)是你独有的
- 每次事故后追问一句"为什么 AI 生成的代码没防住这个",就是在补判断力
建议每个人都维护自己的事故档案,固定五段式:现象 → 错误日志 → 推导过程 → 根因 → 为什么事前没防住、以后怎么一眼看出。这是任何模型都替代不了的个人资产,也是你带团队时最有价值的教材。
9. 一张评审自查清单
把五种判断力压成 12 个问题。以后评审 AI 代码(或者自己写的代码)时逐条过:
| 1 | 不查资料,我能讲清这段代码在运行时的完整执行路径吗? | 机制 |
| 2 | 1000 并发跑 72 小时,会泄漏资源吗?状态会串吗? | 机制 |
| 3 | 这个方案成立的前提假设是什么?哪三个条件下会失效? | 边界 |
| 4 | 失败时是静默错误还是显式失败?错误会不会被吞掉? | 边界/验证 |
| 5 | 它保护的业务规则是什么?哪条规则被漏掉或理解错了? | 业务 |
| 6 | 外部输入进系统前,做了哪些校验、限流、权限过滤? | 安全 |
| 7 | 多租户/多船数据隔离在哪层保证?我能证明它不串吗? | 安全/业务 |
| 8 | 反射、动态加载、序列化这些"动态"操作,在裁剪/AOT 下还成立吗? | 机制/边界 |
| 9 | 怎么证明它对?故障注入、异常时序、压测、资源观测,做了哪个? | 验证 |
| 10 | 凌晨两点出问题,日志/指标/链路追踪能让我 5 分钟定位吗? | 验证 |
| 11 | 三个月后换个人(或换个 AI)维护,哪里最容易被改错? | 架构 |
| 12 | 不用 AI 重写一遍核心逻辑,我知道每一步在干什么吗? | 综合 |
第 12 题是总闸。犹豫了,就说明这段代码目前"属于 AI",还不属于你。上线之前,至少让它属于你。
10. 给带团队的人三句话
如果你在带团队,这个变化对用人标准的影响是直接的:
考核标准要从"写代码的速度"转向"评审代码的深度"。 AI 让初级代码的产能趋于无限,"写得快、写得多"不再是壁垒;"看得出哪里不对、说得出为什么"才是。Code review 的权重应该显著上调。
初级工程师的风险不是降低了,是升高了。 过去初级工程师写得慢、写得丑,错误低级到 review 时一眼可见;现在 AI 帮他产出"结构工整、命名规范"的代码,错误却埋在并发时序、方案边界、安全攻击面这些深层——他自己没有能力抓,review 的人还更容易因为"看起来挺专业"而放松警惕。对初级的培养重点,要尽快从"怎么写"转向"怎么判"。
让团队沉淀判断力,而不是沉淀代码量。 事故复盘、架构决策记录(ADR)、方案评审时的"失效条件"讨论——这些过去被认为"不产出代码"的活动,在 AI 时代价值不降反升。代码 AI 可以重写,团队踩过的坑和形成的判断共识,重写不了。
11. 结语
回到那个很多人在问的问题:代码都能让 AI 写了,框架细节还要不要学?新东西(RAG、MCP、Agent)是不是知道个大概、要用时让 AI 实现就行?
我的答案是:"知道有这个东西"和"能判断它用得对不对"之间,隔着所有会在凌晨两点爆炸的东西。
这个系列四十多篇,主题从 DI、中间件、配置系统,一直写到 AOT、限流、分布式锁,表面零散,其实一直在做同一件事:把那些"AI 能生成、但你未必能判断"的机制,一个个变成你能脱稿讲清楚的东西。
框架会过时,API 会更替,模型会一代代变强。但看得懂运行时行为、预判得到失效边界、理解业务在保护什么、嗅得到安全攻击面、设计得出证明对错的验证——这五种判断力,是工具怎么变都还得你自己做的部分。
AI 负责写代码。你负责判断。
💬 最后一个互动:你最近一次"被 AI 生成的代码坑到"是什么场景?机制、边界、业务、安全、验证,算哪一类?欢迎在评论区留下你的事故——别人的事故档案,是最便宜的教材。


