复杂或复杂性与简单相对立,那么复杂是什么?它是我们大脑中的一个概念,但是我在网上找不到一个给复杂恰当的定义描述,它会有不同的解释。 其中洛克在《人类理解论》中说道:『一些思想是由简单的思想组合而成,我称此为复杂;比如美、感激、人、军队、宇宙等。』 作为研究复杂系统的专家 Melanie Mitchell,也没有给出一个明确的公认的定义。她在《复杂》一书中给出了复杂系统加以定义:『复杂系统是由大量组分组成的网络,不存在中央控制,通过简单运作规则产生出复杂的集体行为和复杂的信息处理,并通过学习和进化产生适应性。』 上述复杂系统中的组分对应软件系统中的组成部分,基于不同粒度可以是对象、函数、类、包、模块、组件和服务等。每一部分都应该是相对单一的职责,细粒度部分之间耦合提供更粗粒度功能,不同组分之间相互协作来提供系统功能,继而组合成我们复杂的软件系统。
计算机的产生对我们生产生活产生的影响不言而喻,其中软件系统的功能是随着我们实际生活需求的变化而变化的。人有七情六欲带来的各种需求,接收信息的方式主要是视觉、听觉。而机器擅长的只是简单的逻辑处理和数值计算,两者之间有着巨大的鸿沟。如何让机器提供视觉和听觉的手段来满足人们的需求,这里抛开硬件不谈,软件层面有操作系统提供基本的软件运行环境。 软件系统则只需要专注于如何组织和管理数据来满足人们的工作生活娱乐需求,一方面要关注人的需求和需求变化,另一方面要关注机器层面能提供的计算能力。 软件系统的复杂性来自于两个方面,一方面是需求侧复杂,导致大多数系统的功能都难以理解;另一方面是难以把控需求的变化,虽然我们遵循一些设计原则可以对未来进行一些预判,但还是存在不可预测的风险。
在《复杂》一书中作者列举了不同角度可能度量复杂性的方法。
复杂度并没有一个统一明确的度量方式,我们可以站在一个角度上对具体的某类或粒度提供一个可供参考的度量方法。不论我们如何度量,我们在开发软件系统中的一个重要目标就是控制和降低系统复杂度。在巨著《人月神话》中提出了两个重要概念:
偶然复杂度不是待求解问题的本质,相对而言, 本质复杂度和待求解问题的本质有关,是无法避免的。偶然复杂度一般是因为选用求解问题的方法时所引入的。
在源代码层面为了描述工程质量有以下两个方面衡量:
在认知复杂度的计算方法中主要基于以下三条规则:
下面实例对比两种复杂度度量方法的差异,在不同写法上圈复杂度的统计和认知复杂度的统计有何差异。
上图是两种写法在圈复杂度的统计方法,得出的值都是 4,也就是从逻辑上来说是相同的。但是在可读性上来说,明显右侧的 switch 代码更高。认知复杂度就是为了度量人的易于理解性上存在的。
以上是认知复杂度算法给这两种方法打出了明显不同的分数,这些分数更能反映出它们的相对可理解性。更具体的内容可以查看 CognitiveComplexity 。
架构的本质目标就是管理复杂度,而管理复杂度有以下三种有效的手段: