9. 高层分割

复杂性是层次化的。 -- Frederick.P.Brooks,《人月神话》

分析与综合是思维方向相反的过程。一部是先分析后综合,没有分析就不能综合;没有综合的分析,也只有片面的分析。 -- 肖纪美,《梳理人、事、物的纠纷:问题分析方法》

“架构 = 模块 + 接口”的做法,其不足可概括为两点。

第一,忽视了多视图。“模块 + 接口”仅是逻辑架构设计视图的核心内容,而软件系统的架构设计还可能涉及开发视图、运行视图、物理视图、数据视图等多方面的考虑。

第二,忽略了概念架构设计。对规模较大的系统而言,都必须先根据重大风险(包含功能方面、质量方面、约束方面),有针对性的制定包括“高层分割”在内的设计决策,然后才是“模块 + 接口”一级的设计。

那么,如何对软件系统进行“高层分割”呢?这属于Conceptual Architecture阶段第2步的工作。也真是这一章要说的主题。

9.1. 高层分割的两种实践套路

  • 切系统为系统
  • 切系统为子系统

在实践中,经常出现这两种方式。虽然从理论上,设计是层层嵌套展开的--即“每一级的子系统”对“下一级的子系统”而言都是系统,都可以单独定义需求和进行设计。但这里更强调“两种套路”的思维。也就是说:

  • 要么告诉自己:我面对的是1个“系统的系统(System of Systems)”
  • 要么告诉自己:我要把这个“原子系统”切成若干子系统

9.1.1. 切系统为系统

“切系统为系统”是一种缩略的说法,具体是指:

  • 系统比较复杂,需要进行两级高层切分。
  • 首先,把系统切成更小一级的系统,每个更小一级都可以有单独的需求、设计、实现......
  • 之后,针对每个“更小一级的系统”进行“切系统为子系统”......

这样做的现实意义是巨大的。

面临比较复杂的软件系统,很多企业都有“这个项目要设几个架构师”的困惑。以电信或广电领域的BOSS系统为背景。

在实践中,当面临如下两种情况时,你需要考虑“切系统为系统”:

  • 当系统覆盖的功能范围比较广泛
    • 例如,BOSS系统设计的需求范围广泛--涵盖网络管理、服务开通、计费、客户关系管理等,于是按照“切系统为系统”的做法分为网管系统、服务受理系统、计费系统、客户关系管理系统等。
  • 当系统需要部署在比较复杂的硬件环境中
    • 很多城市基础服务行业、大型机构、大型企业,都很重视“一卡通”的应用。例如,如一卡通系统要无缝支持HR管理、出入控制、后勤保障等方面的功能,就必须充分考虑复杂的硬件环境给架构带来的冲击--硬件的种类设计考勤机、通道机、闸机、自助查询机、PC机、服务器等,于是应当合理规划组成整个一卡通系统的嵌入式应用、桌面应用及Web应用等。

9.1.2. 案例:SaaS模式的软件租用平台架构设计

再举一例,来说明如何进行“切系统为系统”式的高层分割。

案例背景

SAAS风潮又起(以前叫ASP),“软件租用平台”为用户提供统一的软件租用服务。软件租用平台提供的高层功能描述。

高层分割的思维

业界有数据表明,需求的复杂程度没增加25%,解决方案的复杂程度就增加100% 。那么,我如果应该把“软件租用平台”切成三四个相对独立的系统而没切,就意味着人为的制造灾难--太多问题相互杂糅在一起,造成解决方案的复杂程度陡增。

借助鲁棒图,初步识别功能背后的职责,就可以规划高层切分的具体方式。

具体思维过程如下:

结果呢?1个系统被切为3个系统--组件管理系统、运营管理系统、应用定制系统。

分别设计和开发这3个单独的系统,比直接把软件租用平台当成1个System开发的可控性高多了。复杂性是根本问题(《人月神话》语),虽然无法降低,但是可以控制。

9.1.3. 切系统为子系统

这种方式相当经典,无需太多铺垫。实践中,最常见的就是分层。

案例背景

使用用例图来描述PM系统的功能

高层分割

PM系统的高层分割,采用了经典的4层架构方式。

9.2. 分层式概念服务架构

人们常说,“分层式最流行的架构模式”。从字面上理解,这似乎意味着大家所进行的“分层”在思想层面上是一致的。但事实并非如此。在实践中,分层有不同的角度,并且互不矛盾。通常会总结为“3 + 1”流派。

  • Layer:逻辑层
  • Tier:物理层
  • 按通用性分层
  • 技术堆叠

9.2.1. Layer:逻辑层

逻辑层(Layer)重视职责的划分,职责之间常常是上层使用下层的关系--但是根本不关心上层和下层是否“能分布”在不同机器上。

图片来源:Layered Business Architectures: Logical Structures

  • 图中的Services层对下层Domain Model部分的访问,是一种跨机器的远程访问吗?
  • 答案是:不知道,也不关心。整个架构图中的箭头表示的是逻辑上服务使用关系,而对物理角度是否是跨机器的访问方式并不关心。
  • Layer分层 ≠ 按Tier分层。
  • 图中的User InterfaceServicesDomain ModelPersistent Data是通用性逐渐增加吗?(”通用性越大,所处层次就越靠下“是按通用性分层的常见方式。)
  • 答案是:无法确定那一层更通用。例如,作为最下层的Persistent Data层本来支持硬盘,但后来要支持磁盘阵列,再后来要支持SAN(存储区域网络),这都要求存Persistent Data层要有针对性的进行改变。
  • Layer分层 ≠ 按通用性分层。

