文章目录
- 软件体系结构风格介绍
-
- (一)管道和过滤器风格
- (二)数据抽象与面向对象风格
- (三)基于事件的隐式调用风格
- (四)层次系统风格
- (五)仓库风格
- (六)C2风格
- (七)基于层次消息总线的架构风格
软件体系结构风格介绍
软件结构风格的定义:软件结构风格是描述某一特定应用领域中系统组织方式的惯用模式(idiomatic paradigm)。体系结构风格定义了一个系统家族,即一个体系结构定义一个词汇表和一组约束。词汇表中包含一些构件和连接件组合起来的。体系结构风格反映了领域中众多系统所共有的结构和语义特性,并指导如何将各个模块和子系统有效地组织成一租个完整的系统。按这种方式理解,软件体系结构风格定义了用于描述系统的术语表和一组指导构件系统的规则。
构件的定义:构件是具有某种功能的可重用的软件模板单元,表示了系统中主要的计算元素和数据存储。构件有两种:复合构件和原子构件,复合构件由其他复合构件和原子构件通过连接而成;原子构件是不可再分的构件,底层由实现该构件的类组成,这种构件的划分提供了体系结构的分层表示能力,有助于简化体系结构的设计。
接件的定义:连接件表示了构件之间的交互,简单的连接件如管道(pipe)、过程调用(proceduce call)、事件广播(event broadcast)等,更为复杂的交互如客户-服务器(client-server)通信协议,数据库和应用之间的SQL连接等。
软件体系结构风格的四要素:
(1)提供一个词汇表;
(2)定义一套配置规则;
(3)定义一套语义解释规则;
(4)定义对基于这种风格的系统所进行的分析。
软件体系结构风格的目的:软件体系结构风格为大粒度的软件重用提供了可能。
软件体系结构设计的一个中心问题是能否重用软件体系结构模式,或者采用某种软件体系结构风格。有原则地使用软件体系结构风格具有如下意义:
- 它促进了设计的复用,使得一些经过实践证实的解决方案能够可靠地解决新问题。
- 它能够带来显著的代码复用,使得体系结构风格中的不变部分可共享同一个解决方案。
- 便于设计者之间的交流与理解。
- 通过对标准风格的使用支持了互操作性,以便于相关工具的集成。
- 在限定了设计空间的情况下,能够对相关风格作出分析。
- 能够对特定的风格提供可视化支持。
与此同时,人们目前尚不能准确回答的问题是:
- 系统设计的哪个要点可以用风格来描述;
- 能否用系统的特性来比较不同的风格,如何确定用不同的风格设计系统之间的互操作;
- 能否开发出通用的工具来扩展风格;
- 如何为一个给定的问题选择恰当的体系结构风格,或者如何通过组合现有的若干风格来产生一个新的风格。
M.Shaw等人根据此框架给出了管道与过滤器、数据抽象和面向对象组织、基于事件的隐式调用、分层系统、仓库系统及知识库和表格驱动的解释器等一些常见的软件体系结构风格。
(一)管道和过滤器风格
在管道/过滤器风格的软件体系结构中,每个构件都有一组输入和输出,构件读输入的数据流,经过内部处理,然后产生输出数据流。这个过程通常通过对输入流的变换及增量计算来完成,所以在输入被完全消费之前,输出便产生了。因此,这里的构件被称为过滤器,这种风格的连接件就像是数据流传输的管道,将一个过滤器的输出传到另一过滤器的输入。此风格特别重要的 过滤器必须是独立的实体,它不能与其它的过滤器共享数据,而且一个过滤器不知道它上游和下游的标识。一个管道/过滤器 络输出的正确性并不依赖于过滤器进 行增量计算过程的顺序。
图2-1是管道/过滤器风格的示意图。一个典型的管道/过滤器体系结构的例子是以Unix shell编写的程序。Unix既提供一种符 ,以连接各组成部分(Unix的进程),又提供某种进程运行时机制以实现管道。另一个著名的例子是传统的编译器。传统的编译器一直被认为是一种管道系统,在该系统中,一个阶段(包括词法分析、语法分析、语义分析和代码生成)的输出是另一个阶段的输入。
面向对象的系统有许多的优点,并早已为人所知:
(1) 因为对象对其它对象隐藏它的表示,所以可以改变一个对象的表示,而不影响其它的对象。
(2) 设计者可将一些数据存取操作的问题分解成一些交互的代理程序的集合。
但是,面向对象的系统也存在着某些问题:
(1) 为了使一个对象和另一个对象通过过程调用等进行交互,必须知道对象的标识。只要一个对象的标识改变了,就必须修改所有其他明确调用它的对象。
(2) 必须修改所有显式调用它的其它对象,并消除由此带来的一些副作用。例如,如果A使用了对象B,C也使用了对象B,那么,C对B的使用所造成的对A的影响可能是料想不到的。
(三)基于事件的隐式调用风格
基于事件的隐式调用风格的思想是构件不直接调用一个过程,而是触发或广播一个或多个事件。系统中的其它构件中的过程在一个或多个事件中注册,当一个事件被触发,系统自动调用在这个事件中注册的所有过程,这样,一个事件的触发就导致了另一模块中的过程的调用。
从体系结构上说,这种风格的构件是一些模块,这些模块既可以是一些过程,又可以是一些事件的集合。过程可以用通用的方式调用,也可以在系统事件中注册一些过程,当发生这些事件时,过程被调用。
隐式调用系统的主要优点有:
(1) 为软件重用提供了强大的支持。当需要将一个构件加入现存系统中时,只需将它注册到系统的事件中。
(2) 为改进系统带来了方便。当用一个构件代替另一个构件时,不会影响到其它构件的接口。
隐式调用系统的主要缺点有:
(1) 构件放弃了对系统计算的控制。一个构件触发一个事件时,不能确定其它构件是否会响应它。而且即使它知道事件注册了哪些构件的构成,它也不能保证这些过程被调用的顺序。
(2) 数据交换的问题。有时数据可被一个事件传递,但另一些情况下,基于事件的系统必须依靠一个共享的仓库进行交互。在这些情况下,全局性能和资源管理便成了问题。
(3) 既然过程的语义必须依赖于被触发事件的上下文约束,关于正确性的推理存在问题。
Java的Swing、安卓以及JavaScript 事件的注册与监听都体现了此风格。基于事件的隐式调用风格特点很明显:事件的触发者并不知道哪些构件会被这些事件影响:不能假定构件的处理顺序,甚至不知道哪些过程会被调用;为此,许多隐式调用的系统也包含显式调用作为构件交互的补充形式。
支持隐式调用的系统可以举出这些
- 在编程环境中用于集成各种工具。(集成开发环境)
- 在数据库管理系统中确保数据的一致性约束。
- 在用户界面系统中管理数据。
(四)层次系统风格
层次系统组织成一个层次结构,每一层为上层服务,并作为下层客户。在一些层次系统中,除了一些精心挑选的输出函数外,内部的层只对相邻的层可见。这样的系统中构件在一些层实现了虚拟机(在另一些层次系统中层是部分不透明的)。连接件通过决定层间如何交互的协议来定义,拓扑约束包括对相邻层间交互的约束。
这种风格支持基于可增加抽象层的设计。这样,允许将一个复杂问题分解成一个增量步骤序列的实现。由于每一层最多只影响两层,同时只要给相邻层提供相同的接口,允许每层用不同的方法实现,同样为软件重用提供了强大的支持。
图2-3是层次系统风格的示意图。层次系统最广泛的应用是分层通信协议。在这一应用领域中,每一层提供一个抽象的功能,作为上层通信的基础。较低的层次定义低层的交互,最低层通常只定义硬件物理连接。
(五)仓库风格
在仓库风格中,有两种不同的构件:中央数据结构说明当前状态,独立构件在中央数据存贮上执行,仓库与外构件间的相互作用在系统中会有大的变化。
控制原则的选取产生两个主要的子类。若输入流中某类时间触发进程执行的选择,则仓库是一传统型数据库;另一方面,若中央数据结构的当前状态触发进程执行的选择,则仓库是一黑板系统。
图2-4 是黑板系统的组成。黑板系统的传统应用是信 处理领域,如语音和模式识别。另一应用是松耦合代理数据共享存取。
C2风格是最常用的一种软件体系结构风格。从C2风格的组织规则和结构图中,我们可以得出,C2风格具有以下特点:
(1) 系统中的构件可实现应用需求,并能将任意复杂度的功能封装在一起;
(2) 所有构件之间的通讯是通过以连接件为中介的异步消息交换机制来实现的;
(3) 构件相对独立,构件之间依赖性较少。系统中不存在某些构件将在同一地址空间内执行,或某些构件共享特定控制线程之类的相关性假设。
二层C/S我们不再介绍了,直接说三层C/S
三层C/S的基本硬件结构
传统的二层C/S结构存在以下几个局限:
- 它是单一服务器且以局域 为中心的,所以难以扩展至大型企业广域 或Internet;
- 受限于供应商;
- 软、硬件的组合及集成能力有限;
- 难以管理大量的客户机。
因此,三层C/S结构应运而生。三层C/S结构是将应用功能分成表示层、功能层和数据层三部分。其解决方案是:对这三层进行明确分割,并在逻辑上使其独立。原来的数据层作为DBMS已经独立出来,所以关键是要将表示层和功能层分离成各自独立的程序,并且还要使这两层间的接口简洁明了。
将上述三层功能装载到硬件的方法基本上有三种(如图所示)。其中表示层配置在客户机中,而数据层配置在服务器中。
一般情况是只将表示层配置在客户机中,与二层C/S结构相比,其程序的可维护性要好得多,是其他问题并未得到解决。客户机的负荷太重,其业务处理所需的数据要从服务器传给客户机,所以系统的性能容易变坏。
如果将功能层和数据层分别放在不同的服务器中,则服务器和服务器之间也要进行数据传送。但是,由于在这种形态中三层是分别放在各自不同的硬件系统上的,所以灵活性很高,能够适应客户机数目的增加和处理负荷的变动。例如,在追加新业务处理时,可以相应增加装载功能层的服务器。因此,系统规模越大这种形态的优点就越显著。
值得注意的是:三层C/S结构各层间的通信效率若不高,即使分配给各层的硬件能力很强,其作为整体来说也达不到所要求的性能。此外,设计时必须慎重考虑三层间的通信方法、通信频度及数据量。这和提高各层的独立性一样是三层C/S结构的关键问题。
JB/HMB风格基于层次消息总线、支持构件的分布和并发,构件之间通过消息总线进行通讯,如图所示。消息总线是系统的连接件,负责消息的分派、传递和过滤以及处理结果的返回。各个构件挂接在消息总线上,向总线登记感兴趣的消息类型。构件根据需要发出消息,由消息总线负责把该消息分派到系统中所有对此消息感兴趣的构件,消息是构件之间通讯的唯一方式,构件接收到消息后,根据自身状态对消息进行响应,并通过总线返回处理结果。由于构件通过总线进行连接,并不要求各个构件具有相同的地址空间或局限在一台机器上。该风格可以较好地刻画分布式并发系统,以及基于CORBA,DCOM和EJB规范的系统。
如图所示,系统中的复杂构件可以分解为比较低层的子构件,这些子构件通过局部消息
总线进行连接,这种复杂的构件称为复合构件。如果子构件仍然比较复杂,可以进一步分解。
如此分解下去,整个系统形成了树状的拓扑结构,树结构的末端结点称为叶结点,它们是系统中的原子构件,不再包含子构件,原子构件的内部可以采用不同于JB/HMB的风格,例如数据流风格、面向对象风格及管道/过滤器风格等,这些属于构件的内部实现细节。但要集成到JB/HMB风格的系统中,必须满足JB/HMB风格的构件模型的要求,主要是在接口规约方面的要求。另外,整个系统也可以作为一个构件,通过更高层的消息总线,集成更大的系统中。于是,可以采用统一的方式刻画整个系统和组成系统的单个构件。
构建模型
系统和组成系统的成分通常是比较复杂的,难以从一个视角获得对它们的完整理解,因
此一个好的软件工程方法往往从多个视角对系统进行建模,一般包括系统的静态结构、动态行为和功能等方面。例如,在Rumbaugh等人提出的OMT(object modeling technology)方法中,
采用了对象模型、动态模型和功能模型刻画系统的以上3个方面。
借鉴上述思想,为满足体系结构设计的需要,JB/HMB风格的构件模型包括了接口、静态结构和动态行为3个部分,如图所示。
在许多重要的应用领域中,例如金融、电力、电信及空中交通管制等,系统的持续可用性是一个关键性的要求,运行时刻的系统演化可减少因关机和重新启动而带来的损失和风险。此外,越来越多的其他类型的应用软件也提出了运行时刻演化的要求,在不必对应用软件进行重新编译和加载的前提下,为最终用户提供系统定制和扩展的能力。JBI/HMB风格方便地支持运行时刻的系统演化,主要体现在以下3个方面:
(1) 动态增加或删除构件。在JB/HMB风格的系统中,构件接口中定义的输人和输出消息刻画了一个构件承担的系统责任和对外部环境的要求,构件之间通过消息总线进行通讯,彼此并不知道对方的存在。因此只要保持接口不变,构件就可以方便地替换。一个构件加人到系统中的方法很简单,只需向系统登记其所感兴趣的消息即可。但删除一个构件可能会引起系统中对于某些消息没有构件响应的异常情况,这时可以采取两种措施:一是阻塞那些没有构件响应的消息,二是首先使系统中的其他构件或增加新的构件对该消息进行响应,然后再删除相应的构件。系统中可能增删改构件的情况包括:当系统功能需要扩充时,往系统中增加新的构件。当对系统功能进行裁剪,或当系统中的某个构件出现问题时,需要删除系统中的某个构件。用带有增强功能或修正了错误的构件新版本代替原有的旧版本。
(2) 动态改变构件响应的消息类型。类似地,构件可以动态地改变对外提供的服务(即接收的消息类型),这时应通过消息总线对发生的改变进行重新登记。
(3) 消息过滤。利用消息过滤机制,可以解决某些构件集成的不匹配问题,详见“消息过滤”一节。消息过滤通过阻塞构件对某些消息的响应,提供了另一种动态改变构件对消息进行响应的方式。
JB/HMB风格的优点
以上讨论了JB/HMB风格的各组成要素,下面对JB/HMB风格的主要特点作总结。
(1) 从接口、结构和行为方面对构件进行刻画。在JB/HMB风格中,构件的描述包括接口、静态结构和动态行为3个方面。接口:构件可以提供一个或多个接口,每个接口定义了一组发送和接收的消息集合,刻画了构件对外提供的服务以及要求的环境服务,接口之间可以通过继承表达相似性。
静态结构:复合构件是由子构件通过局部消息总线连接而成的,形成该复合构件的内部结构。
动态行为:构件行为通过带输出的有限状态机刻画,构件接收到外来消息后,不但根
据消息类型,而且根据构件当前所处的状态对消息进行响应,并导致状态的变迁。
基于层次消息总线:消息总线是系统的连接件,负责消息的传递、过滤和分派,以及
处理结果的返回。各个构件挂接在总线上,向系统登记感兴趣的消息。构件根据需要发出消息,由消息总线负责把该消息分派到系统中对此消息感兴趣的所有构件。构件接收到消息后,根据自身状态对消息进行响应,并通过总线返回处理结果。由于构件通过总线进行连接,并不要求各个构件具有相同的地址空间或局限在一台机器上,系统具有并发和分布的特点。系统和复合构件可以逐层分解,子构件通过(局部)消息总线相连。每条消息总线分别属于系统和各层次的复合构件,我们把这种特征的总线称为层次消息总线。在系统开发方面,由于各层次的总线局部在相应的复合构件中,因此可以更好地支持系统的构造性和演化性。
统一描述系统和组成系统的构件:组成系统的构件通过消息总线进行连接,复杂构
件又可以分解为比较简单的子构件,通过局部消息总线进行连接,如果子构件仍然比较复杂,
可以进一步分解。系统呈现出树状的拓扑结构。另外,整个系统也可以作为一个构件,集成到更大的系统中。于是,就可以对整个系统和组成系统的各层构件采用统一的方式进行描述。
支持运行时刻的系统演化:系统的持续可用性是许多重要的应用系统的一个关键性
要求,运行时刻的系统演化可减少因关机和重新启动而带来的损失和风险。JB/HMB风格方便地支持运行时刻的系统演化,主要包括动态增加或删除构件、动态改变构件响应的消息类型和消息过滤。
摘自《软件体系结构原理、方法与实践(第2版)张友生》
声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!