软件体系结构风格

软件体系结构风格概述

多年来,人们在开发某些类型软件过程中积累起来的组织规则和结构,形成了软件体系结构风格。风格是艺术概念,艺术作品在整体上呈现的有代表性的面貌。软件体系结构风格并不是某一种特定系统的结构,而是一个结构的类型。

软件体系结构设计的一个核心问题是,能否使用重复的体系结构模式,即能否达到体系结构级的软件重用。

软件体系结构风格是描述某一特定应用领域中系统组织方式的惯用模式

体系结构风格的最关键的四要素
提供一个词汇表;定义一套配置规则;定义一套语义解释原则定义对基于这种风格的系统所进行的分析


管道-过滤器风格的体系结构

管道-过滤器风格,最早出现在UNIX中,适用于对有序数据进行一系列已经定义的相互计算的应用程序。管道-过滤器模式下,每个功能模块都有一组输入和输出。功能模块从输入集合读入数据流,并在输出集合产生输出数据流,即功能模块对输入数据流进行增量计算得到输出数据流。

管道-过滤器模式下,功能模块称作过滤器(Filter)。

功能模块间的连接可以看作输入、输出数据流之间的通路,所以称作管道(Pipe)。

需求来源:如果要建立一个必须处理或转换输入数据流的系统,单个组件实现会过于臃肿,需求不容易变动。所以,可能要通过替换或重新排列处理步骤为灵活性作规划。

解决方案:管道-过滤器体系结构模式,把系统任务分成几个序贯的处理步骤。这些步骤,通过系统的数据流连接,一个步骤的输出是下一个步骤的输入。实现相连处理步骤间的数据流动。通过管道联合的过滤器序列叫做处理流水线(pipeline)。过滤器是独立运行的部件,不受其它过滤器运行的影响。

管道-过滤器模式的优点

1)由于每个构件的行为不受其他构件的影响,因此,整个系统的行为比较易于理解
2)支持功能模块的复用
3)具有较强的可维护性、可扩展性
4)支持特殊的分析,如吞吐量计算和死锁检测。
5)支持并发执行

管道-过滤器模式的缺点

1)往往会导致系统处理过程的成批操作
2)在处理两个独立但又相关的数据流时,可能会遇到困难。
3)需要对数据传输进行特定的处理时,导致对于每个过滤器的解析输入和格式化输出要做更多的工作,系统复杂性上升。
4)并行处理获得的效率并不好


数据抽象和面向对象风格

抽象数据类型概念对软件系统有着重要作用,目前,软件界已普遍转向使用面向对象系统。这种风格建立在数据抽象和面向对象的基础上,数据的表示方法和相应操作,封装在一个抽象数据类型或对象中。

这种风格的构件是对象,或者说,是抽象数据类型的实例。

数据的表示方法和它们的相应操作被封装在一个抽象数据类型或对象中。这种风格的构件是对象或者说是抽象数据类型的实例。对象通过函数和过程的调用来进行交互。

数据抽象和面向对象风格的优点

1)因为对象对其它对象隐藏表示,所以可以改变一个对象的表示,而不影响其他的对象。
2)设计者可将一些数据存取操作的问题,分解成一些交互的代理程序的集合。

数据抽象和面向对象风格的缺点

1)为了使一个对象和另一个对象通过过程调用等进行交互,必须知道对象的标识,只要一个对象的标识改变了,就必须修改所有其他明确调用它的对象。
2)连锁反应:必须修改所有显式调用它的其他对象,并消除由此带来的一些副作用。例如,如果A使用了对象B,C也使用了对象B,那么C对B的使用所造成的对A的影响,可能是预想不到的。


基于事件的隐式调用风格(事件驱动)

基于事件的隐式调用风格的思想,是构件不直接调用一个过程,而是触发或广播一个或多个事件。从体系结构上说,这种风格的构件是一些模块,这些模块既可以是一些过程,又可以是一些事件的集合。基于事件的隐式调用风格的主要特点,是事件的触发者并不知道哪些构件会被这些事件影响。

实例:数据库管理系统,用户界面。

事件驱动的特点:开发者不需要关心大体流程,而是需要做好每一个事件对应的处理方式即可。

隐式调用系统的优点

1)为软件重用提供了强大的支持。当需要将一个构件加入现存系统时,只需注册到系统的事件中。
2)为改进系统带来了方便。当用一个构件代替另一个构件时,不会影响到其他构件的接口。

隐式调用系统的缺点

1)构件放弃了对系统计算的控制。一个构件触发一个事件时,不能确定其它构件是否会响应它。而且即使知道事件注册了哪些构件的过程,也不能保证这、些过程被调用的顺序。
2)数据交换的问题。有时数据可被一个事件传递,但在另一些情况下,基于事件的系统必须依靠一个共享的仓库进行交互。这些情况下,全局性能和资源管理便成了问题。
3)既然过程的语义必须依赖于被触发事件的上下文约束,关于正确性的推理就存在问题。


分层系统风格

诺贝尔经济学奖获得者西蒙(Herbert Alexander Simon)认为,“要构造一门关于复杂系统的比较正规的理论,有一条路,就是求助于层级理论

分层式体系结构,是按层次组织软件的一种软件体系结构。其中,每一层软件,建立在低一层的软件层上。位于同一层的软件系统或子系统,具有同等的通用性,在下一层的软件比在上
一层的软件通用性更强。一个层次可视为同等通用档次的一组(子)系统。

一个分层风格的系统按照层次结构组织,每一层向它的上层提供服务,同时又是它的下层客户。连接件可以用层次间的交互协议来定义。每个独立层都要防止较高层直接访问较低层

分层风格体系结构的优点

