上个月我收到一条私信,发消息的是个刚工作两年多的前端,他说最近一到写需求就慌,因为 AI 总能更快地把代码写出来,而他越来越搞不清楚自己到底在干什么。这条私信让我想起一个人——Matt Pocock。如果你常混 TypeScript 社区,对他应该不陌生;就算不熟也不要紧,他关于 AI 编程的那几个看法,我真心建议每个还在写代码的人都听一听。这篇文章就把我梳理出来的 5 个关键问题连同他的解法一起整理出来,顺便说说我自己把这些思路落到工作流里之后的真实体会。
1. 这个人为什么值得听:我对 Matt Pocock 的第一印象
1.1 我的第一印象:一个做类型教学的“教练”
我第一次注意到 Matt,是因为他做的类型挑战题。TypeScript 社区里有个挺出名的玩法:给你一个类型定义,让你把它实现出来。他的题目不是那种考背诵的语法题,而是逼你去思考一个类型到底在约束什么。那会儿我就觉得,这个人不是单纯教语法,而是在教人怎么“想清楚再写代码”。
后来我又看了他不少关于 TypeScript 的分享和视频教程,整体感觉就四个字:非常务实。他不爱讲花哨的奇技淫巧,反复强调的是“类型是你的第一层测试”“把错误消灭在编译之前”这类朴素原则。正是这种风格,让我在 AI 编程的话题上愿意认真听他怎么说。
说句实话,AI 编程刚火起来的时候,圈子里观点特别分裂:要么吹得天花乱坠,觉得以后程序员全失业;要么嗤之以鼻,觉得 AI 写的都是垃圾。Matt 不属于任何一边。他没有装成老学究去否定 AI,也没有跟着热度去贩卖焦虑,而是回到一个很本质的问题上:人在这条流水线里到底要负责什么。
1.2 他的核心立场:AI 放大判断力,而不是替代判断力
我把他零散的观点归纳成一句话就是:AI 不会替你做决定,它只会放大你的判断力。这句话听起来简单,细想其实挺狠的。判断力弱的人,AI 会把他的错误变成十倍速;判断力强的人,AI 会把他的效率变成十倍速。工具不会改变你的水平,它只会加速你的水平显现。
这个立场贯穿了他对每一个具体问题的回答。比如谈到初级开发者,他说重点不是要不要学写代码,而是把“学怎么写”的重心移向“学怎么判断好坏”;谈到 AI 生成的代码信不信,他说不要靠感觉判断,要靠类型系统和测试来判断;谈到人机协作的边界,他说判断接口属于谁,是人的事,不是模型的事。
理解了这层底色,后面那 5 个问题就顺理成章了。它们不是从技术文档里翻出来的冷门问题,而是每个开发者在 AI 编程落入日常之后,几乎都会撞上的真问题。
2. 第一个关键问题:AI 会不会让初级开发者失去入场机会
2.1 焦虑的源头:不是“岗位变少”,而是“台阶变了”
这个问题是焦虑感最强的一个。原因很简单,以前初级开发者的核心价值就是“能写代码”。公司在招不到高级人的时候,会招几个基础不错的新人慢慢带。那时候“会写”本身就是敲门砖。
现在情况变了。AI 在“把需求变成代码”这件事上,效率已经超过了大部分入门水平的人。一个实习生写完一个 CRUD 接口可能要一个下午,AI 可能十几秒就把骨架打好了。于是大家开始担心:连写代码都不需要新人了,我还学编程干什么?
我在这个圈子里待了挺久,说实话,问题问错了方向。AI 抢走的不是“写代码”这件事,而是“只靠写代码吃饭”这件事。初级岗位确实在变,但变得不是数量,是门槛的结构。过去门槛是“你能不能从零写出来”,现在的门槛是“给你一堆 AI 生成的代码,你能不能判断它对不对、能不能改好”。这其实是把初级岗位的要求往上抬了一层。
2.2 Matt 的解法:重新定义入门路线
Matt 给的解法不是“别学了”,而是调整学习和练习的重心。他的路线大概是这样的:
- 先练读代码,尤其是读别人写的不完美的代码
- 再练改代码,给一段现成代码加功能、修 bug
- 然后练审代码,判断一段代码有没有隐藏问题
- 最后才练写代码,而且是带着明确目标去写
这个顺序和传统教学正好相反。传统路线是“先学写,再学读”,现在他建议“先学读,再学写”。逻辑其实很通:AI 已经帮你把“写”完成了 80%,你要接住这个结果,就必须先具备“看”的能力。怎么看一段代码是否可信?怎么看类型定义是否合理?怎么看边界条件有没有覆盖?
他说过一句让我印象很深的话:以后初级开发者最重要的面试题,可能不是“手写一个排序算法”,而是“给你一段 AI 生成的功能代码,你告诉我哪里会出问题”。这句话我一开始觉得夸张,后来自己做技术面试时才发现,很多候选人真的在这一关上栽跟头。
2.3 我的理解:从拼“写得多”变成拼“看得准”
我自己这几年带过不少新人,也搭过不少问询电话,最大的感受是:能干活的 AI 让“手速”这个维度彻底失重了。以前两个人 PK,一个写得快,一个写得稳,好歹风格不同;现在论写得快,谁都快不过机器,剩下的只有“看得准”。
所谓看得准,就是拿到需求之后能快速判断 AI 给的方向对不对。比如一个需求是要做分页,AI 给了一个简化版写法,功能看着没问题,但没处理排序键的稳定性,翻页时会出现重复数据。看不出来的人,代码“跑通了”就提交了;看得出来的人,会在提交前加一个关键约束。这两种人,在 AI 时代的能力差距会像雪球一样越滚越大。
所以我的结论是:初级开发者的入场券没有消失,只是换了一张。以前是“会写”,现在是“会判断”。而且这种判断力不是天赋,它完全可以靠刻意练习获得。
3. 第二个关键问题:AI 生成的代码到底能不能信
3.1 危险的不是报错,而是“看着能用”
AI 生成代码有个特别容易误导人的特点:它给出来的东西,大部分时候语法完全正确,风格干净利落,注释还写得挺好,看起来就是一个有经验的工程师写的。但“看起来对”和“真的对”之间,隔着的恰恰是最难发现的那类 bug。
我自己就踩过这种坑。有次让 AI 处理一个时间解析的需求,核心逻辑是“把各种格式的日期字符串统一转成标准格式”。AI 给的实现很漂亮,用了正则、解析函数、异常兜底,我第一眼看完觉得没问题,甚至心生佩服。结果压测的时候发现,某个非常规格式的输入会导致解析结果整体偏移一天,而常规测试用例根本覆盖不到。
为什么这种代码特别危险?因为人类对“能跑”有天然的信任感。IDE 没报错,测试也过了,编译也过了,你就倾向于认为它是对的。但 AI 生成的代码本质上不是“经过验证的产物”,而是“从概率分布里采样出来的文本”。它模仿的是“看起来正确的代码”,而不是“经过严格论证的正确代码”。这两者之间的差距,就是出事的空间。
3.2 Matt 的解法:三层验证关卡
Matt 在聊到这个问题时,核心就两个字:验证。而且他强调的验证不是“跑一遍试试”,是三层关卡:
- 第一层是静态检查。把 AI 生成的代码放进你的类型系统里,让编译器去审。TypeScript 在这件事上的价值特别大,类型定义本身就是在描述契约,AI 生成的代码如果连契约都满足不了,直接退回。
- 第二层是自动化测试。给 AI 生成的函数补上边界条件的测试,尤其是空值、极端输入、并发场景这些 AI 特别喜欢“默认忽略”的地方。
- 第三层是人工阅读。把 AI 生成的代码当成别人提交的 PR 来看,带着“这是陌生人写的代码,我要怀疑它”的心态逐行读一遍。
他说过一句话我觉得特别实在:不要问“这段代码能不能跑”,要问“这段代码凭什么让我相信它能跑”。第一层解决“凭什么”,第二层和第三层解决“能不能”。
3.3 一个小例子:类型通过不代表逻辑正确
我举个简化过的例子,TypeScript 开发者应该都见过类似的东西。假设你要一个函数,把用户输入的数字字符串转成数字,并且超过 100 的要抛异常:
function parseScore(input: string): number { const value = Number(input); if (value > 100) { throw new Error("score exceeds limit"); } return value; }这段代码类型检查完全通过,看起来也没问题。但如果输入是"abc",Number("abc")会返回NaN,而NaN > 100是false,于是函数返回了NaN。调用方以为拿到的是一个数字,实际上拿到的是一个无法参与计算的特殊值。类型系统不会抓到这个错误,因为你写的返回类型就是number,而NaN确实属于number。
这种细节,恰恰是 AI 最常漏掉、而人可以在 review 时最容易发现的地方。我的经验是:凡是 AI 生成的涉及边界处理的代码,都要专门盯三样东西——空值、类型转换、溢出条件。这三样是重灾区。
4. 第三个关键问题:面向 AI 编程和面向 Google 编程差在哪
4.1 搜索时代 vs 生成时代,本质区别
很多从传统开发走过来的人,刚开始用 AI 时会有一种错觉:这不就是高级版搜索引擎嘛,以前我搜代码,现在让它直接给我写。表面上确实像,深想一层完全不是一回事。
以前用搜索引擎,你拿到的基本是别人已经跑过的、验证过的、有讨论和踩坑记录的代码。Stack Overflow 上的答案之所以可信,不是因为它写得漂亮,而是因为它下面有大量人的反馈,告诉你“二楼的做法在旧版本会有问题”“用这种方法记得清理资源”。换句话说,你搜到的是“被社区筛选过的经验”。
AI 生成的不是经验,它是根据你的上下文实时“猜”出来的。同一个问题,你换一种问法,它给你的答案可能就是另一套逻辑。它没有经历过真实环境的毒打,不会主动跟你说“这个方案在高并发下会炸”。这就意味着,你不能再把 AI 当成熟的同事用,你得像项目经理一样,自己负责拿主意。
4.2 Matt 的解法:把上下文变成第一公民
Matt 对这个问题给出的解法,归结起来是:面向 AI 编程的核心能力,从“搜索关键词”变成了“构建上下文”。
搜索时代,你只要想清楚搜什么关键词,就能找到高质量结果。生成时代,AI 输出的质量完全取决于你给了它多少“约束条件”。你给一段需求描述,它能给你一段代码;你给需求加上项目结构、数据结构定义、异常处理规范、依赖版本信息,它才能给你一份接近可用的代码。
我自己试过几次对比。同样一个需求:“给我写一个用户注册接口”。只给这一句话,AI 给出的东西往往是大路货,连基本的参数校验都懒得写。但如果我把数据库表结构、框架接口规范、统一返回体、已有的异常处理类全部作为上下文丢给它,它给出的代码基本上可以直接进 review 流程。差别真的不是一点半点。
4.3 可复制的 prompt 结构
分享一个我现在常用的 prompt 模板,谈不上高级,但胜在稳定,跑了很多项目验证过:
任务:实现 [功能点] 输入:{[参数一: 类型, 参数二: 类型]} 输出:{[返回值类型, 失败时的异常类型]} 约束: 1. 必须使用项目已有的 [XX 工具函数]处理错误 2. 不引入新的依赖 3. 处理 [空值 / 极端值 / 并发] 场景 4. 参考项目里 [某个模块] 的写法保持一致 完成后请先列出实现思路,再给出代码。注意最后一句,让 AI 先列思路再写代码,这个顺序能显著减少那种“一看就写、越写越歪”的情况。因为让模型先组织逻辑,它生成代码时会受到自己刚才思路的约束,比直接要答案靠谱得多。
5. 第四个关键问题:AI 时代最该练的核心能力是什么
5.1 为什么读代码比写代码重要
这个问题其实和第一个问题是一体两面,但要更深一层。不仅是初级开发者,我觉得所有开发者都应该认真想想:当机器比你写得快、写得稳的时候,你的不可替代性在哪里?
答案肯定不是“我比 AI 更会写代码”。这个领域是 AI 的主场,没必要硬刚。真正的不可替代性在于:你能理解代码背后的设计意图,能判断一段代码是否真正满足了需求,能在出问题的时候快速定位到根源。
这些能力全部属于“读代码”的范畴,而不是“写代码”的范畴。AI 可以帮你把代码输出来,但它不会帮你理解那段代码。它也不会在四个月后你回来维护的时候,帮你回忆起当初为什么这里要加一个特殊判断。如果你自己没有读懂,那这段代码对你来说就是一个黑盒,一旦出问题,你会完全无从下手。
5.2 Matt 的解法:概念模型和 code review
Matt 在聊到“AI 时代学什么”时,反复提到一个词:概念模型。大意是,你在动手写代码之前,脑子里得先有一个对系统的抽象理解——这些数据从哪里来、到哪里去、中间经过哪些变换、哪些状态是合法的、哪些状态是不可能出现的。
我觉得这个观点特别精准。AI 擅长的是“把明确指令变成代码”,它不擅长的是“在模糊需求里建立正确的抽象”。而建立抽象能力,靠的就是大量的读代码、画流程图、做反思。你现在让 AI 写代码,它给你一段函数;你要判断这段函数放在整个系统里合不合理,靠的正是你脑子里的那个概念模型。
另一个他重点强调的是 code review。很多人把 code review 当成流程负担,但他说过一句话,大意是:AI 时代,review 别人的代码就是你最重要的练习项目。因为你需要以最小的成本去发现一个你看不懂的代码里藏着的风险,这恰恰是 AI 最需要人类兜底的地方。
5.3 我的练习方法
受他的启发,我现在给自己定了一个练习计划,不知道能不能坚持下去,但至少这几个月感觉收获很大:
- 每天读一个开源项目的 diff,不一定是大项目,重点是观察别人为什么这样改。
- 拿到 AI 生成的代码,先不急着用,先自己写一个“我预期它应该怎么实现”的提纲,再看它和我的提纲差在哪。
- 每周挑一段自己过去写的代码,模拟成陌生人的 PR,认真审一遍,写 review 意见。
做完这些之后,我最大的感受是:判断力确实是一种可以训练的能力,而且它比单纯的编码速度快慢重要得多。因为快慢是机器的事,判断是人的事。
6. 第五个关键问题:人机协作的边界到底在哪
6.1 不是所有代码都适合交给 AI
AI 编程用了这么多,渐渐会发现一件事:它确实好用,但它不是万能的。有些代码交给 AI,风险成本极低,收益极大;有些代码交给 AI,风险完全不可控,收益却几乎没有。问题是你有没有意识到这两类代码的分界线在哪里。
我见过太多人,包括我自己刚开始的时候,是“把所有需求一股脑丢给 AI,能跑就提交”。这种用法迟早出事,因为 AI 的错误往往不是“一眼能看出来的错”,而是“在特定条件下才爆炸的错”。你把它埋在核心链路里,它就像一颗定时炸弹,爆的时候你已经忘了它是不是 AI 写的了。
Matt 的态度非常明确:AI 是副驾驶,不是司机。方向盘永远在人的手里。这句话不是情怀,而是工程上的必然。开飞机的时候副驾驶可以帮你执行一堆例行操作,但遇到突发情况,机长必须亲自接管。写代码也是,越是靠近系统核心、越是在边界状态、越是出错成本高的地方,越需要人自己上手。
6.2 Matt 的解法:按风险分层交付
我把他的思路总结成“按风险分层”——不同类型的任务,交给 AI 的比例完全不同。
比如下面这张对比表,是我在实际项目里反复用过的分法:
| 任务类型 | 交给 AI 的比例 | 人工投入重点 |
|---|---|---|
| 样板代码、CRUD、增删改查 | 高,可以大胆交 | 改接口字段、对齐命名规范 |
| 单元测试、Mock 数据 | 较高,适合生成 | 补边界条件、审查断言合理性 |
| 数据处理、格式转换 | 中等,先让 AI 给方案 | 重点检查边界值、空值、性能 |
| 核心业务逻辑、状态流转 | 低,以 AI 为参考就好 | 自己建模、自己写主链路 |
| 架构设计、接口契约 | 极低,AI 只能陪聊 | 自己做决策,AI 只用来扩展思路 |
这张表的核心是“出错成本”。出错成本越低、越环境隔离的任务,越可以交给 AI;出错成本越高、影响面越大的任务,越要自己握紧方向盘。这不是保守,这是把工具放在合适的位置上。
6.3 我用一张表格看明白的“什么时候自己写”
我自己在实践里还有一个辅助判断,三个问题:
- 这段代码如果出错了,影响范围是局部的还是全局的?
- 这段代码如果带着隐藏 bug 上线,我需要多久才能发现?
- 这段代码是否承载了我对这个系统的核心设计意图?
如果三个问题里有两个答案偏“严重”,那这段代码我就会自己写,或者至少自己把主干实现,AI 顶多用来补充周边细节。如果三个答案都偏“轻微”,那我可以放心大胆地让 AI 来干。
说实话,AI 写代码的水平早就过了“不能用”的阶段,真正限制我们敢不敢用它的是我们自己的兜底能力。不被 AI 拖下水的前提,是你永远知道自己写的是什么东西。
7. 我把这套思路落地后,工作流发生了哪些变化
7.1 现在我的 AI 编程日常流
受这套思路影响,我把自己的日常工作流重新整理了一遍,现在大概是这样一个流程:
每天开工前先把需求拆成小块,按上面的风险分层表分类。低风险的部分,比如接口样板、测试 mock、格式化工具函数,直接交给 AI 填充,我负责审查参数和命名。中等风险的部分,比如某个模块的数据变换,我会让 AI 先给实现思路,我亲自确认思路之后再让它写代码,写完补边界测试。高风险的部分,比如状态机、支付流转、数据一致性处理,我自己动手,AI 只用来提供参考资料和快速原型。
这个流程执行了几个月之后,最大的感受不是“代码写得更快了”,而是“代码的长期维护成本明显变低了”。以前让 AI 全包的时候,经常遇到“这段代码是谁写的?我当时怎么想的”这种灵魂拷问。现在因为高风险代码全是自己写的,低风险代码也经过了自己的审查,整个项目的可解释性提升了一大截。
7.2 踩过几次坑之后总结的检查清单
前面说了一堆方法和理念,最后把我踩坑总结的检查清单完整列出来。每次 AI 生成的代码要合进主干前,我都会过一遍这个清单,推荐你也试试:
AI 代码提交前检查清单 1. 边界值是否处理:空值、0、负数、超长字符串、null/undefined 2. 隐式转换是否可靠:Number/parseInt/字符串拼接/时间格式化 3. 异常路径是否兜底:被 0 除、请求超时、依赖服务不可用 4. 性能是否可接受:循环里有没有重复查询、有没有全表扫描 5. 状态变更是否可控:函数有没有副作用、有没有并发写问题 6. 是否引入新依赖:依赖是否可控、版本是否安全 7. 契约是否满足:类型定义、接口字段、错误码是否和约定一致 8. 可读性是否达标:别人看到这段代码能不能理解意图这个清单几乎覆盖了我踩过的所有 AI 代码坑。它不是 AI 给的,是我一条一条从线上事故里捡回来的。用了一段时间之后,我对 AI 生成的代码的信任度反而提高了,因为我知道自己已经把它放在正确的审查流程里,而不是裸奔上线。
7.3 一点个人体会
最后说句实在话。Matt 这套思路最让我服气的地方,不是他给了什么惊天动地的技巧,而是他把“人和 AI 的关系”重新拉回到一个朴素的工程原则上:工具越强,使用者的基本功越重要。
以前打字快、记性好、框架熟是优势;以后优势会转移到概念模型清不清楚、代码品味正不正、关键时刻敢不敢拍板。AI 编程不会让我们失业,它只会让我们重新回答那个老问题:你到底是在完成别人定义的任务,还是在为自己的判断负责。