_中字_老外工程师揭秘_AI代码越改越烂的真相_BV1qAouBhEZ6_笔记
约 2322 字大约 8 分钟
2026-05-01
核心论点
软件基础原理(Software Fundamentals)从未像现在这样重要。
演讲者认为,许多人担心在 AI 时代自己的技能变得毫无价值,但事实恰恰相反:代码从来都不便宜,烂代码现在是史上最昂贵的。因为:
- 一个难以修改的代码库让你无法充分利用 AI 的能力
- AI 在好的代码库上表现极好,在烂代码库上表现极差
- 越是依赖 AI 编程,越需要扎实的基础能力来把控方向
一、Spec to Code 运动的困境
1.1 什么是 Spec to Code
所谓 Spec to Code(规格到代码)运动,主张:
- 编写应用规格说明(specification)
- 用 AI 将规格转换为代码
- 如果应用出问题,回去改规格
- 重新运行编译器,得到更多代码
1.2 实践中的问题
演讲者亲自尝试后发现:
运行 → 获得代码 → 运行 → 代码变差 → 运行 → 代码更差 → 运行 → 一团糟这正是软件熵(Software Entropy)的体现——每次改动只关注局部,整体设计不断恶化,最终产出垃圾代码。
1.3 错误假设
Spec to Code 运动基于一个错误观念:Code is cheap(代码是廉价的)
演讲者明确反对这一观点:
| 观点 | 真相 |
|---|---|
| 代码是廉价的 | 代码从来都不廉价 |
| 烂代码可以随便重写 | 烂代码是史上最昂贵的 |
| 不需要看代码 | 不看代码只会越来越烂 |
二、AI 编程的六大失败模式与解决方案
失败模式一:AI 没有按照你的想法工作
现象:你脑子里有明确的想法,但 AI 的输出完全跑偏。
根本原因:你与 AI 之间存在沟通障碍,缺乏共享的设计概念。
设计概念(Design Concept)
引用 Frederick Brooks 的《设计的设计》:
当多人共同设计某样东西时,脑海中会有一个短暂的、飘忽不定的想法——这就是"设计概念"。
它不是资产,不能写在 Markdown 文件里,而是关于"你在构建什么"的隐形理论。
你和 AI 之间没有共享的设计概念,所以它不理解你真正想要什么。
解决方案:Interview Me 技能
演讲者开发了一个技能,要求 AI 不断向你提问,直到达到共享理解:
Interview me relentlessly about every aspect of this plan until we reach a shared understanding.
Walk down each branch of the design tree, resolving dependencies between decisions one by one.工作原理:
- AI 会问 40、60 甚至 100 个问题
- 将 AI 变成"对手",不断向你确认想法
- 最终可生成产品需求文档或直接转化为 issue
- 比工具自带的 Plan Mode 更好用——后者太急于创建资产和开始工作
📦 GitHub 仓库:MikeOpenHWGroup/skills(13000+ stars)
失败模式二:AI 输出过于冗长
现象:与 AI 沟通时感觉"鸡同鸭讲",它用太多文字解释自己正在做的事,用的不是你熟悉的语言。
根本原因:缺乏共享语言(Shared Language)。
解决方案:领域驱动设计(DDD)与通用语言(Ubiquitous Language)
引用《领域驱动设计》(Domain-Driven Design):
开发者之间的对话、代码中的表达式、与领域专家的沟通,都源自同一个领域模型。
通用语言本质上是一个 Markdown 文件,包含你和 AI 共同使用的术语表:
| 术语 | 定义 | 示例 |
|------|------|------|
| Order | 客户提交的交易请求 | - |
| LineItem | 订单中的单个商品 | - |
| CheckoutSession | 完成购买的上下文 | - |演讲者开发的技能
扫描代码库 → 提取术语 → 生成通用语言 Markdown 文件 → 传递给 AI
效果:
- AI 的思考过程更简洁,不再啰嗦
- 实现结果与计划高度一致
- 改善规划质量
失败模式三:代码能运行但不符合预期
现象:AI 构建了正确的东西,但代码根本不工作。
解决方案:建立反馈循环(Feedback Loops)
| 反馈机制 | 说明 |
|---|---|
| 静态类型 | 使用 TypeScript(非 TS 项目简直是疯了) |
| 浏览器访问 | 给 LLM 访问浏览器的能力,让它能探索页面 |
| 自动化测试 | 必须有,覆盖核心功能 |
失败模式四:AI 一次性生成太多代码
现象:AI 一次性产出大量代码,然后才想起来要类型检查或写测试。
根本原因:AI 默认超出 headlights(车灯照不到的范围)。
引用《 pragmatric programmer》
反馈的速率就是你的速度上限(The rate of feedback is your speed limit)
翻译成人话:开得太快,前面黑漆漆的根本看不见路。
解决方案:TDD(测试驱动开发)
TDD 强制 AI 采取小步前进:
1. 先写测试
2. 让测试通过
3. 重构改进设计问题:测试本身就很难
| 测试决策 | 内容 |
|---|---|
| 测试单元多大? | 太大 → 测试不稳定;太小 → 依赖复杂 |
| 什么要 Mock? | Mock 哪些依赖 |
| 测试什么行为? | 需要明确边界 |
演讲者的发现:好的代码库 = 容易测试的代码库。反过来也成立——测试做得好,反馈循环才好,AI 才能产出更好的代码。
失败模式五:代码库难以理解
现象:AI 尝试探索代码库,但最后还是不理解它在做什么。
根本原因:代码库中存在大量浅层模块(Shallow Modules)。
John Osterhout 的模块设计原则
| 模块类型 | 特征 | 代码库中的样子 |
|---|---|---|
| 深度模块(Deep Module) | 大量功能隐藏在简单接口后面 | 边界清晰,内部复杂 |
| 浅层模块(Shallow Module) | 功能不多,接口却复杂 | 一堆小 blob,AI 很难导航 |
浅层模块的问题:
- 一堆零散的小代码块
- AI 要在它们之间穿梭导航
- 经常找不到正确的模块
- 无法理解依赖关系
解决方案:创建深度模块
┌─────────────────────────────────┐
│ Interface Layer(接口层) │ ← 设计重点,控制边界
├─────────────────────────────────┤
│ │
│ Deep Module(深度模块) │ ← AI 可以处理内部实现
│ - 复杂逻辑 │
│ - 隐藏在简单接口后 │
│ │
└─────────────────────────────────┘演讲者的技能:improve-codebase-architecture
- 探索代码库
- 寻找相关的代码
- 打包成深度模块
- 边界简单 → 易于测试
- 奖励 TDD
失败模式六:大脑跟不上代码产出速度
现象:能用 AI 产出比以往更多的代码,但大脑精疲力竭,根本跟不上。
根本原因:烂代码库让 AI 和人类都需要在脑中同时维护大量信息。
解决方案:设计接口,委托实现
将深度模块视为灰盒(Gray Box):
- 设计接口:仔细思考,确保接口设计良好
- 委托实现:AI 负责内部实现细节
- 从外部测试:不深入审查每个实现,只验证接口行为
┌─────────────────────────────────┐
│ 你:设计接口 + 思考模块职责 │
│ AI:处理模块内部实现 │
│ 测试:从外部验证 │
└─────────────────────────────────┘适用场景:
- ✅ 非关键模块——不必深究实现
- ❌ 金融、安全等关键模块——必须仔细审查
这样做的代价:
你作为人类在规划时必须始终考虑模块结构,理解模块的边界和职责。这必须成为你通用语言的一部分。
三、核心设计原则:每天投资系统设计
引用 Kent Beck:
每天为系统的设计投资(Invest in the design of the system every day)
| 做法 | 结果 |
|---|---|
| Spec to Code | 撤资(Divest)——忽视设计,只关注规格 |
| 本演讲建议 | 投资——每次 PR 都考虑接口和模块的变化 |
四、AI 编程的正确姿势:战略 vs 战术
┌──────────────────────────────────────┐
│ 你(战略层) │
│ - 架构设计 │
│ - 接口设计 │
│ - 需求理解 │
│ - 代码审查 │
└──────────────┬───────────────────────┘
│ 指挥
▼
┌──────────────────────────────────────┐
│ AI(战术层) │
│ - 具体编码实现 │
│ - Sergeant on the ground │
│ - 底层执行 │
└──────────────────────────────────────┘AI 是一个优秀的"地面 tactical 程序员"——但它需要有人在战略层面思考。那个人就是你。
五、关键书籍推荐
| 书名 | 作者 | 核心概念 |
|---|---|---|
| The Philosophy of Software Design | John Osterhout | 好/坏代码的定义、深度模块 |
| The Pragmatic Programmer | Dave Thomas & Andy Hunt | 软件熵、反馈速率即速度上限 |
| The Design of Design | Frederick Brooks | 设计概念 |
| Domain-Driven Design | Eric Evans | 通用语言(Ubiquitous Language) |
六、演讲者提供的资源
- 技能仓库:GitHub MikeOpenHWGroup/skills
- 网站:aiheroro.dev
- 社交媒体:YouTube、Twitter
七、核心要点总结
- 代码从来都不廉价——烂代码是史上最昂贵的
- Spec to Code 不work——忽视代码质量只会越来越糟
- 与 AI 达成共享理解——通过反复提问建立设计概念
- 建立共享语言——通用语言让沟通更高效
- 反馈循环是关键——静态类型、测试、浏览器访问
- TDD 强制小步前进——防止"超出车灯范围"
- 深度模块优于浅层模块——让 AI 和人类都更容易理解
- 设计接口,委托实现——解放大脑
- 每天投资系统设计——在每个 PR 中思考架构
- 你是战略层——AI 负责战术执行