1)由于对层次的邻接层数目进行限制,系统易于改进和扩展
2)每一层的软件都易于重用,并可为某一层次提供多种可互换的具体实现。如果一个独立层体现了一个良好定义的抽象,且有良好定义和文档化的接口,该层就可在多个语境中被重用。
3)分层系统所支持的设计体现了不断增加的抽象层次,这样,一个复杂问题的求解,就被分解为一系列递增的步骤
4)标准化支持:清晰定义和接受共同的抽象层,能促进标准化任务和接口的开发。同一接口的不同实现,可以替换使用。这样,可以使用不同层的不同售主的产品。
5)局部依赖性:层之间的标准化接口,往往会限制被改动层的改动代码的影响。对可测试性的支持也很好,因为可以测试系统中独立于其他组件的特殊层。
6)可替换性:独立层实现,不需要太费劲,就可以被语义上等价的实现所替换。如果层之间的连接在代码中是硬连线的,则可以用新层的实现的名称来更新。

分层风格体系结构的缺点

1)应当如何界定层次间的划分是一个较为复杂的问题。
2)更改行为的重叠。层的行为改变时,会出现一个严重问题。高层往往不受低层改动的影响
3)降低效率。一个分层体系结构的效率,往往要低于整体结构或一个“对象的海洋”。
4)不必要的工作。如果低层执行的某些服务执行了多余或重复的工作,而这些工作并非高层真正
需要的,那么,这对性能的影响是负面的。
5)难以认可层的正确粒度。层数太少的分层体系结构,不能完全发挥这种模式在可重用性、可更改性和可移植性上的潜力。相反,层过多,会引入不必要的复杂性和层间分离的冗余以及变元和返回值传输的开销。


仓库风格和黑板风格(数据共享风格)

仓库风格的体系结构由两个构件组成。一个中央数据结构,表示当前状态,一个独立构件的集合,对中央数据结构进行操作。对于系统中数据和状态的控制方法有两种。一个传统的方法是,由输入事务选择进行何种处理,并把执行结果作为当前状态存储到中央数据结构中,这时,仓库是一个传统的数据库体系结构。另一种方法是,由中央数据结构的当前状态,决定进行何种处理。这时,仓库是一个黑板体系结构。即黑板体系结构是仓库体系结构的特殊化。

在问题求解过程中,黑板上保存了所有的部分解,代表了问题求解的不同阶段。“黑板”模式类似于这样一个情形,即让专家们坐在真实黑板前并一起工作,来解决一个问题。

需求分析:黑板系统传统是应用在需要对数据做出复杂解释的信号处理中,这类系统包括语音和模式识别领域。例如:图、表、视觉、图像识别、语言识别、预警等应用领域,都属于这类问题。问题特点是,当把整个问题分解成子问题时,各个子问题涵盖了不同的领域知识、解决方法。

黑板风格体系结构的优点

1)便于多客户共享大量数据,不用关心数据是何时出现的、谁提供的、怎样提供的。
2)既便于添加新的作为知识源代理的应用程序,也便于扩展共享的黑板数据结构。
3)可重用的知识源。
4)支持容错性和健壮性

黑板风格体系结构的缺点

1)不同的知识源代理:对于共享数据结构要达成一致,也造成对黑板数据结构的修改较为困难。
2)需要一定的同步锁机制:保证数据结构的完整性和一致性,增大了系统复杂度。
3)测试困难
4)低效。黑板系统在拒绝错误假设中要承受多余的计算开销。
5)开发成本高。绝大多数黑板系统要花几年时间来进化。我们把这归因于病态结构问题。


模型-视图-控制器风格

模型-视图-控制器(Model-View-Controller,MVC)由挪威奥斯陆大学教授Trygve Reenskaug提出,首先被应用在SmallTalk-80环境中,是许多交互和界面系统的构成基础。MVC结构是为那些需要为同样的数据提供多个视图的应用程序而设计的,很好地实现了数据层与表示层的分离。

模型类Model

  • 模型包含了应用问题的核心数据、逻辑关系、计算功能,封装了所需的数据,提供了完成问题处理的操作过程。控制器依据I/O的需要调用这些操作过程。
  • 模型还为视图获取显示数据而提供了访问其数据的操作。这种变化-传播机制,体现在各个相互依赖部件之间的注册关系上。
  • 模型数据和状态的变化,会激发这种变化-传播机制,是模型、视图和控制器之间联系的纽带。

视图类Viewer

  • 视图通过显示的形式把信息转达绐用户。
  • 不同视图通过不同的显示来表达模型的数据和状态信息。
  • 每个视图有一个更新操作,可被变化-传播机制所激活。当调用更新操作时,视图获得来自模型的数据值,来更新显示。
  • 在初始化时,通过与变化-传播机制的注册关系建立起所有视图与模型间的关联。视图与控制器之间,保持着一对一的关系,每个视图创建一个相应的控制器。
  • 视图提供给控制器处理显示的操作。因此,控制器可以获得主动激发界面更新的能力。

控制类Controller

  • 控制器通过时间触发的方式,接收用户的输入。控制器如何获得事件,依赖于界面的运行平台。
  • 控制器通过事件处理过程对输入事件进行处理,并为每个输入事件提供相应的操作服务,把事件转化成对模型或相关视图的激发操作。
  • 如果控制器的行为,依赖于模型的状态,则控制器应该在变化-传播机制中进行注册,并提供一个更新操作,可以由模型的变化来改变控制器的行为,如禁止某些操作。

发表回复

Breeze Wang

A student majoring in Software Engineering at Central South University has an understanding of software development techniques, software architecture, and is able to use Godot to develop game projects. I am currently in the Game Development Laboratory at Central South University. I have experience participating in Global Game Jam. Loving game development.