软件架构产生的背景
1972年图灵奖获得者、荷兰计算机科学家Edsger Wybe Dijkstra早在20世纪60年代就开始涉及软件架构概念了。
20世纪60年代第一次软件危机引出了结构化编程,创造了模块的概念。
20世纪80年代第二次软件危机引出了面向对象编程,创造了对象的概念。
到了20世纪90年代软件架构开始流行,创造了组件的概念。
由此可见,模块、对象、组件本质上都是对达到一定规模的软件进行拆分,区别仅仅是随着软件复杂度不断增加,拆分的粒度越来越粗,拆分的层次越来越高。
架构定义
目前软件架构没有统一的定义,下面列举几个比较具有代表性的架构定义:
- 卡内基梅隆大学SEI--计算系统的软件架构是解释该系统所需的结构体的集合,其中包括软件元素、元素之间的相互关系,以及二者各自的属性。
- ISO42010.2011--架构是一个系统的基本组织,体现为其组成部件、部件之间、环境之间的关系,以及支配其设计和演进的原则。
- 《系统架构》--架构是对系统中实体与实体之间关系所进行的抽象描述,在人类构建的系统中,它可以表述为一系列的决策。
架构设计
架构设计是一门分与合的艺术。
关注点分离(Separation of concerns, SoC)原则主要目的就是为了解决复杂系统如何“分”的问题。将复杂系统根据不同的角度(也即关注点)分解为多个相对独立的部分,再对每个独立部分单独处理,这就是关注点分离。
从不同维度,可以有不同的分离方案。温昱老师的《软件架构设计》一书中的【 2.1.1 关注点分离之道 】章节分别从功能职责、通用专用性、大小粒度等不同维度进行分离。
架构的“合”,下面从功能职责划分视角说明,从高层到低层依次为展现层、业务层、数据层。
架构设计需要明确依赖关系规则。一是源码的依赖关系必须只能由高层指向低层,即展现层依赖于业务层或数据层。二是上层模块发生的任何变更,都不应影响到下层模块的实现,如展现层变更,不应影响到业务层或数据层。
对于大型长生命周期的项目,为了保持核心业务层架构的稳定性,避免数据层的变化对业务层影响,业务层不能直接调用数据层的接口读写数据。通常采用依赖倒置原则(DIP)解决源码中控制流与依赖方向的相反性问题,即由高层定义接口,由低层实现接口。此处,由业务层定义接口,由数据层实现接口。
架构设计-RUP 4+1视图方法
1995年,Philippe Kruchten在《IEEE Software》上发表了题为《The 4+1 View Model of Architecture》的论文,引起了业界的极大关注。后来,他加入Rational,演变出著名的“RUP 4+1视图方法”。
- 逻辑视图(Logical View),设计的对象模型。
逻辑视图关注功能,不仅包括用户可见的功能,还包括为实现用户功能而必须提供的 “辅助功能模块”。它们可能是逻辑层、功能模块、类等。
- 进程视图(Process View),捕捉设计的并发和同步特征。
进程视图关注进程、线程、对象等运行时概念,以及相关的并发、同步、通信等问题。进程视图和实现视图的关系:进程视图一般偏重程序包在编译时期的静态依赖关系,而这些程序运行起来之后会表现为对象、线程、进程,进程视图比较关注的是这些运行时单元的交互问题。
- 部署视图(Deployment View),描述了软件到硬件的映射,反映了分布式特性。
部署视图关注 “目标程序及其依赖的运行库和系统软件” 最终如何安装或部署到物理机器,以及如何部署机器和网络来配合软件系统的可靠性、可伸缩性等要求。部署视图和进程视图的关系:进程视图特别关注目标程序的动态执行情况,而部署视图重视目标程序的静态位置问题;部署视图还要考虑软件系统和包括硬件在内的整个 IT 系统之间是如何相互影响的。
- 实现视图(Implementation View),描述了在开发环境中软件的静态组织结构。
实现视图关注程序包,不仅包括要编写的源程序,还包括可以直接使用的第三方 SDK 和现成框架、类库,以及开发的系统将运行于其上的系统软件或中间件。实现视图和逻辑视图之间可能存在一定的映射关系:比如逻辑视图中的逻辑层一般会映射到实现视图中的多个程序包;再比如实现视图中的源码文件可以包含逻辑视图中的一到多个类。
- 用例视图(Use-Case View),该视图对应于“+1”,代表用户需求。它关联了其他所有视图,实际上也代表了所有设计都必须围绕用户需求展开。