AI写代码越来越强,程序员还需要学习什么?

上周我把一段 React 组件的状态逻辑丢给编码 agent,20 秒拿到一版改动。类型检查过了,单测过了,我在 diff 上看了两遍也没找出毛病。三天后线上冒出一串重复请求——它把 useEffect 的依赖数组改宽了,同一个数据流被多订阅了一次。

这类错误的形态很一致:语法没问题,类型没问题,局部逻辑读着也顺,错的是那份只存在于我脑子里的约定。JetBrains 的开发者调研里有个数字能说明当下的状态:90% 的专业开发者每周至少用一次 AI 编码 agent。写代码的动作已经在被大规模外包,剩下没被外包的,正是让这件事能长期跑下去的那部分能力。

模型给得出实现,给不出"什么算对"

你让 agent 写一个上传组件,它会给你一个能跑的上传组件。但它不知道这个接口在你的系统里超时是 8 秒还是 60 秒,不知道失败时该重试三次还是直接把错误抛给用户,不知道上传中断后要不要清理已经写进去的半条记录。

这些不是"提示词没写清楚"的问题,是约束本来就不在代码里。它们散落在两年前的线上事故复盘、某个 PR 的评论区、同事随口说的一句话里。模型拿不到,只能按最常见的做法猜一个,而最常见的做法通常不是你这个系统该用的做法。

所以第一件要学的事,是把隐性约束变成显性产物。ESLint 的自定义规则、收窄到不能再收窄的类型定义、接口契约测试、CI 里那条不允许跳过的检查,本质上都是同一个动作:把"我觉得这样才对"改写成机器能判定的形式。写进去之后,agent 的产出才会被自动拦一道,而不是每次都靠人眼去兜。

读 diff 的速度变成了新的瓶颈

产出速度上去之后,瓶颈就移到了验收侧。以前一天自己写两三百行,现在一天可能要过一千行不是你写的代码。

读代码和写代码是两套不同的能力。写代码时你脑子里有完整意图,读代码时你得从产物反推意图,再判断这个意图跟真实意图差在哪。后者只能靠积累——你见过足够多的错误形状,才能在扫过 diff 的十秒里感觉到"这里的依赖数组不对劲"。

一个比调 prompt 更值的练习:拿到 agent 的改动,先不看它的说明文字,自己读代码推断它想干什么,再回头对照它的解释。两边对不上的地方,通常就是问题藏的地方。这个练习还有个副作用:你会慢慢建立起一份"它惯常在哪些地方出错"的清单,之后再看 diff 就知道该重点扫哪几行,速度会明显提上来。

前端调试的基本功在这些场合的使用频率比以前高得多,JavaScript 里关于执行顺序、事件循环、闭包捕获的内容值得反复看——不是要背 API,而是大部分"看着对"的错误都出在顺序和捕获上。组件层面的问题也一样,状态放在哪一层、effect 什么时候跑,这些在 React 教程 里是最基础的章节,但在 agent 生成的组件里恰好是最容易出错的位置。

环境知识是最难转移的一块

还有一类知识几乎喂不进模型:你的程序实际跑在什么上面。

同一个接口,本地直连和经过反向代理之后行为可能不一样——缓存头、超时、请求体大小限制都不在同一处配置。容器里的时区、文件编码、进程能打开的文件数,这些参数决定代码在开发和生产下的表现差异,而它们写在部署配置里,不在应用代码里。agent 看不到,它按默认环境假设写,写出来在你机器上跑得好好的。

这让"知道自己的程序跑在什么上面"从运维知识变成了开发者的核心能力。以前你可以不懂部署,靠同事兜底;现在你是那个唯一同时看得到代码和部署配置的人,判断两端是否自洽的责任只能落在你身上。花一个下午把 Docker 的镜像分层、环境变量注入和构建缓存弄明白,回报比再学一个框架要大。

具体该学什么

学怎么写测试,尤其是怎么写真正反映约束的测试——不是覆盖率好看的测试,是改错一个参数就会红的测试。学怎么读别人的代码,包括读那些没有注释、命名混乱的历史代码,因为 agent 会大量模仿仓库里已有的坏写法。学怎么把你系统的不变量表达成可执行的检查。

还有一样容易被忽略:怎么把问题拆到足够小,小到你能在读 diff 的十秒内判断它对不对。拆得越小,agent 的产出越可控,你要验收的范围也越窄。一个两百行的改动和五个四十行的改动,出错概率和排查成本完全不是一回事——前者你只能整体接受或整体拒绝,后者你可以逐块确认。

写代码这件事正在被替代,"决定这段代码该不该留下"这件事没有。前者是产出,后者是责任,而责任没法外包。


JetBrains 数据引自其开发者生态调研报告中关于 AI 编码 agent 使用频率的部分。