编码时间降了65%,但我反而更焦虑了
你有没有过这种感觉——效率明明涨了,交付的东西明明多了,但下班的时候心里虚得慌。我以前一直以为是矫情。直到上个月我给自己做了个实验,然后失眠了一个晚上。事情是这样的。我一个十年 Java 程序员,从去年开始陆陆续续在用 AI 写代码。Claude Code 为主,偶尔 Codex 打杂。用着用着觉得挺顺手,就想看看它到底省了我多少时间。
5 月底我开了个严格对照:手头三个 Spring Boot 微服务——设备数据接入、告警上报、音视频流转发——再加一个管理后台。我把 AI 当成刚入职的 P6,我当 Tech Lead。我负责描述需求、审查代码、拍板架构,它负责写。对照基线是 4 月份纯手写、规模接近的同类项目。跑满 30 天,拉数据。结果是日均编码时间从 5.2 小时掉到了 1.8 小时。注意,这不是说 AI 帮我把一天变成了不到两小时——是我真正坐在电脑前敲键盘的时间,不到以前的一半。交付的有效代码行,从 180 行涨到了 420 行。这里我剔除了 AI 直接吐出来的东西,只统计我自己手敲和大幅修改的部分。说白了,活干得更多了,手敲得更少了。Commit 次数从日均 3.2 跳到了 11.5。不是变勤奋了,是节奏被 AI 改了。以前一个接口吭哧写一天,中间懒得提交。现在 20 分钟干完一个 CRUD,顺手就 git commit 了。单元测试覆盖率从 61% 飙到 73%,这没啥好说的,AI 写测试确实是碾压级的。说实话,数字好看到有点不真实——第一次把这几张表拼出来的时候,我心里咯噔了一下,隐约觉得哪里不对劲,但没细想,毕竟谁会跟自己的效率数据过不去。到这里一切都很美好。朋友问我用 AI 什么体验,我说"像带了个干活贼快的 P6"。但 30 天实验结束时一统计,同样类型和规模的交付,线上 bug 从 3 个涨到了 11 个。
就是那 11 个 bug 让我失眠的。我一个个复盘。7 个是同一个根因——并发安全。2 个空指针。1 个缓存一致性。1 个异常被吞。全都是那种"理论上测不出来,上线就炸"的类型。最典型的是积分扣减。代码长这样:
@Transactional
public void deductPoints(Long userId, Integer amount) {
User user = userMapper.selectById(userId);
if (user.getPoints() < amount) {
throw new BusinessException("积分不足");
}
user.setPoints(user.getPoints() - amount);
userMapper.updateById(user);
PointsLog log = new PointsLog();
log.setUserId(userId);
log.setAmount(-amount);
pointsLogMapper.insert(log);
}
本地跑三天,测试全绿。上线以后两个并发请求同时读到 `points = 100`,各扣 10 分,都写回了 `points = 90`。MySQL 默认 RR 隔离级别,普通的 SELECT + UPDATE,就这个窗口。说出来不怕你笑话,这段代码我在 Code Review 的时候看了两遍,没看出问题。不是因为逻辑复杂——逻辑一眼就通。是因为 AI 写得太快了,快到我把 Code Review 变成了"看一眼通不通",而不是"推演一遍并发路径下会怎样"。
缓存一致性那个更离谱。我让 AI 写了个"设备状态变更后刷新在线状态缓存"的逻辑。它生成的代码很标准——先更新数据库,再删 Redis。所有教科书都这么教的。但线上跑了两天,偶尔有设备明明在线,缓存里却显示离线。排了半天发现问题出在时序上:
坑就出在"删 Redis"这一步写在了 `@Transactional` 方法体里——事务要等方法返回才真正提交,但删缓存的动作已经先执行了。这个窗口期只要有别的请求插进来读一次库,缓存就脏了,而且脏了之后不会自己修复,除非再有人写一次。AI 不知道这个接口的 QPS,不知道你的事务隔离级别,不知道你的缓存过期策略。它只知道"先更新数据库再删缓存"是一条标准答案。标准答案在低并发下是对的,在你这里不是。说白了,它就像个 P6。基础扎实,干活快。你告诉它写什么,它 30 秒给你一个完整的 Service 层,格式统一,注释齐全。写测试、优化 SQL、拼配置类,这些活它干得比谁都利索。但它也跟 P6 一样,有些东西你教不会。
它不知道你们系统里哪些接口是高并发的。不知道上游某个字段可能传 null。不知道你删了 Redis key 之后,另一个请求会插进来读到旧数据。这些不是语法错误,是你干了十年攒下来的东西——扫一眼就知道这里会崩、那里没判空、这段的缓存对不齐。AI 不会自动长出这些经验。你不说,它就不知道。而且这一次你教了它,下一次换个同样的问题,它还是按默认套路来。你带一个 P6 两年,他会成长。AI 你用两年,它还是按你最近一次 prompt 里的上下文办事。
这个月之后,我给自己钉死了几条自查清单:
1. 涉及余额、库存、计数类字段的更新,默认走乐观锁或行锁,不写"先查后改"这种裸奔的 SELECT + UPDATE
2. 缓存删除动作必须放在事务提交之后执行,绝不能塞在 `@Transactional` 方法体内部(至少先守住这一条底线;延时双删、binlog 订阅那些看场景再上)
3. 只要是"读一次、算一次、再写回去"这种组合操作,先问自己一句:并发下这两步中间会不会被别人插队
不求多,就求 AI 写完之后,我扫一眼代码,能对上这几条。
30 天实验结束的时候,我给自己画了一条线。不是给别人看的,是给自己——什么活直接甩给 AI,什么活老老实实自己啃。CRUD、单元测试、SQL 优化、配置类、工具方法、枚举转换、日志框架、API 文档——全都丢。这些活的规则是明确的,不需要你做业务判断。你纠结的时间,AI 已经写完三遍了。架构设计、复杂业务逻辑、跨模块重构、线上排查、安全相关代码——留给自己。这些东西需要你把整个系统的上下文装在脑子里,AI 现阶段就是在浪费你的时间。这条线也不是一刀切的。比如"给设备心跳接口加一层在线状态缓存"这种活,看着像 CRUD,能丢给 AI,但我现在都会自己啃——因为一牵扯到缓存和实时状态,就绕不开一致性问题,一旦交出去,风险就藏在你看不到的地方。判断标准很简单:这活出了问题,你能不能一眼看出锅在哪。能,就丢给 AI;看不出来,就自己写。
还有个用法,很多人没试过:让你手写的代码给 AI 做 Review。不是让它审自己写的,是审你写的。你把手写代码丢进去,问一句"找出所有并发问题、空指针风险和性能瓶颈",它十秒能扫出一堆你漏掉的。人工 review 容易漏,AI 刚好补上。所以你发现没有,分工其实很自然——AI 写的你审,你写的 AI 审。不是谁替代谁的关系,是交叉检查。
顺便说一句,如果你嫌 Claude Code 贵,现在大部分模型都能接了。我中间试了个 CC-Switch 把后端切到 DeepSeek V4,大概两折半,日常写 CRUD 和跑单元测试基本感受不到差距。复杂重构再切回 Claude。一个月 API 费不到两百块。
失眠那个晚上,我翻来覆去想一个问题。不是"AI 为什么会写出 bug"——它当然会写,不写才奇怪。也不是"我为什么没审出来"——审不出来是因为它写太快,我跟不上。这些都不是真正让我睡不着的东西。真正让我睡不着的是这个:当 AI 把写代码的门槛降到零之后,我干了十年的经验,到底还值不值钱。
我问了自己一夜。天亮的时候有了一个答案。比以前更值钱。但前提是你得意识到,你现在干的不叫"写代码",叫"审代码"。审的不是格式规范,不是命名约定,是并发、安全、一致性——是所有 AI 不会自动学会的东西。审的也不是代码本身,是"这个方案在你的业务里,什么条件下会失效"。写代码变简单了,所以写代码的人会变多。但编程变难了——因为当所有人都能写的时候,你能不能在三秒内扫出一段代码在高并发下会崩,能不能一眼判断出这里缺了缓存一致性,能不能预判到上游可能为 null——这些以前是加分项,现在正在变成及格线。AI 没有抬高天花板。它把地板抬高了。把以前"还不错"的那批人,跟"真的懂"的那批人,拉开了。
我以前觉得写技术文章这事挺没意思的。网上教程那么多,不缺我一个。但这次 AI 实验做下来,我发现真正缺的东西不是教程——是那种"我也踩过这个坑"的共鸣。如果你也在用 AI 写代码,也有过那种"效率涨了但心里不踏实"的感觉,这篇文章评论区聊聊。我把这次实验里复盘的 11 个 bug 整理成了一份踩坑笔记,包括每一条的触发场景和修复后的代码。不是什么正式文档,就是一个工程师的踩坑记录。
不发教程,只发踩坑记录。十年 Java 老兵,用代码说话。
更多推荐

所有评论(0)