9.2.2. Tier: 物理层

物理层(Tier)指”能分布“在不同机器上的软件单元,不同的物理层之间必须有跨机器访问的能力--可以通过远程调用、或通讯协议等方式。

图片来源:Oracle Application Server Containers for J2EE

关于Tier这种分层方式, 最需要强调的是,几层(Tier)架构是看”能分布“的能力,不是看”实际部署情况“。

我们常说的Java EE应该是N-Layer的,因为从逻辑上来看,Java EE里面有表现层、业务逻辑层和数据持久层。从物理上而言,这3层可以在不同的Tier上(表现层在PC上,业务逻辑层在应用服务器上,数据持久层在数据库服务器上),也可以在一个Tier上,比如Martin说过,如果把数据库、应用服务器和浏览器都装在一台电脑上,那么3-layer就在1-tier上了。

这段话问题不小。毕竟,”N-Tiers架构“的一大好处是可伸缩性--业务量小的时候将NTier都部署在同一台机器上 ,等业务量大的时候再为每个Tier单独安排一台或一组机器,这恰恰是"N-Tiers架构"的目标!所以,一个系统如果架构设计时是”4-Tiers架构“的,并且开发时也实现了这一点,那么把它们部署在同一台机器上并没有改变”4-Tiers架构“。最终,工程师的实际部署方案觉得了系统是几层(Tier)架构,这未免荒唐。

其实,总结出”3级“映射关系(而不是”两级“)就清楚了:

逻辑层Layer -> 物理层Tier -> 一台或一组计算机

关于按Tier分层 ,再看一例:微软的Azure虚拟网络系统,很明确的进行了不同的tier的划分,各层之间必然是能以进行跨机器方式的协议互相通讯的(只不过每个Tier的部署规模比较大罢了)。

图片来源:Azure中具有Apache Cassandra的Linux多層式架構 (N-tier) 應用程式

9.2.3. 按通用性分层

严格来讲,按通用性分层是另一种Layer,但是,绝对有必要让它”独立门户“以引起实践者的足够重视。按通用性分层式只:将通用性不同的部分划归不同的层,以此作为系统的总体切分方式。一般而言,通用程度越大,所处层次就越靠下。

不同,嵌入式系统的分层架构有所不同:通用性最强的层位于中间,硬件相关的部分,以及应用特点部分分布位于下层和上层。

这种“中间通用、上下专用”的分层方式对可移植性关键的通信系统、控制系统、软件平台等情况都非常重要。

9.2.4. 技术堆叠

技术堆叠不是独立的架构,而是基于分层架构(或其他架构模式)提供的进一步说明。下面这个两个架构模式都是按Tier分层,并明确了各个技术点。

图片来源:Category Archives: Day 15. Understanding J2EE Architecture

另一个例子,基本架构模式是基于通用性分层的,也加入技术堆叠的描述。

9.3. 给架构师的提醒

许多架构师认为,架构就是把系统切成框框,再在框框之间连上线。这种观点太片面了。

高层分割很重要,但不是概念架构的全部。除了切分策略之外,概念架构还包括技术选择、权衡策略等种类的决策。

例如,为了支持各种相互矛盾的非功能需求,仅调整切分方式还远远不够的。

9.4. 贯穿案例

继续PASS系统的贯穿案例。

由于PASS系统的分布式特点明显,所以高层分割除了考虑常见的Layer方式之外,我们也考虑Tier。而通过主动考虑“按通用性分层”,我们也大有收获--确定引入“PASS医生模块通用SDK”而使无谓的重复开发工作量降至最低。

9.4.1. 从初步设计到高层分割的过渡

我们在之前完成了初步设计成果,通过对这些已发现的职责进行“综合”,可以确定系统基本的高层分割方式。

9.4.2. PASS系统Layer设计

于是,可以得到按LayerPASS系统进行高层分割的方式。

9.4.3. PASS系统之Tier设计

Layer切分为反应PASS系统很强的分布式特点,我们应进一步从Tier角度考虑PASS系统的高层分割方式。

9.4.4. 引入通用性分层

如果进一步质疑“可重用性”(详见 10. 贯穿案例部分的目标-场景-决策表 ,应将嵌入HIS的程序进一步切分--分出“PASS系统医生模块通用SDK”,它和任何具体HIS无关,所以通用性高,应分离出去。

下一节:架构不仅仅是系统功能需求的结果 -- Len Bass, 《软件架构实践(第二版)》

在我们当中,有不少人一厢情愿的认为:只要所开发出的系统完成了用户期待的功能,项目就算成功了,但这并不符合实际。 -- 温昱,《软件架构设计》

《软件架构设计》一书中指出,“其实任何作为复合整体的复杂事物都有可能有架构,比如一本书”。“非功能目标的考虑”在ADMEMS方法中不是一个阶段,而是一个贯穿环节。

我们接下来讨论的重点是贯穿案例 -- PASS系统概念架构设计的第3步,考虑非功能需求。