乐于分享
好东西不私藏

软件基本功在AI时代变得更加重要

软件基本功在AI时代变得更加重要

Matt Pocock 是一位知名的 TypeScript 专家、在线教育者及软件工程师,目前专注于 AI 辅助编程教学。

AI 时代的软件基本功

核心观点:软件基本功比以往任何时候都更加重要。优秀的代码库是享受 AI 红利的前提,糟糕的代码是有史以来最昂贵的。

一、背景:从规范到代码运动的陷阱

当前流行一种”从规范到代码”(Spec-to-Code)的理念:

  • 写一份应用规范,让 AI 将其转化为代码

  • 出了问题不看代码,只修改规范,重新”编译”

  • 反复运行,期望代码自动变好

现实却是:每次运行编译器,代码只会越来越糟,最终得到一堆垃圾。这种做法本质上只是换了个名字的”凭感觉写代码”(cowboy coding)。

二、为什么代码并不廉价

“代码很廉价”是一个流行但错误的前提。

  • 糟糕的代码库难以修改,让你无法享受 AI 带来的好处

  • AI 在良好的代码库中表现非常出色

  • 因此,优秀的代码库比以往任何时候都更加重要

两本经典著作的支撑

书籍

核心概念

启示

John Ousterhout《软件设计的哲学》

复杂性——让系统难以理解和修改的结构性因素

好的代码库 = 容易修改的代码库

《程序员修炼之道》

软件熵——事物趋向混乱、分崩离析

每次只顾眼前改动而不考虑整体设计,代码库只会越来越糟

三、AI 编程的五种失败模式与应对策略

失败模式 1:AI 没有按照我的意愿去做

你和 AI 之间存在沟通障碍,AI 做出了你不想要的东西。

根因:你和 AI 之间没有共享的”设计概念”(Design Concept)。

来自 Frederick P. Brooks《设计的设计》:当多人协作设计时,需要一个共同的无形概念——设计概念。它不是资产,不是 markdown 文件,而是你们正在构建的东西的共识。

应对——GrillMe 技能

  • 让 AI 不断采访你,确认计划细节,直到双方达成共识

  • 深入设计树的每个分支,逐一理解决策之间的依赖关系

  • AI 会问你 40-100 个问题,在满意之前不会停止

  • 对话结果可转化为 PRD 或任务,交给 AI 代理执行

  • 核心思路:先达成共同的设计理念,再开始执行(比急于制定计划更好)

失败模式 2:AI 说话太啰嗦,鸡同鸭讲

你和 AI 之间没有共同语言,AI 用大量词语却表达不到点子上。

根因:这和开发者与领域专家之间的语言鸿沟完全一样。

应对——通用语言(Ubiquitous Language)

来自领域驱动设计(DDD):通过通用语言,开发者之间的交流、代码表达、与领域专家的对话,全部源自同一个领域模型。

具体做法:

  • 扫描代码库,查找术语

  • 生成一个 markdown 文件,包含所有术语的表格

  • 确保术语含义与实际完全一致

  • 在代码、讨论、与 AI 沟通中统一使用这些术语

效果:提升规划质量,让 AI 思考更简洁,最终实现更符合规划。

失败模式 3:AI 构建了正确的东西,但不能正常运行

应对——反馈循环

必须为 AI 提供以下反馈机制:

  • 静态类型检查(TypeScript)

  • 浏览器访问(前端开发时让 LLM 查看页面)

  • 自动化测试

但仅仅有反馈循环还不够——LLM 并不像资深开发者那样充分利用它们。

来自《程序员修炼之道》:”超越你的车灯”——开得太快,因为反馈的速度就是你的速度上限。

LLM 默认行为:一次性生成大量代码,然后才想起来做类型检查或跑测试。

应对——TDD(测试驱动开发)

  • 先写测试 → 让测试通过 → 再重构

  • TDD 迫使 LLM 采取小步前进的方式

  • 好的代码库是容易测试的代码库——又回到了”代码本身很重要”

失败模式 4:AI 不理解你的代码

代码库充满浅层模块,AI 需要在大量小块中穿梭导航,无法及时找到正确模块或理解依赖关系。

应对——深层模块(Deep Modules)

来自 John Ousterhout:代码库应拥有相对较少的大而深的模块,而非大量浅层模块。

深层模块

浅层模块

大量功能隐藏在简单接口后面

功能不多,接口却复杂

隐藏了复杂性

暴露大量函数,结构混乱

AI 擅长理解和探索

AI 难以探索和理解

重构方法

  • 探索代码库,寻找彼此相关的代码

  • 将相关代码封装进深层模块

  • 精心设计接口(否则 AI 可能搞砸设计)

  • 具体实现可一定程度交给 AI

  • 在接口层进行测试,通过接口验证

失败模式 5:交付更多代码,但大脑跟不上了

AI 加速了开发,但你却比以往更疲惫——因为你的大脑和 AI 一样需要记住所有信息。

应对——设计接口,把实现交给 AI

  • 把深层模块当作”灰盒”:只设计接口,不过多审查具体实现

  • 在应用中不太关键的部分,无需在意内部实现

  • 前提:模块外部有可测试的边界,你理解它的用途,能从外部验证

  • 关键领域(如金融)仍需审查

进一步要求

  • 熟悉应用中的模块地图,将其纳入通用语言

  • 在 PRD 中具体说明模块变更和接口修改方式

Kent Beck:每天都要投入到系统设计中。

从规范到代码的运动恰恰是在撤出对系统设计的投入——这是最危险的趋势。

四、总结:你就是那个战略层面的人

  • 代码并不廉价,代码很重要

  • AI 是一位非常优秀的基层/战术型程序员——擅长做代码变更

  • 但 AI 之上还需要有人在战略层面进行思考——那个人就是你

  • 这需要我们过去 20 年甚至更久以来一直在使用的软件基础技能

不要因为 AI 的出现就抛弃经典的软件设计原则——恰恰相反,现在比任何时候都更需要它们。