软件复杂度

通常系统设计时,涉及到的两类复杂性:

  • 实质复杂性 Essential Complexity
  • 附属复杂性 Accidental Complexity

这个概念,最早出现在Brooks的『人月神话』没有银弹章节,文中Brooks将软件开发的困难分为两类:

  • 本质类(essence):软件本身在概念建构上存先天的困难;即问题本身的复杂性。
  • 附属类(accident):将概念上的构思施行于计算机上,使用编程语言表达这些抽象实体,所遭遇到的困难。

Brooks认为,附属类的复杂度最终会随着工具的改善而逐渐淡化,反而是本质性的困难最难以解决。人月神话出版于上个世纪70年代,Brooks本人是IBM System/360研发出身,得出这类结论也比较正常。然而,对于业务类系统,其本质的复杂度可能并不太高,但是随着时间的发展,其本身的附属性复杂度却会越来越高

附属复杂性通常是人们在解决实质复杂度的过程中衍生的,即系统设计的初衷是解决本质复杂性,
但解决方案本身带来了新的问题。

事实上,我们在使用很多软件框架都在一定程度上表现出附属复杂性的问题,这本质上是由于框架/解决方案只适用特定的场景,归根结底是系统设计一定是基于场景的Trade-off。比如我们引入分层架构时,会遇到不同Layer对象的转换复杂度;我们引入DDD/DCI时,领域实体抽象,领域对象管理的复杂度;我们引入云原生架构时,会遇到应用层开发模式转变的复杂度等等。

上面的复杂度更多体现为解决方案的成本,然后解决方案的误用,也会产生更大的附属复杂性,这更多的体现为方案的反模式(Anti-Pattern)。比如,单体架构中的反模式:大泥球/意大利面架构,分层架构中的千层面架构,领域化设计中的贫血模型等等。这部分的附属复杂度是我们更需要重点关注和避免的。