背景:一篇十年前的经典重新引爆讨论
Sandi Metz 在 2016 年发表的博客文章《The Wrong Abstraction》再度登上 Hacker News 首页,获得 414 分和 83 条评论。这篇文章的核心观点源自她 2014 年 RailsConf 演讲中的一句话:「重复远比错误的抽象更便宜(duplication is far cheaper than the wrong abstraction)。」十年过去,这个观点不仅没有过时,反而在每次被重新提起时引发越来越强烈的共鸣。
核心观点:错误抽象的滑坡效应
Metz 描绘了一个经典场景:程序员 A 发现重复代码,将其提取为一个新的抽象(方法或类),然后满意地离开。时间流逝,新需求出现——当前抽象「几乎完美」但不完全适用。程序员 B 感到有义务保留现有抽象,于是添加参数和条件逻辑来区分不同情况。随着更多需求到来,条件分支不断增加,曾经通用的抽象变成了一团乱麻。
关键洞见是:这个过程几乎不可逆。一旦抽象被建立,后来的开发者会(正确地)假定它是经过深思熟虑的设计产物,而不是一个需要被质疑的临时方案。错误的抽象会持续扩散,像病毒一样感染与之交互的每一行代码。
社区讨论:DRY 被滥用的血泪史
评论区充满了开发者亲身经历的惨痛教训。znkr 写道:「我维护过的最糟糕代码,就是那些试图遵循 DRY 却不理解其原始意图的代码。唯一的出路是大规模代码重复。」strongpigeon 总结道:「任何经历过两种代码库的人都会同意——维护设计不足的代码,远比维护过度设计的代码容易得多。」
ultim8k 的评论辛辣而精准:「90% 的公司里都有所谓的资深开发者,一创建新抽象就兴奋不已。过度工程、过度抽象和过早优化是工程的三大瘟疫——但也正是它们的存在保证我们永远有工作。」
关于「单一真相源」的辩证
并非所有人都完全认同 Metz 的观点。lg5689 提出了一个重要的补充:「单一真相源(Single Source of Truth)是始终应遵循的原则。如果重复代码的分歧会导致 bug,那么就应该重构。但如果并不违反这一原则,抽象就只是一种便利——当它变得不再便利时,就没有理由继续使用。」
这一辩证揭示了问题的关键:不是不要抽象,而是不要在还没有充分理解问题域的时候就急于抽象。过早抽象往往是对未来需求的错误预测,而重复代码至少是诚实的——它直言不讳地告诉你,这些代码片段目前是独立的。
功能性编程视角
bhouston 提供了一个有趣的替代视角:「自从转向几乎纯粹的函数式编程后,我发现代码重复变得罕见。你只需要写一个函数,在两个地方调用它。主要的抽象问题变成了数据结构,而 TypeScript 的鸭子类型接口让这方面也很少有麻烦。」这表明编程范式的选择也能在很大程度上影响抽象困境的发生频率。
总结
Sandi Metz 的「重复优于错误抽象」之所以能持续引发共鸣,是因为它挑战了软件工程中最被滥用的教条之一。DRY 原则本身是正确的,但它被简化为「任何重复都要消除」的口号时,就变成了有害的教条。真正的智慧在于知道何时抽象、何时容忍重复——而这需要经验、判断力,以及对自己「可能还不足够理解这个问题」的诚实认知。
📎 原文链接:The Wrong Abstraction — Sandi Metz
💬 HN 讨论:news.ycombinator.com/item?id=48620090