领域驱动设计工作坊
上QQ阅读APP看书,第一时间看更新

1.1.1 软件复杂度与规模

本节将首先讨论第一个软件复杂度维度——规模。规模是软件复杂度最基本的表现形式。

1.规模的表现形式和关注点

关于如何评估一个软件系统的规模,业界存在很多实践方法。图1-3展示了一种常见的评估方法——功能点(Function Point,FP)评估法。

图1-3 功能点评估法

FP评估法是软件行业专用的估算方法之一。应用FP评估法时,首先识别系统边界和应用类型,区分新开发的系统和增强型遗留系统;然后识别系统的功能点计数项,包括内部逻辑文件数量、对外接口数量、输入和输出数量,以及包括排序和聚集在内的查询数量等五大计数项;识别各个功能点计数项并确定各项指标的系数后,加权求和即得到最终的估算结果。在图1-3中,我们可以看到该示例中的功能点数量为215。从这个示例中,我们明确了软件规模的一种表现形式——数量。

我们再来看软件规模的另一种表现形式——交互。图1-4展示了McCabe圈复杂度(Cyclomatic Complexity)的组成结构。

图片2

图1-4 McCabe圈复杂度的组成结构

这里解释一下圈复杂度的概念。如果一段代码中不包含控制流语句(条件或决策点),那么这段代码的圈复杂度为1,因为这段代码中只有一条路径;如果一段代码中仅包含一个if语句,且if语句仅有一个条件,那么这段代码的圈复杂度为2;如果一段代码中包含两个嵌套的if语句,或者一个if语句有两个条件代码块,那么这段代码的圈复杂度为3……以此类推。

在软件测试的概念中,圈复杂度用来衡量一个模块判定结构的复杂程度,数量上表现为线性无关的路径条数,即合理预防错误所需测试的最少路径条数,路径条数本质上就是系统内部的交互过程。圈复杂度高说明交互过程的复杂性高。根据经验,代码的出错可能性和圈复杂度的高低有很大关系。

2.规模的应对策略

如何应对规模导致的软件复杂度?基本思路就是通过分而治之来控制规模。分而治之是一种设计思想,这一设计思想有多种实现策略,其中最具代表性的就是图1-5所示的AKF扩展立方体。

图1-5 AKF扩展立方体结构

AKF扩展立方体是业界关于如何开展系统拆分工作的一条原则,通过这条原则,系统就可以实现高度的扩展性。在AKF扩展立方体的X轴上,开发人员可以使用负载均衡等技术来实现水平复制;在Z轴上,开发人员可以使用类似数据分区的方式实现系统扩展性。这里需要重点关注的是Y轴,它提示针对单体系统,应该基于业务体系按功能进行拆分。实际上,AKF扩展立方体也为拆分微服务提供了解决方案。

系统拆分的基本思路有两种——纵向(Vertical)拆分和横向(Horizontal)拆分。所谓纵向拆分,就是将一个大应用拆分为多个小应用。如果新业务较为独立,那么直接将其部署为一个独立的应用系统。例如,在图1-6中,将互联网医院系统拆分为医生子系统、就诊子系统和患者子系统等独立业务子系统。

图1-6 系统纵向拆分示例

纵向拆分关注业务,基于不同的业务场景,通过将内聚度较高的相关业务进行剥离以形成不同的子系统。相较纵向拆分的面向业务特性,横向拆分更关注技术。将可以复用的业务进行拆分,独立部署为分布式服务后,我们只需调用这些分布式服务即可构建复杂的新业务。所以,横向拆分的关键在于识别可复用的业务,设计服务接口并规范服务依赖关系,示例如图1-7所示。

图1-7 系统横向拆分示例

图1-7是对图1-6中的互联网医院系统进行横向拆分的结果。可以看到,当我们将医生、就诊、处方和患者等业务抽象为独立的垂直化服务,并在各个服务上应用分布式环境下的调用和管理框架时,系统的业务就可以转变为一种排列组合的构建方式,如基于医生和处方服务,我们可以构建出业务A,基于就诊和患者服务,我们可以构建出业务B。