核心论点:AI Coding 的出现,把工具链的速度瓶颈从"人类打字速度"移到了"编译/测试反馈速度"。在这个新基准下,Scala/SBT 的编译慢不再是小问题,而是系统性的生产力损耗。
一、一个被 AI 放大的旧问题
编译慢,Scala 程序员早就知道。
但以前这个问题不致命——因为瓶颈在人。写代码慢,思考慢,编译等待只是喝杯咖啡的借口。
AI Coding 改变了这个前提。
当 AI 能在 30 秒内生成一个完整实现,当 TDD 的"写测试→AI实现→验证"循环理论上可以压缩到 90 秒时,编译等待就从背景噪音变成了主要矛盾。旧问题,在新语境下,变成了新瓶颈。
二、反馈循环,是思维的延伸
TDD 的本质不是测试,是节奏。
红灯亮起,你知道方向错了。绿灯亮起,你知道可以前进。这个信号必须足够快,快到能嵌入你的思维流,而不是打断它。
心理学上有个概念叫"心流"(Flow)——当反馈足够即时,人会进入一种高度专注的创造状态。而打断心流的代价,远不止被打断的那几分钟。
< 5 秒的反馈 → 思维连续,你在"驾驶"代码
5s ~ 30 秒 → 开始分心,思维开始漂移
> 1 分钟 → 心流断裂,你在"等待"代码
Scala/SBT 的红绿循环普遍在 1~3 分钟。这意味着,每一次 TDD 迭代,都是一次强制性的心流中断。
TypeScript + vitest,Python + pytest,红绿循环在 3~5 秒。这意味着,工具链在配合你思考,而不是阻碍你思考。
三、AI 重新定义了工具链的价值坐标
过去评估编程语言和工具链,核心维度是:
- 表达能力(能不能写出优雅的抽象)
- 类型安全(能不能在编译期捕获错误)
- 生态完整性(有没有需要的库)
这些维度在 AI Coding 时代依然重要,但权重发生了根本性偏移。
AI 能补全大量的样板代码,能写出符合类型约束的实现,能快速检索生态用法。这些原本需要工程师付出大量时间的事,AI 都在接管。
于是剩下的稀缺资源只有一个:工程师的注意力。
而注意力最大的杀手,是等待。
| 维度 | Pre-AI 时代权重 | AI Coding 时代权重 |
|---|---|---|
| 表达能力 | ★★★★★ | ★★★☆☆(AI 补) |
| 类型安全 | ★★★★☆ | ★★★★☆(仍重要) |
| 生态完整 | ★★★★☆ | ★★★☆☆(AI 检索) |
| 反馈速度 | ★★☆☆☆ | ★★★★★ |
| TDD 友好度 | ★★★☆☆ | ★★★★★ |
Scala 在前三个维度表现优秀,但在后两个维度,它输给了脚本语言。
四、数据:两个世界的 TDD 体验
循环耗时对比
| 阶段 | Scala/SBT | TypeScript | Python |
|---|---|---|---|
| 写完测试 → 首次编译 | 30s ~ 2min | 瞬时 | 瞬时 |
| 修改实现 → 增量编译 | 10s ~ 40s | < 2s | 瞬时 |
| 运行单个测试 | 5s ~ 20s | < 1s | < 1s |
| 完整红绿一次循环 | 1 ~ 3 分钟 | < 5 秒 | < 3 秒 |
AI Coding TDD 工作流对比
理想循环(Python/TS):
写测试(30s) → AI生成实现(30s) → 测试通过(3s) → 下一个需求
总计:~63秒/需求,心流完整
Scala 实际循环:
写测试(30s) → AI生成实现(30s) → 等待编译(60s)
→ 等待测试(20s) → 调试重编译(40s)
总计:~3分钟/需求,心流 3 次中断
一天 8 小时,按 TDD 节奏迭代:
- Python/TS:可完成约 400+ 次红绿循环
- Scala/SBT:可完成约 80~160 次红绿循环
5 倍的差距,不是语言差距,是节奏差距。
Scala 慢的根因
- JVM 启动开销:每次运行都要热身,Python/Node 直接解释执行
- 编译器本身重量级:类型推断、implicit 解析、macro 展开,每次编译都是完整的类型系统运算
- Zinc 增量编译不可靠:改一个 trait,可能触发整个模块重编译
- 测试框架初始化:ScalaTest/Specs2 类加载成本高
五、当前的缓解手段(治标)
在不换语言的前提下,可以做的优化:
1. 常驻 SBT Shell + watch 模式
sbt
~testOnly com.example.MySpec # 文件保存自动重跑
避免每次重启 JVM,循环从 2min → 30~60s。
2. 精确控制测试范围
sbt "testOnly *MySpec"
避免全量测试,只跑目标 Spec。
3. 引入 bloop 编译后端
Bloop 是独立 Scala 编译服务,比 SBT 原生快 20~40%,支持 BSP 协议。
bloop test --only com.example.MySpec
4. 拆分编译单元
将核心业务逻辑独立成小模块,减少 Zinc 的重编译范围。
5. TDD 聚焦纯逻辑层
对重依赖的集成层(HTTP、DB)不强行 TDD,只对纯函数逻辑层使用 TDD,减少等待。
六、更深的战略思考
6.1 不是 Scala 的错,是场景错配
Scala 的编译慢,是为了它的强大付出的代价——强类型、高阶抽象、函数式纯粹性,这些在大型分布式系统中有巨大价值。
问题在于:高频迭代的 TDD 工作流,本质上是探索性、实验性的。而 Scala 的设计哲学是"编译期尽量多做,运行期尽量安全"。两者的节奏本来就不同。
把 Scala 用在稳定的、大型的、需要长期维护的核心系统上——它的编译慢是值得的。把 Scala 用在快速迭代的、AI 辅助探索的、逻辑频繁变化的业务层上——它的编译慢是不值得的。
6.2 AI Coding 时代的语言选型新原则
选语言,不只是选表达能力,更是选开发节奏。
在 AI 大量接管"写代码"这件事之后,工程师的核心工作变成了:
- 定义问题(写测试、写规格)
- 验证结果(看测试通过、看行为正确)
- 调整方向(修改测试、调整约束)
这三件事,都依赖快速反馈。
语言和工具链的首要职责,不再是帮你"写得更优雅",而是帮你"想得更快"。
6.3 一个实用的混合策略
| 层次 | 特征 | 推荐技术选型 |
|---|---|---|
| 核心执行层(稳定、长期) | 高性能、强类型、复杂状态机 | Scala(当前栈) |
| 业务逻辑层(频繁变化) | AI 辅助、TDD 优先、快速探索 | Python / TypeScript |
| 胶水层 / 脚本工具 | 一次性、自动化 | Python |
不必全面替换,但新的、独立的、需要频繁迭代的模块,值得用 TDD 友好的语言重新评估。
七、结论
编译慢这件事,在 AI Coding 时代不再是"忍一忍就好"的小问题。
它是思维速度的限制器。
当 AI 把代码生成速度提升 10 倍,而编译反馈速度没有改变,整个工作流的瓶颈就从"人写代码"转移到了"等待编译"。我们把 AI 的潜力,堵在了工具链上。
Scala 是一门优秀的语言。但在 AI Coding + TDD 的工作流下,它的节奏和这个时代的需求产生了错位。
承认这个错位,是做出正确技术决策的前提。
好的工具,应该让你感觉思维在流动。当你在等待编译,你等待的不只是字节码——你等待的,是下一个想法的权利。