AI 写代码越来越溜, 我为何还在刷算法题?代码越来越廉价, 程序员真正核心的竞争力是什么?
AI 正在大幅压缩编码的成本。曾经工程师需要耗费数小时乃至数日才能交付的任务,如今 AI 能在数分钟内输出代码、补齐测试、修复 CI 并提交合并请求。开发者的定位也随之发生迁移——从"敲代码的人"变成"审代码的人、系统设计者与关键决策者"。代码本身的价值在持续下滑,而架构能力、设计能力、安全把控、验证手段、代码评审与判断力却愈发珍贵。AI 可以化身为永不疲倦的全天候工程师,可决定软件去向的舵盘,依然握在人类手中。
Linus Torvalds 曾经留下一句广为流传的名言:
Talk is cheap. Show me the code.
过去我对这句话深以为然。
程序员终究还是要靠代码立身。方案讲得再动听、PPT 做得再精美,如果最终落不了地,或者代码跑不通,都是空谈。
然而迈入 AI 时代之后,我越来越觉得,这句话或许得换个角度去解读。
因为当下,代码本身正在变得越来越廉价。
我甚至已经想不起,上一次自己从零手写一长段代码,是什么时候了。
现在日常的工作模式,更像是调度不同的 AI 来协作:把需求讲明白,告诉它代码库的位置、目标设定、约束条件,剩下由 AI 自行分析代码、敲定方案、改动实现、补充测试,最终提交一个 PR 给我。
多数时候,AI 产出的代码质量确实相当可观。
当然,我也不会全然放手。
通常我会先让另一个 AI 跑一轮 Code Review,排查有无明显瑕疵,再亲自快速核对关键逻辑,必要时手动补一些测试。
整套流程已经和从前截然不同了。
过去做工程的时候,如果一个 PR 一次性改动几百行乃至上千行代码,大家一般都会建议:
拆一下吧。Small PR。
这样更便于 Review,也更容易暴露问题。
这条原则当然依旧成立。
问题是,AI 把编码速度拉升了一个量级之后,人类 Review 的速度完全跟不上节奏。
如今一天涌来十几个 PR 早已司空见惯,随便一个功能模块可能就是数百行代码。
若还沿用过去的做法,一行一行仔细评审:
那这一天就什么都别干了。
所以我现在越来越多采用一种"抽样式"的 Review。
先看整体架构方向是否正确。
再挑几个核心函数过一遍。
看看数据流走向、异常如何兜底、接口是否被破坏、测试覆盖了哪些点。
大方向没有跑偏之后,许多实现细节我已经不再耗费大量精力去纠缠。
这是一个非常显著的变化:
工程师正在从 Code Writer,转型为 Code Supervisor。
不过这里也有一个颇为有趣的问题。
AI 极其擅长"解决问题"。
尤其是:
Make the CI pass.
你丢给它一个失败用例,它会拼尽全力把测试变绿。
有时确实修复了真实的 Bug。
但有时它的解法会让我哭笑不得。
比如 AI 格外热衷于写这种代码:
哪里报错,就 Catch。
还不行?
再 Catch 一层。
或者测试挂了,就加一条特判。
再挂,就继续打补丁。
最终 CI:
AI:
任务搞定。
从局部看,每一次改动都"有理有据"。
但这些代码累积半年、一年之后,会演变成什么样,就很难讲了。
这也是为什么:
CI Passing ≠ Code Quality。
甚至:
CI Passing ≠ Correctness。
测试只能证明你测过的那些场景没出问题,无法证明整个系统没有问题。
AI 特别擅长优化一个非常明确的目标函数。
你告诉它:
把 CI 跑绿。
那么它就会挖空心思让 CI 变绿。
但"让这个代码库未来五年依然好维护"是一个非常模糊、且反馈周期极长的目标。
AI 目前并不天然擅长这类事情。
不过后来我又想到另一个问题。
我们是不是还在用旧时代的软件工程思维,去衡量未来的软件开发?
过去我们总强调:
代码要 Readable。
为什么?
因为将来需要另一位工程师来读。
可如果未来 80% 的代码维护工作都由 AI 接手呢?
那么许多代码实际上或许不再是主要写给人看的,而是写给 AI 看的。
只要:
那么一些过去我们非常在意的代码风格问题,可能就没那么举足轻重了。
这并不意味着代码质量不重要。
恰恰相反。
只是"质量"的定义可能正在发生变化。
过去我们强调:
Human Readability
以后或许越来越强调:
Machine Maintainability
这两者高度相关,却未必完全等同。
所以我越来越确信:
代码在贬值,但工程能力并没有贬值。
恰恰相反,一些能力正在飞速升值。
比如:
这些东西反而比以往更加关键。
AI 可以一分钟产出几百行代码,但它无从判断这几百行代码究竟该不该存在。
这是两件截然不同的事情。
过去一个高级工程师和初级工程师最大的差距,可能是:
高级工程师一天写出的代码质量更高。
以后最大的差距或许变成:
高级工程师清楚哪些代码根本不该写。
02
Elon Musk 曾经表达过一种相当激进的观点:
未来 AI 足够强大之后,可能根本不再需要传统意义上的程序员,甚至 AI 可以绕过现有高级语言,直接产出机器可执行的内容。
我对这个判断持保留态度。
并非因为 AI 做不到。
从纯技术角度看,AI 当然可以生成 Machine Code。
问题是:
你敢运行吗?
假设 AI 给你产出一个 500MB 的 Binary。
然后告诉你:
你敢把它部署到银行?
Azure?
操作系统?
医疗设备?
自动驾驶汽车?
你怎么知道里面没有藏匿恶意逻辑?
如何做安全审计?
怎么验证它和 Specification 一致?
有人可能会说:
很简单。
再拉一个 AI 来审核。
问题接踵而至:
你怎么确保第二个 AI 是对的?
再拉第三个 AI?
那第三个 AI 又由谁来审?
如果几个 AI 都基于相似的训练数据、相似的架构、甚至相似的 Reasoning Pattern,它们完全可能犯下相同的错误。
最终,你依然会撞上最基本的问题:
谁来担责?
这也是为什么我认为,在许多关键软件系统中,Human in the Loop 很难真正消失。
如果回望整个编程语言的演进史,其实有一条耐人寻味的规律。
最初,人类直接与机器指令打交道。
后来出现了汇编语言。
再后来诞生了高级语言。
C 语言早期的编译器最初要依赖更底层的语言实现,等 C 编译器成熟后,便能逐渐用 C 来实现 C 编译器,这就是所谓的 Self-hosting。
从那以后,绝大部分程序员再也不必关心:
更不必关心具体的 0 和 1。
我们一直在不断提升抽象层级。
过去:
然后:
然后:
再后来:
现在或许正在迈入下一层:
程序员开口:
给这个 API 加一个 Rate Limiter,要支持 Distributed Deployment,不能依赖 Local Memory,把 Unit Tests 和 Integration Tests 都补齐。
AI 负责:
从这个视角看,AI 并非消灭编程。
它只是又一次抬升了编程的抽象层级。
不过,这一次和以往所有抽象层跃迁都有一个非常大的不同。
以前的工具基本都是 Deterministic 的。
同一份 C 程序:
在相同环境、相同编译器、相同参数下,理论上你期待得到确定的结果。
Compiler 不会今天心情好给你一种实现,明天心情差换一种实现。
但 LLM 完全不同。
今天你问:
Implement this function.
它可能给你方案 A。
过一分钟再问:
它可能给你方案 B。
换个模型:
方案 C。
因为当下的大语言模型,本质上仍是概率模型。
它根据已有的 Context,不断预测接下来最可能出现的 Token。
我们当然可以借助多种手段提升确定性:
这些技术都能不断压缩错误空间。
但它们没有改变一个根本事实:
AI 本身并非传统意义上的 Deterministic Compiler。
所以 AI 编程时代真正需要攻克的难题,并不是:
AI 会不会写代码?
这个问题基本已经解决了。
真正棘手的问题是:
我们怎么确认 AI 写的代码是对的?
这或许才是未来十年软件工程最重要的命题之一。
所以如果让我重新改写 Linus 那句话,我可能会写成:
Talk is cheap. Code is becoming cheap too. Judgment is expensive.
过去最稀缺的是:
把想法翻译成代码的能力。
如今 AI 正在把这个成本快速压低。
未来真正稀缺的,很可能变成:
以及,当十几个 AI 同时 24/7 不知疲倦地替你编码时,你还能否清楚地知道:
这艘船,究竟该驶向何方。
AI 可以成为极其出色的水手。
但工程师真正需要修炼的,可能已经不再是怎样划桨。
而是如何掌舵。
03
我还是会继续刷题。
尽管工作中已经很少需要自己手动写大量代码,而且力扣里的很多算法题在实际工程中也未必直接用得上,但刷题依然能让我保持最基础的编程手感。
毕竟,即便未来大部分代码都由 AI 操刀,阅读代码、理解逻辑、判别实现是否正确,这些能力依然不能丢。
而手动编码本身,就是一种极佳的训练方式。
它不仅能训练 Coding,也能训练 Problem Solving:如何拆解问题、寻找规律、设计数据结构与算法,再一步步把想法落地为可运行的代码。
而且每攻克一道题,看到那个绿色的 AC,依旧会涌起一丝简单的多巴胺愉悦。
所以我的 iPad 基本寸步不离,不在手里,就在包里。哪怕出门和媳妇约会,只要中间冒出五分钟空闲,我也能掏出来刷一道题,开心一下。
也许未来这种自己一行一行敲代码的方式,真的会逐渐演变成一种"古法编程"。
但至少对我来说,它依旧是一种很棒的脑力锻炼。
这次去威尔士露营的时候 条件艰苦也不能耽误我每天打卡力扣。