所谓“过度设计”,其实只是设计错误

刚工作时,经常听到一句话:不要过度设计。

于是很多人对接口、抽象层、设计模式都保持警惕。

代码一旦多出几层结构,就容易被怀疑是在"过度设计"。

但工作几年之后,我慢慢有了不同的理解:

很多所谓的"过度设计",其实只是设计错误。

"过度设计"是错误的切入视角,因为设计本身并不会"过度"。

真正的问题,是设计落错了地方。

软件系统中,总有一些东西会变化:

  • 不同厂商设备

  • 不同算法实现

  • 不同数据来源

  • 不同运行环境

这些地方,可以称为变化点

如果变化点没有被很好地隔离,变化就会沿着系统结构不断传播。

与变化点对应的是稳定面

稳定面是系统中尽量保持不变的接口或语义,其它模块依赖这些稳定面,而不是依赖具体实现。

好的设计,本质上只是在做一件事:

在变化点和稳定面之间建立清晰的边界。

当这个边界足够清晰时,变化通常只会影响很小的一部分代码。

可以把这理解为变化传播半径

如果新增一种算法只需要增加一个类,那么变化传播半径很小;

如果新增一种算法需要修改很多已有代码,那么变化传播半径就很大。

"过度设计",其实只是因为系统并没有真正的变化压力。

抽象存在了,但它没有隔离任何变化。

而另一种更常见的问题恰恰相反:

系统没有识别变化点,导致变化在代码中不断扩散。

从这个角度看,设计问题其实很简单:

  • 无变化而抽象,是错误设计

  • 有变化而不抽象,也是错误设计

当然,也存在另一种情况。

有时使用某种模式,并不是为了应对变化,而是为了表达结构关系

软件设计真正困难的,并不是使用多少模式,而是判断清楚三件事:

  • 哪里是变化点

  • 哪里是稳定面

  • 变化会传播多远

当这些问题想清楚之后,很多设计决策就会变得自然。