我得坦白一件事。2023年,我花了三周时间为一个测试自动化框架构建插件系统。可配置的测试运行器、热重载插件、依赖注入容器——全套都做了。
结果从来没人写过任何插件。
这个框架每次都在CI中用相同的配置运行。我构建的"可扩展性"被零个人使用过。如果没有这个插件架构,我本可以在4天内交付整个项目。
过度工程化是如何发生的
它始于一个看似合理的想法:"万一以后需要扩展呢?"
这个想法就是个陷阱。因为"以后"很少会像你想象的那样,而你为虚构需求构建的抽象层,往往会阻碍真正需求的实现。
以下是我在自己身上观察到的演变过程:
- 写一个简单的函数 ✅
- 心想"这个应该做成可配置的" ⚠️
- 添加配置对象
- 心想"不同环境可能需要不同的实现" ⚠️
- 添加接口和工厂模式
- 心想"我们可能需要在运行时切换" 🚩
- 添加依赖注入
- 发现从来没人需要切换
- 永远维护这个抽象层,因为删除它比保留它更难
三个问题
在添加任何抽象层之前,我现在会问:
1. "真的有人要求过这个吗?"
如果答案是"没有,但可能以后会需要"——那就别做。YAGNI(你不会需要它)是工程中最常被违反的原则。
2. "现在添加和以后添加的成本分别是多少?"
如果等到真正需要时,我能在2小时内添加这个抽象层,那就没有理由现在"以防万一"就构建它。过早抽象的成本(维护没人使用的代码)几乎总是高于以后再加的成本。
3. "我能用一句话向别人解释它为什么存在吗?"
"我们使用依赖注入是因为在不同环境中需要在Stripe和Braintree之间切换支付提供商。" 这是真正的理由。
"我们使用依赖注入是因为这是最佳实践。" 这不是理由。这是盲目跟风。
简洁代码的样子
\\
