架构设计以业务理解、需求分析的成功为输入,对系统架构进行设想和描述,最终输出架构设计文档。虽然在网上查找架构设计文档时,常常会看到推荐使用 4+1 架构视图 来描述系统架构并生成相应的文档。然而,4+1 架构视图模型诞生于1995年,当时大多数系统还是单体架构。随着软件技术的不断发展,4+1 模型已显得陈旧,难以适应现代复杂的分布式系统需求。
什么是4+1架构模型
如上图所示,即为经典的4+1架构模型,下面对几个视图进行解释:
逻辑视图(Logical View):描述系统的功能、组件和它们之间的关系。该视图主要关注系统的静态结构,包括类、接口、包、模块等,用于表示系统的组织结构、模块划分和关系。
进程视图(Process View):描述系统的并发性和分布性。该视图主要关注系统在运行时的行为,包括系统运行时的进程、线程、节点和通信方式等,用于表示系统的并发性、分布性、通信和同步方式。
物理视图(Physical View ):描述系统的部署和配置。该视图主要关注系统在物理计算资源上的部署,包括硬件、网络、服务器和存储等,用于表示系统的部署拓扑、配置和资源分配。
开发视图(Development View):描述系统的软件开发过程。该视图主要关注软件的开发、构建和部署过程,包括开发环境、版本控制、构建工具和编译器等,用于表示系统的开发工程、构建过程和开发环境。
场景视图(Scene View): 描述系统在不同情景下的使用场景。该视图主要关注系统的用例、用户交互和系统行为,包括用户界面、用例场景和用户需求等,并用于表示系统的功能需求、用户交互和系统行为。
这里让我们尝试用领域模型来理解一下4+1视图模型。当系统是一个小型的且由一个单体应用构成时,该应用就是系统的全部,应用的架构即系统架构。此时系统需求对应场景视图,应用的代码工程对应开发视图,设计的类对应逻辑视图,部署的机器对应物理视图,运行的进程对应进程视图。
可以看到4+1架构视图模型是围绕单体应用、代码工程、类、机器和进程这几种元素展开的。那么它究竟存在哪些问题呢?
1、时代局限性
前面说过,4+1模型是1995年提出的,那时候Java语言刚刚诞生,软件系统基本都是采用单一技术的单体应用,且运行在少量几台机器上,与现在的大型信息系统在技术复杂度、业务复杂度、开发规模、用户规模、部署规模上都无法比较。在这种技术背景下,整个方法论考虑的面比较狭窄,仅使用于单机应用或简单的C/S结构和B/S结构的应用系统。
2、描述充分性
对于大型项目来说,描述系统架构仅用几个视图是远远不够的。图虽然易于理解,但表达的信息量有限。为了描述完整的架构设计,还需要使用大量的文字来说明设计思路,以及使用大量的表格进行信息整理、比较分析。最终所有的图、表格、文字组织在一起,才能行成完整的架构设计文档。
3、逻辑视图问题
逻辑视图是在软件层面对系统进行初步分解,由于提出4+1视图模型时软件大部分都是单体应用,采用单一技术,在技术上没有多少可以考虑的,因此如果对系统进行分解,不可避免地要考虑整个单体应用的程序结构,结果就到了类、包、模块的粒度。现在的大中小项目甚至小型项目一般都不再是单体应用,而是由很多组件构成的分布式应用,因此需要在组件维度对系统进行分解,在组件层面考虑可复用性,技术选型,而对每个组件内部的代码结构暂不考虑。所以,在软件系统复杂化以后,对系统分解的主视角发生了变化,从代码结构变成了组件划分,所以4+1模型中逻辑架构视图其实已经不再适用。
4、开发视图问题
经过组件划分后,所有组件可以划分为复用组件和开发组件。对于每个要开发的组件,确实有必要确定工程结构,但是对于一个有一定积累的软件组织来说,代码工程的框架是可以直接复用的,并不是每个项目都要考虑。开发语言、开发工具、框架、过程支撑工具也都是固定的,不需要每个项目都考虑,因此开发视图中涉及的内容其实没有多少需要考虑。在架构设计的第一视角变成组件后,更重要的其实是定义组件和代码工程的对应关系,至于每个代码工程的内部结构,可以延后考虑,不在系统架构设计的考虑范围内。
5、进程视图问题
在系统福再度提升、第一视角变成组件后,进程逐渐被弱化,如果要考虑进程也是对每个组件分别考虑,至于每个组件由几个进程组成,线程模型如何设计,可能到开发阶段才需要考虑。首先要考虑的其实是各个组件之间如何通信,这种通行不是进程间通信,而是网络通信,涉及通信协议,传输格式和通信框架的选择。
6、物理视图问题
这里把部署视图当成物理视图,但“物理”一次的含义并不明确,如果是指硬件,就没有软件什么事,只展示服务器即可;如果是指软件到硬件的映射,就是部署,此时不应该用“物理”一次。之所以出现“物理”一词,很可能是为了与“逻辑”对应。
7、场景视图问题
场景视图是用例,属于功能性需求,是在做架构设计之前就应该确定的。在架构设计阶段,需求是输入,架构师需要对需求进行确认,而不是在这个阶段考虑需求。
大型系统的架构设计
当系统为大中型时,其领域模型往往如上图所示,此时可复用性被提升到一个较高的高度,系统将由许多组件构成,其中一部分是复用的,一部分要开发的,系统架构要考虑的首先是这些组件的划分和技术选型,而不是某个组件的内部结构。
在大中型系统中,第一层级要考虑的内容变成组件的构成,另外,需求作为输入,不纳入架构设计范围内。涉及的类由于层级降低且与业务功能关联密切,因此也不在架构设计范围之内。
所以这里要强调的是,在大中型系统中我们应该要采用上图所示的思路,以组件为驱动,首先对系统划分组件并定义其关系,然后基于组件划分的结构来定义技术要素。整个设计分为逻辑架构设计和物理架构设计两个阶段。这里的逻辑和物理分别指抽象和具体,类似于面向对象编程中先定义一个抽象类,再编写一个具体的实现类。其实很多设计都分为逻辑设计和物理设计两个阶段,如系统工程、数据库工程等。分为这两个阶段有一大好处,就是先通过抽象的逻辑设计可以尽快确定相对稳定的总体结构,再在这个基础上做进一步的设计就会比较清晰,在物理架构设计中针对逻辑架构的元素逐一具体化就可以得到最终设计。
DailyMart是一个基于 DDD 和Spring Cloud Alibaba的微服务商城系统,采用SpringBoot3.x以及JDK17。旨在为开发者提供集成式的学习体验,并将其无缝地应用于实际项目中。该专栏包含领域驱动设计(DDD)、Spring Cloud Alibaba企业级开发实践、设计模式实际应用场景解析、分库分表战术及实用技巧等内容。如果你对这个系列感兴趣,可在本公众号回复关键词 DDD 获取完整文档以及相关源码。