YAGNI:保护你免于过早构建未来的原则
Source: Dev.to
YAGNI 真正的含义
YAGNI 代表 You Aren’t Gonna Need It。
这条规则极其简单:
- 如果你现在不需要,就不要现在就构建它。
- 不要出于“以防万一”。
- 不要因为它看起来在架构上很优雅而实现。
YAGNI 的来源
YAGNI 是在 1990 年代后期由 Kent Beck 作为 极限编程(Extreme Programming,XP) 的一部分提出的。
极限编程挑战了传统的软件思维:
- 快速交付
- 经常迭代
- 持续重构
- 避免投机性设计
与其预测所有未来情景,XP 采用了增量演进的方式。YAGNI 成为其核心实践之一——并不是因为防止未来变化本身不好,而是因为投机性的复杂性代价高昂。
真正的敌人:投机式工程
大多数对 YAGNI 的违背看起来很聪明。它们表现为:
- 为“可扩展性”添加抽象层
- 为不存在的实现创建接口
- 在变体真正出现之前构建配置系统
- 在只有单一客户的情况下为多租户设计
其背后的推理总是相同的:“我们可能会需要这个。”
大多数情况下你并不需要,而且你只会增加:
- 认知负担
- 维护成本
- 错误暴露面
- 入职阻力
这一切都是为了一个从未到来的未来。
简单示例
过度设计的版本
class PaymentStrategy:
def execute(self, amount):
pass
class StripeStrategy(PaymentStrategy):
def execute(self, amount):
return f"Processing {amount} with Stripe"
class PayPalStrategy(PaymentStrategy):
def execute(self, amount):
return f"Processing {amount} with PayPal"
class PaymentProcessor:
def __init__(self, strategy: PaymentStrategy):
self.strategy = strategy
def process(self, amount):
return self.strategy.execute(amount)
看起来干净、可扩展、很“架构化”,但实际上没有 PayPal,没有路线图,也没有第二个网关。你构建了并不存在的可选性。
YAGNI 版本
class PaymentProcessor:
def process(self, amount):
return f"Processing {amount} with Stripe"
简单、清晰、诚实。如果 PayPal 成为现实,你再重构——而且重构的成本比维护想象中的灵活性要低。
“但如果是扩展呢?”
- 忽视设计
- 忽视增长
- 忽视架构
它并不是这样。YAGNI 拒绝没有证据的猜测,而不是预见。正如 Donald Knuth 所说,“Premature optimization is the root of all evil”。YAGNI 将同样的逻辑应用于架构——过早的抽象只是优化的表亲。
YAGNI 与时机
工程并不是在第一天就把所有东西都做对。它关注的是:
- 构建必要的东西
- 验证假设
- 在现实需要改变时进行重构
最优秀的工程师不会为每一种可能的未来设计;他们为变化而设计。
当 YAGNI 不适用时
YAGNI 很强大,但并非绝对。不要在以下情况下使用它:
- 需求是合同性的并已确认
- 保证有多种实现方式
- 公共 API 必须保持稳定
- 以后更改的成本极高
YAGNI 对抗的是基于不确定性的复杂性,而不是基于明确性的设计。
YAGNI 的心理层面
YAGNI 挑战自我。开发者常常想要:
- 证明架构深度
- 展示模式知识
- 显示前瞻性
- 避免显得“未准备好”
成熟的工程是交付最简洁且正确的解决方案。克制是一种技能,YAGNI 是行动中的纪律。
改变一切的问题
在添加之前:
- 一个新的抽象
- 一个新的模式
- 一个新的配置层
- 一个新的通用系统
问问自己:这是否在解决一个真实、当前的问题?
如果不是… 你可能根本不需要它。
最终思考
软件在不断演进。你的系统会发生变化。需求会转变。用户会给你意外的惊喜。试图把一切都预测出来并不是智慧,而是披着架构外衣的恐惧。YAGNI(You Ain’t Gonna Need It)提醒我们:
- 为当下而构建。
- 需要时再重构。
- 相信演进的力量。
- 尊重简洁。
不要为了明天的想象牺牲今天的清晰。