复杂性是层次化的。 -- 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 Interface
、Services
、Domain Model
和Persistent 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
架构“的一大好处是可伸缩性--业务量小的时候将N
个Tier
都部署在同一台机器上 ,等业务量大的时候再为每个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设计
于是,可以得到按Layer
对PASS
系统进行高层分割的方式。
9.4.3. PASS系统之Tier设计
按Layer
切分为反应PASS
系统很强的分布式特点,我们应进一步从Tier
角度考虑PASS
系统的高层分割方式。
9.4.4. 引入通用性分层
如果进一步质疑“可重用性”(详见 10. 贯穿案例部分的目标-场景-决策表 ,应将嵌入HIS的程序进一步切分--分出“PASS系统医生模块通用SDK”,它和任何具体HIS无关,所以通用性高,应分离出去。
下一节:架构不仅仅是系统功能需求的结果 -- Len Bass, 《软件架构实践(第二版)》
在我们当中,有不少人一厢情愿的认为:只要所开发出的系统完成了用户期待的功能,项目就算成功了,但这并不符合实际。 -- 温昱,《软件架构设计》
《软件架构设计》一书中指出,“其实任何作为复合整体的复杂事物都有可能有架构,比如一本书”。“非功能目标的考虑”在ADMEMS方法中不是一个阶段,而是一个贯穿环节。
我们接下来讨论的重点是贯穿案例 -- PASS系统概念架构设计的第3步,考虑非功能需求。