原则

YAGNI:"You Aren't Gonna Need It"(你不会需要它)。

含义:不要为"将来可能需要"的功能写代码,只实现当前需要的。

为什么重要

一、预测未来的需求是很难的

研究表明,人们(包括领域专家)在预测未来需求上表现很差。

结果:为"将来"写的抽象和扩展点,往往:

  • 从未被使用;
  • 或者被使用时,当初的设计假设已经错了。

二、代码是有成本的

每一行代码都要:

  • 被阅读和理解;
  • 被测试;
  • 被维护(依赖升级、重构、修改);
  • 可能引入 bug。

没用到的代码不是"免费的可选项",而是持续的成本。

三、过早的抽象会束缚你

一个为"可能的多种情况"设计的抽象,当你真正遇到第二种情况时,往往会发现:

  • 实际情况与预期不同;
  • 抽象的接口不对;
  • 修改这个抽象的代价比当初直接写更高。

这就是"错误的抽象比重复更糟糕"。

一个常见场景

// 需求:支持 MySQL
// "将来可能要支持 Oracle、PostgreSQL……"
public interface DatabaseAdapter { ... }
public class MySQLAdapter implements DatabaseAdapter { ... }
// 但永远只有 MySQLAdapter 这一个实现

YAGNI 的做法:先直接用 MySQL 的客户端写。

如果将来真的需要支持第二种数据库,那时你有两个具体的实现,才能看出哪些是需要抽象的共同点——这时抽象才是正确的。

这就是"三次法则"(前文提到过):第一次直接做,第二次注意重复,第三次才抽象。

例外情况

YAGNI 不是"不做任何设计"。

一、架构级的决策应该有一定前瞻性

比如:

  • 数据模型和存储选型;
  • 服务边界的划分;
  • 对外暴露的 API 契约。

这些后期变更成本极高的决策,值得多想一步。

但"多想一步"不等于"实现所有可能性"——你可以选择架构,让它容易在未来扩展,而不必现在就把扩展实现出来。

二、明确的、有依据的未来需求

如果需求方明确说"下个季度要支持 X",且这是可信的,那么现在就考虑 X 是合理的。

判断标准:这是"我猜可能会",还是"我们确定会"?

三、安全与合规要求

某些安全设计不能等到"需要时再加"——因为事后补的成本和风险都太高。

与其它原则的关系

KISS(Keep It Simple, Stupid):保持简单。

DRY(Don't Repeat Yourself):不要重复。

注意 DRY 与 YAGNI 的张力:

  • DRY 说:消除重复;
  • YAGNI 说:不要为将来写代码。

协调:对已经存在的重复,DRY 适用;对想象中的未来需求,YAGNI 适用。

少量重复的成本,往往低于过早抽象的成本。

一个实用的自问

在加一段"为了将来"的代码前,问自己:

  1. 这个需求在当前是真实存在的吗?
  2. 如果不加,将来加的成本有多高?(如果很低,那就现在别加)
  3. 我对未来的预测有多大的把握?
  4. 这段代码现在有人用吗?

如果"将来加的成本"很低(通常如此),那就遵循 YAGNI。

一句话

"为今天设计,为明天做好准备(但不要今天就建造明天)。"

让代码保持易于修改,比让它预先包含所有可能性更有价值。

说明:本文为软件设计原则的知识整理。