软件架构风格
第一章 软件架构风格
文章目录
前言
软件体系结构(架构)设计的一个核心目标是重复的体系结构模式,即达到体系结构级的软件重用/复用。也就是说,在不同的软件体系中,使用同一个结构体系。基于这个目标,主要任务是研究和实践软件体系结构风格和类型问题。
一、软件架构风格概述
软件架构风格是描述某一特定应用领域中系统的组织方式和惯用模式。体系结构风格定义了一个系统家族,即一个体系结构定义一个词汇表和一组约束。
(1)词汇表:构件和连接件。
(2)约束:如何将构件和连接件组合起来,约束定义构件和连接件的组合方式。
体系结构风格反映了领域中众多系统所共有的结构和语义特性,并指导如何将各个模块和子系统有效地组织成一个完整的系统。
二、软件架构风格分类
1.数据流体系结构风格
数据流体系结构是一种计算机体系机构,直接与传统的冯·诺依曼体系结构或控制流体系结构进行了对比。数据流体系结构没有概念上的程序计数器:指令的可执行性和执行仅基于指令输入参数的可用性来确定,因此,指令的顺序是不可预测的,即行为是不确定的。
是一种编程和计算模式,用于描述和实现数据在系统中的流动和转换。
它强调数据的流动,以及数据流之间的转换和处理
(1)批处理风格
每个处理步骤是一个单独的程序,每一步必须在前一步结束后才能开始,并且数据必须是完整的,以整体方式传递。
构件:独立的应用程序。
连接件:某种类型的媒介。
(2)管道-过滤器风格
把系统划分为几个序贯的处理步骤(过滤器),这些步骤之间通过数据流连接,一个步骤的输出是另一个步骤的输入,每个步骤都有输入和输出。
每个构件都有一组输入和输出,构件读取数据流,经过内部处理,产生输出数据流。前一个构件的输出作为后一个构件的输入,前后数据流关联。
构件:过滤器。
连接件:数据流传输管道。
风格比较
风格 | 批处理 | 管道-过滤器 |
---|---|---|
特点 | 1. 处理数据的单位是批次,即一组数据一次性处理。 2. 通常在整个数据集上执行操作,然后输出结果。 3. 适用于离线数据分析和大规模数据处理。 4. 常用的工具包括Hadoop MapReduce、Spark的批处理模式等。 | 1. 数据以流的形式通过一系列处理器(过滤器)逐步处理。 2. 可以实现实时数据处理和流式计算。 3. 适用于交互式应用、数据流分析、实时监控等。 4. 常用的工具包括Apache Kafka、Apache Flink等。 |
优点 | 1. 高吞吐量,适合大规模数据处理。 2. 可以进行全局优化,充分利用资源。 3. 易于编程,适用于复杂计算。 | 1. 低延迟,适合实时应用。 2. 可以按需处理数据,节省资源。 3. 支持无限数据流,适用于流式数据。 |
缺点 | 1. 响应时间较慢,不适合实时处理需求。 2. 不适合交互式应用。 3. 需要处理大量数据时,需要大内存和计算资源。 | 1. 处理复杂逻辑可能需要额外的编程复杂性。 2. 不适用于离线数据分析和大规模批处理。 3. 难以进行全局优化。 |
数据处理单位 | 批次 | 流式数据 |
处理速度 | 较慢,适用于离线处理 | 快速,适用于实时处理 |
编程复杂性 | 相对较低 | 可能较高,取决于逻辑 |
资源需求 | 高内存和计算资源 | 低延迟,按需分配资源 |
优化能力 | 全局优化可能 | 局部优化 |
适用场景 | 大规模数据分析 1.批量数据处理:批处理风格广泛应用于大规模数据处理和转换任务。例如,一个电子商务网站可能每晚批量处理数百万笔交易数据,以生成销售报告、更新库存和客户账户。这些数据流通过一系列批处理作业,每个作业负责执行不同的任务。 2.批量图像处理:图像处理应用程序通常使用批处理风格,以一次性处理大量图像文件。例如,一家摄影工作室可能需要批量调整照片的大小、应用滤镜和重命名文件,以准备批量发布。 | 实时处理、监控 1.文本处理工具:文本处理工具如Unix中的命令行工具(例如grep、sed、awk)采用管道-过滤器风格。用户可以使用管道将多个命令连接在一起,每个命令充当一个过滤器,处理输入文本并将结果传递给下一个命令。这种风格使用户能够构建强大的文本处理工作流程。 2.编译器和解释器:编译器和解释器也使用管道-过滤器风格。编译器通常将源代码文件作为输入,并经历多个阶段(如词法分析、语法分析、代码生成)以生成目标代码。每个阶段都可以被看作是一个过滤器,将输入转换为下一个阶段的输出。 |
2.调用/返回体系结构风格
调用/返回风格是指在系统中采用了调用与返回机制。利用调用-返回实际上是一种分而治之的策略,其主要思想是将一个复杂的大系统分解为若干个子系统,以便降低复杂度,并且增加可修改性。程序从其执行起点开始执行该构件代码,程序执行结束,将控制返回给程序调用构件。
(1)主程序/子程序风格
一般采用单线程控制,把问题划分为若干个处理步骤,构件即为主程序/子程序。子程序通常可合成模块。过程调用作为交互机制,即充当连接件。调用关系具有层次性,其语义逻辑表现为子程序的正确性取决于它调用的子程序的正确性。
构件:主程序/子程序。
连接件:过程调用。
(2)面向对象风格
建立在数据抽象和面向对象的基础上,数据的表示方法和他们的相应操作封装在一个抽象数据类型或对象中。
构件:对象(抽象数据类型的实例)。
连接件:过程调用。
(3)层次型风格
层次系统组成一个层次结构,每一层为上层服务,并作为下层的接口。在一些层次系统中,除了一些精心挑选的输出函数外,内部的层接口支队相邻的层可见。这样的系统中构件在层上实现了虚拟机,连接件由通过决定层间如何交互的协议来定义,拓扑约束包括对相邻层间交互的约束。由于每一层最多只影响两层,同时只要给相邻层提供相同的接口,允许每层用不同的方法实现,这样为软件重用提供了强大的支持。
构件:层上虚拟机。
连接件:层间交互的协议。
(4)客户端/服务器(C/S)风格
基于资源不对等,且为实现共享而提出的。客户应用和服务器构件分别运行在不同的计算机上。
1)二次C/S模式。主要组成部分:数据库服务器(负责数据管理)、客户应用程序(完成与用户交互任务)和网络。称为“胖客户,瘦服务”。
2)三次C/S模式。整个应用逻辑驻留在应用服务器上,只有表示层存在于客户机上。应用功能分为表示层、功能层和数据层。
称为“瘦客户机”。
表示层:用户接口与应用逻辑层的交互,通常适用图形用户界 面,不影响应用逻辑。
功能层:应用的主体,实现具体的业务处理逻辑。
数据层:数据库管理系统。
-浏览器/服务器(B/S)风格:是三层应用结构的实现方式,其三层结构分为:浏览器、web服务器、数据库服务器。
风格 | 优点 | 缺点 |
---|---|---|
C/S | 交互性强、具有安全的存取模式、网络通信量低、响应速度快、利于处理大量数据 | 开发成本高、客户端设计复杂、信息内容和形式单一、不利于推广、软件移植困难、软件维护和升级困难 |
B/S | 分布性强、维护方便、开发简单且共享性强、总体拥有成本低 | 动态页面的支持能力弱、系统的扩展能力差、安全性难以控制、响应速度不足、数据交互性不强 |
风格比较
风格 | 特点 | 优点 | 缺点 |
---|---|---|---|
主程序/子程序风格 | 1. 主程序是程序的入口点,控制程序的执行流程。 2. 程序通过调用子程序来执行具体的任务,子程序完成后返回控制权给主程序。 3. 子程序可以被多次调用,以执行相同或不同的任务。 4. 参数和返回值用于数据传递。 | 1. 模块化:代码可以分解成小的可复用部分。 2. 易于理解和维护。 3. 支持代码重用,减少代码冗余。 | 1. 可能存在全局变量和共享状态,导致潜在的副作用。 2. 难以处理复杂的数据流和并发。 |
面向对象风格 | 1. 程序由对象组成,每个对象具有状态和行为。 2. 对象之间通过方法调用进行交互。 3. 面向对象编程(OOP)强调封装、继承和多态。 4. 数据和方法紧密耦合在对象内部。 | 1. 封装性:对象内部状态被保护,不容易被外部直接访问。 2. 继承和多态支持代码重用和扩展。 3. 易于处理复杂的数据结构和关系。 | 1. 面向对象设计需要深思熟虑,不适合所有问题。 2. 部分性能开销,因为对象和方法调用需要额外开销 |
层次结构风格 | 1. 程序被组织成一系列层次化的模块或层。 2. 上层层次通常调用下层层次的服务,形成分层架构。 3. 每个层次解决特定的问题,层次间的交互通常有规则和接口。 | 1. 分层结构清晰,易于维护和扩展。 2. 支持模块化开发,不同层次可以独立开发和测试。 3. 适合构建大型系统和分布式系统。 | 1. 可能存在性能开销,因为数据必须穿越多个层次。 2. 需要精心设计层次和接口,否则会引入复杂性。 |
客户端/服务器风格 |
特点/要素 | 主程序/子程序 | 面向对象 | 层次结构 |
---|---|---|---|
调用方式 | 明确调用子程序 | 调用对象的方法 | 调用下层层次 |
数据传递 | 参数和返回值 | 对象的属性和方法 | 接口和消息 |
代码组织方式 | 函数/子程序 | 类和对象 | 模块/层次 |
封装性 | 有限,依赖全局变量 | 高,数据和方法封装 | 高,模块内部封装 |
代码复用性 | 一般,通过子程序调用 | 高,通过继承和多态 | 高,通过模块重用 |
复杂性 | 低到中等 | 中等 | 中等到高 |
适用场景 | 小型到中型应用 1.批量数据处理:批量数据处理应用程序通常使用主程序/子程序风格。主程序控制数据的流程,而不同的子程序负责执行特定任务,如数据清洗、转换、计算和报告生成。例如,大型数据库的数据ETL(提取、转换、加载)过程使用这种风格。 2.科学计算:科学计算应用中,主程序通常负责定义数学模型和算法,而子程序执行数值计算和模拟。科学领域的仿真、数值模拟和数据分析都使用主程序/子程序的结构 | 复杂数据结构和关系 1.图形用户界面 (GUI) 开发:GUI应用程序通常使用面向对象风格。界面元素(如按钮、窗口、文本框)被视为对象,每个对象具有属性和方法。用户界面的交互和事件处理通常通过对象的方法来实现。 2.软件开发框架:许多软件开发框架,如Java Spring框架、.NET框架,采用面向对象的设计。开发者通过创建和组合对象来构建应用程序,利用框架提供的类和接口来完成各种任务。 | 大型系统和分层系统 网络协议栈:网络协议栈是一个层次结构风格的示例,如TCP/IP协议栈。不同的协议层负责不同的功能,例如物理层、数据链路层、传输层等。每个层次都有特定的责任,构成网络通信的分层结构。 2.企业应用程序:大型企业应用程序通常采用分层结构风格,如MVC(模型-视图-控制器)架构。应用程序分为数据访问层、业务逻辑层和用户界面层,每个层次负责不同的任务,使应用程序易于维护和扩展。 |
3.以数据为中心的体系结构风格
以数据为中心的体系结构风格强调数据或信息的集中存储和管理。
(1)仓库风格
存储和维护数据的中心场所。由中央数据结构(说明当前的数据状态)和一组独立构件(对中央数据进行操作)组成。
构件:仓库、独立构件。
连接件:仓库与独立构件的交互。
(2)黑板风格
适用于解决复杂的非结构化的问题,能在求解过程中综合运用多种不同的知识源,使得问题的表达、组织和求解变得比较容易。是一种问题求解模型,是组织推理步骤、控制状态数据和问题求解之领域知识的概念框架。可通过选取各种黑板、知识源和控制模块的构件来设计,也可以利用预先定制的黑板体系结构的编程环境。应用于信号处理领域,如语音识别和模式识别。
4.虚拟机体系结构风格
虚拟机体系结构风格的基本思想是人为构建一个运行环境,在这个环境之上,可以解析与运行自定义的一些语言,增加架构的灵活性。它的核心思想是引入虚拟机层,通过在虚拟机上执行代码,实现软件的运行和隔离。
(1)解释器风格
通常被用来建立一种以弥合语义与硬件语义之间的差异。缺点是执行效率较低,典型例子是专家系统。
(2)规则系统风格
包括知识库(规则集、事实集)、规则解释器、规则/数据选择器及工作内存(程序存储区)
风格 | 特点 | 优点 | 缺点 |
---|---|---|---|
解释器风格 | 1. 使用解释器来执行源代码,而不是将代码编译成本地机器代码。 2. 解释器逐行解释和执行代码,通常需要在运行时动态解析和执行指令。 3. 能够实现跨平台兼容性,因为解释器可以在不同的硬件和操作系统上运行。 4. 常见的应用包括编程语言的解释器、虚拟机等。 | 1. 跨平台性:解释器通常不依赖于底层硬件,因此能够在不同平台上执行相同的代码。 2. 灵活性:支持动态语言和运行时修改代码。 3. 相对易于调试和开发。 | 1. 性能较低:解释器通常比本地编译的代码执行速度慢。 2. 不适合高性能、大规模应用。 |
基于规则的系统风格 | 1. 基于规则的系统使用一系列规则和条件来决定程序的行为。 2. 这些规则可以是人工定义的,也可以是自动生成的,用于决策、自动化和智能系统。 3. 常见的应用包括专家系统、决策支持系统、人工智能等。 | 1. 灵活性:可以轻松添加、修改规则,适应不断变化的需求。 2. 自动化:支持自动决策和智能化处理。 3. 易于可视化和调试。 | 1. 复杂性:管理大量规则和条件可能变得复杂。 2. 需要精心设计规则和条件,以避免不一致性和错误。 |
特点/要素 | 解释器风格 | 基于规则的系统风格 |
---|---|---|
执行方式 | 逐行解释源代码 | 基于事先定义的规则和条件 |
跨平台性 | 高,不依赖底层硬件 | 高,不依赖底层硬件 |
性能 | 较低,通常慢于编译代码 | 取决于规则和条件的复杂性 |
灵活性 | 高,支持动态语言和代码修改 | 高,可以灵活添加和修改规则 |
复杂性 | 相对较低 | 取决于规则和条件的数量和复杂性 |
适用领域 | 专家系统、编程语言解释器、虚拟机 1.Python解释器:Python是一种高级编程语言,它的解释器将Python源代码逐行解释和执行。这种解释器风格允许Python代码在不同平台上运行,因为解释器负责将Python代码翻译成底层机器码。这种灵活性和跨平台性使Python成为广泛用于Web开发、数据分析、科学计算等领域的编程语言。 2.JavaScript引擎:Web浏览器中的JavaScript引擎,如V8(用于Google Chrome)和SpiderMonkey(用于Mozilla Firefox),是解释器的例子。这些引擎将JavaScript代码解释为机器码,以便在Web浏览器中执行。解释器使Web应用程序能够以跨平台和跨浏览器的方式运行。 | 决策支持系统、AI 1.欺诈检测系统:金融领域经常使用基于规则的系统来检测欺诈交易。这些系统根据预定义的规则和条件来评估交易,例如交易金额、交易地点、客户历史等。如果某个交易触发了规则中的条件,系统可以采取预定的操作,如暂停交易或发出警报。 2.医疗决策支持系统:医疗决策支持系统可以使用基于规则的系统风格。系统根据患者的病历、症状、诊断标准和医疗指南的规则来提供临床决策建议。这些系统可以帮助医生做出更明智的治疗决策。 |
5.独立构件风格
独立构件风格主要强调系统中的每个构件都是相对独立的个体,它们之间不直接通信,以降低耦合度,提升灵活性。通过构件之间的协作来构建整个系统。
(1)进程通信风格
构件是个独立的过程,连接件是消息传递。这种风格的特点是构件通常是命名过程,消息传递的方式可以是点到点、异步或同步方式及远程过程调用等。
(2)事件系统风格
基于事件的隐式调用风格的思想,构件不直接调用一个过程,而是触发或广播一个或多个事件。系统中的其他构件中的过程在一个或多个事件中注册,当一个事件被触发,系统自动调用在这个事件注册的所有过程,这样,一个事件的触发就导致了另一模块中的过程的调用。
风格 | 特点 | 优点 | 缺点 |
---|---|---|---|
进程通信 | 1. 系统中的不同组件运行在独立的进程中,可以是本地进程或远程进程。 2. 进程之间通过进程间通信(IPC)机制进行数据传递和协作。 3. 可以实现分布式系统,支持并行处理和容错性。 | 1. 高度隔离,一个组件的故障不会影响整个系统。 2. 可以利用多核和多机资源,提高性能。 3. 适用于大规模、分布式系统。 | 1. 进程间通信的性能开销较大。 2. 复杂性高,需要处理进程生命周期、通信协议等问题 |
事件系统 | 1. 组件之间通过事件和消息进行通信。 2. 一个组件产生事件,其他组件订阅并响应这些事件。 3. 常见于图形用户界面(GUI)应用和异步编程。 | 1. 松散耦合,组件之间互相独立。 2. 支持异步和非阻塞操作。 3. 易于实现观察者模式和回调机制。 | 1. 可能难以追踪事件流,引发难以调试的问题。 2. 处理复杂的业务逻辑时,事件驱动模型可能变得复杂。 |
特点/要素 | 进程通信 | 事件系统 |
---|---|---|
通信方式 | 显式进程间通信 | 事件和消息传递 |
耦合度 | 低 | 松散 |
扩展性 | 可扩展,支持分布式 | 可扩展,支持异步 |
性能 | 性能开销较大 | 异步和非阻塞操作 |
适用场景 | 大规模分布式系统 1.操作系统内核:操作系统内核是一个典型的使用进程通信风格的实例。操作系统内核包括多个进程,例如进程调度器、文件系统管理器和网络堆栈。这些进程通过进程通信机制来共享资源、进行调度和处理用户请求,以提供操作系统的核心功能。 2.分布式系统:分布式系统中,各个节点通常作为独立的进程运行,并使用进程通信来实现节点之间的协作。例如,分布式数据库系统中的不同数据库节点可能需要相互通信以支持分布式事务处理。 | 异步和事件驱动应用 1.图形用户界面 (GUI) 应用:GUI应用通常使用事件驱动风格。用户与应用程序交互时,应用程序响应用户触发的事件,如点击按钮、键盘输入等。这些事件触发应用程序中的相应处理逻辑。 2.电子游戏:电子游戏通常采用事件驱动的设计。游戏中的各种事件,如玩家的移动、敌人的行为、碰撞检测等,都会触发相应的游戏逻辑和动作。 |
参考
系统架构设计师教程(第2版)
软件架构风格总结以及场景应用