软件体系结构及应用 软件体系结构及应用 体系结构风格的选择
主要内容 体系结构风格选择方法 体系结构风格选择的案例分析:上下文关键词索引系统(KWIC) 体系结构风格的选择 主要内容 体系结构风格选择方法 体系结构风格选择的案例分析:上下文关键词索引系统(KWIC) – Solution 1: 带有共享数据的主程序-子过程体系结构 – Solution 2: 抽象数据类型风格 – Solution 3: 隐式调用风格 – Solution 4: 管道-过滤器风格
软件体系结构及应用 体系结构风格选择方法
目前最常见的体系结构: 分层+OO 我们已经学习过了十余种体系结构风格; 简单的判断某一个具体的应用应该采取何种体系结构是非常困难的, 体系结构风格的选择 目前最常见的体系结构: 分层+OO 我们已经学习过了十余种体系结构风格; 简单的判断某一个具体的应用应该采取何种体系结构是非常困难的, 需要借助于丰富的经验。 从目前的趋势来看: – 管道-过滤器风格、批处理风格已经非常少见; – 过程控制风格、黑板结构、虚拟机风格往往针对具体的应用领域; – OO的思想已经融合在几乎所有的体系结构之中,而事件风格、层次化的思 想同样也被广泛使用; – MVC、基于规则的系统、B/S、数据库风格也是经常使用的风格。
体系结构风格的选择次序 绝大多数实际运行的系统都是几种体系结构的复合: 将焦点集中在系统的总体结构的考虑上,而避免较多的考虑使用的语 – 在系统的某些部分采用一种体系结构而在其他的部分采用另外的体系,故而 需要将复合几种基本体系结构组合起来形成复合体系结构。 – 在实际的系统分析和设计中,首先将整个系统作为一个功能体进行分析和权 衡,得到适宜的、最上层的体系结构; – 如果该体系结构中的元素较为复杂,可以继续进行分解,得到某一部分的局 部体系结构。 将焦点集中在系统的总体结构的考虑上,而避免较多的考虑使用的语 言、具体的技术等实现细节上。
风格选择的基本思想:由粗到细的分解 基本的分析方法:功能和复杂 性的分解 体系结构风格的选择 – 横向分解:分层次 2 纵向划分 – 横向分解:分层次 – 纵向分解:子系统、模块 – 针对每一个分解后得到的模块, 根据该问题领域的特性,选择行 为模式 (具体的体系结构风格) 1 横 向 分 层 3 体系结构风格 (行为模式)选择 – 构件、连接件设计 ——从大粒度风格入手,逐渐细化 4 构件-连接件划分
SA风格选择需考虑的因素 技术因素: 性能因素: 体系结构风格的选择 – (1) 何种构件、连接件 – (2) 在运行时,构件之间的控制机制是如何 被共享、分配和转移 – (3) 数据如何通讯 – (4) 数据与控制如何交互 性能因素: –可修改性 • 算法的变化 • 数据表示方式的变化 • 系统功能的可扩展性 –性能: •时空复杂性 –可复用性
软件体系结构及应用 基于经验的SA风格选择原则
经验法则(1) 层次化的思想在任何系统中都可能得到应用; 如果问题可分解为连续的几个阶段,那么考虑使用顺序批处理风格或 管道-过滤器风格 体系结构风格的选择 经验法则(1) 层次化的思想在任何系统中都可能得到应用; 如果问题可分解为连续的几个阶段,那么考虑使用顺序批处理风格或 管道-过滤器风格 – 如果每个阶段是递增的,从而后序可在前序完成之前开始,那么就要使用管 道-过滤器风格 – 如果问题涉及到连续数据流上的转换,考虑使用管道-过滤器风格
经验法则(2) 如果核心问题是应用程序中数据的理解、管理与表示,那么考虑使用 仓库或者ADT/OO风格 体系结构风格的选择 经验法则(2) 如果核心问题是应用程序中数据的理解、管理与表示,那么考虑使用 仓库或者ADT/OO风格 如果数据格式的表示可能发生变化,ADT/OO可限制这种变化所影响 的范围 如果数据是持久存在的,使用仓库结构 – 如果使用仓库风格且输入数据是无序的、执行次序无法预先确定,使用黑板 结构 – 如果使用仓库风格且执行次序由请求来决定、数据是高度结构化的,适用数 据库风格 • 如果系统存在很多异构的数据源,考虑使用联邦数据库风格; • 如果追求数据存取的性能,考虑使用分布式数据库风格。
如果任务之间的控制流可预先设定、无须配置,那么考虑使用主程序- 体系结构风格的选择 经验法则(3) 如果任务之间的控制流可预先设定、无须配置,那么考虑使用主程序- 子过程风格、OO风格 如果任务需要高度的灵活性与可配置性、松散耦合性,或者任务是被 动性的,那么考虑使用事件系统或C/S风格 – 如果任务的产生者与接收者之间不能预先绑定在一起,使用基于事件的风格 – 如果任务分为生产者与消费者,考虑C/S风格 • 如果追求客户端的计算效率,考虑胖客户端的C/S风格 如果客户端频繁发生变化,考虑瘦客户端的C/S风格(或B/S风格) 如果服务器端的计算压力过大,考虑使用服务器的集群风格 如果无须中央服务器,使用点对点(P2P)风格
基于经验的SA风格选择 经验很重要,没有不行; 经验的随意性很大,很难科学地评价各种经验的正确性; 体系结构风格的选择 基于经验的SA风格选择 经验很重要,没有不行; 经验的随意性很大,很难科学地评价各种经验的正确性; 没经过高度概括和总结的经验需要后来者花费很长的时间和精力才能 继承,甚至可能失传; 经验经常限制创新。 …发挥想象力,创造新的体系结构风格
Key Word in Context (KWIC) 软件体系结构及应用 案例分析 Key Word in Context (KWIC)
题内关键词索引 简称KWIC,又称上下文关键词索引。是最早出现的机编索引,首先应用于1960年美国化学文摘社创办的《化学题录》。题内关键词索引的标目在款目的中部,左右均为该标目的上下文;索引款目按位于款目中部作为标目的关键词的字顺排列。格式如: KWIC的设计思想是:①文献题名通常具有揭示文献主题内容的作用,从题名中抽取的关键词能有效地将用户指向相关主题的文献;②保留题名中关键词前后的上下文,有助于说明关键词的含义,可用作限定标目含义的说明语。 KWIC的编制步骤包括:①把经过人工处理的文献题名(包括增补的关键词)输入计算机。②计算机用"非用词表"剔除题名中的介词、连词、冠词等,筛选出有检索意义的关键词。③将每个关键词依次轮流用作索引标目,同时保留其上下文。若题名过长,可以截断或移位。④编成索引款目,并进行编排加工,最后交付印刷。上述工序除第一步由人工完成外,其余皆由计算机完成。
KWIC: Functional Requirements 体系结构风格的选择 KWIC: Functional Requirements The KWIC index system (KWIC索引系统) –接受一些行 –每行有若干词 –每个词由若干字符组成 –每行都可以循环移位。重复地把第一个词删除,然后接到行末 – KWIC把所有行的各种移位情况按照字母表顺序输出
A third way for styles to 体系结构风格的选择 A case for KWIC A third way for styles to third way for styles to A way for styles to A third for styles to A third way styles to A third way for to A third way for styles A third way for styles to be combined is to combined is to be elaborate one level of for styles to A third way is to be combined A third way for styles to be combined is to elaborate one level of Input(输入) be combined is to combined is to be is to be combined to be combined is elaborate one level of one level of elaborate level of elaborate one of elaborate one level Circular shifts(循环移位) level of elaborate one of elaborate one level one level of elaborate styles to A third way for third way for styles to A to A third way for styles to be combined is way for styles to A third Output(输出)
KWIC use case 体系结构风格的选择 User User Provides Input 提供输入 <uses> Views Output 产生输出 <uses> <uses> Generate Circular Shift 产生循环移位 Sort Output 排序
KWIC: 非功能性需求 可修改性 性能 系统构件的可复用性 –处理算法的变化 –数据表示方式的变化 –系统功能的可扩展性 –时空复杂性 体系结构风格的选择 KWIC: 非功能性需求 可修改性 –处理算法的变化 • 批处理 vs. 渐增式 –数据表示方式的变化 • 行存储, 显式 vs. 隐式变化 –系统功能的可扩展性 • e.g., 从数据库或从UI输入行 • e.g., 对初始行从删除,修改或增加操作 性能 –时空复杂性 系统构件的可复用性 –在何种程度上可以作为可重用的组件实体
KWIC 解决方案 Solution 1: 带有共享数据的主程序-子过程体系结构 Solution 2: 抽象数据类型风格 体系结构风格的选择 KWIC 解决方案 Solution 1: 带有共享数据的主程序-子过程体系结构 Solution 2: 抽象数据类型风格 Solution 3: 隐式调用风格 Solution 4: 管道-过滤器风格
Solution 1:带有共享数据的主程序- 子过程体系结构 软件体系结构及应用 Solution 1:带有共享数据的主程序- 子过程体系结构
Solution 1:主程序-子过程体系结构 体系结构风格的选择 Solution 1:主程序-子过程体系结构 采用“主程序-子过程”风格、对系统进行功能分解,是最自然的想法, 也是“面向过程的编程” 的主要思路。 –分为四个基本功能:输入、移位、排序、输出 –主程序按次序调用这四个模块 –通过共享的数据存储和无约束的读-写协议在模块之间进行数据交换
Solution 1:主程序-子过程体系结构 体系结构风格的选择 Solution 1:主程序-子过程体系结构 主程序 子过程 共享数据结构
过程算法 首先调用input函数来读取和解析输入文件并将其写在chars_和 line_index_数组中 体系结构风格的选择 过程算法 首先调用input函数来读取和解析输入文件并将其写在chars_和 line_index_数组中 然后调用circularShift函数,产生移位结果并写入circular_shifts_数组中 然后调用alphabetize函数对其进行排序,结果写入alphabetized_数组中 最后调用output函数,输出结果
Solution 1:主程序-子过程体系结构 体系结构风格的选择 Solution 1:主程序-子过程体系结构 Advantages: –模块之间的数据共享 –不同的计算功能被隔离在不同的模块中 Disadvantages: –对数据存储格式的变化将会影响几乎所有的模块 –对处理流程的改变与系统功能的增强也很难适应,依赖于控制模块内部的调用次序 –这种分解也难以支持有效的复用
软件体系结构及应用 Solution 2: 抽象数据类型
Solution 2:抽象数据类型 技术发展: 采用OO的思想,数据和作用在数据上的读写操作被封装为对象,主 体系结构风格的选择 Solution 2:抽象数据类型 技术发展: – 面向过程的结构化编程 面向对象的编程 采用OO的思想,数据和作用在数据上的读写操作被封装为对象,主 程序调用这些对象,形成控制流程; –数据不再被构件直接共享,而是被封装在了对象中 –每个对象提供了一个接口,允许其他对象通过该接口调用对该对象内封装的数据的操作
体系结构风格的选择 Solution 2:抽象数据类型
Solution 2:抽象数据类型 LineStorage object (存储和处理字符、单词、行) 体系结构风格的选择 Solution 2:抽象数据类型 LineStorage object (存储和处理字符、单词、行) Input object (负责从输入文件中读取数据并将其存储在LineStorage对 象中) CircularShifter object (负责对LineStorage对象中存储的数据进行循 环移位) Alphabetizer object (负责对循环移位后得到的数据进行排序) Output object (负责打印输出排序后的数据) Master control object (主控制对象:负责控制其他各对象中方法的 调用次序)
体系结构风格的选择 “输出”对象 主控制程序 “排序”对象 Class Diagram: System Statics “行数据存储” 对象
Sequence Diagram: System Dynamics 体系结构风格的选择 Sequence Diagram: System Dynamics 主控制 程序 “输入” “输出” 对象 对象 “排序” 对象 “循环 “行数据 移位” 存储” 对象 对象
Class KWIC //主对象KWIC构造五个对象实例 LineStorage lines = new LineStorage(); 体系结构风格的选择 Class KWIC //主对象KWIC构造五个对象实例 LineStorage lines = new LineStorage(); Input input = new Input(); CircularShifter shifter = new CircularShifter(); Alphabetizer alphabetizer = new Alphabetizer(); Output output = new Output(); //然后分别调用这五个对象实例的某些方法 input.parse(file, lines); shifter.setup(lines); alphabetizer.alpha(shifter); output.print(alphabetizer);
Solution 2: Abstract Data Types 体系结构风格的选择 Solution 2: Abstract Data Types Advantages: –某一构件的算法与数据结构的修改不会影响其他构件 –构件之间依赖性降低,提高了复用度 Disadvantages: –不适合功能的扩展 –为了增加新功能,要么修改已有的模块,要么就加入新的模块
软件体系结构及应用 Solution 3: 隐式调用
Solution 3:隐式调用 为了降低各模块之间的耦合度,提高复用性能,将模块之间的“直接调 体系结构风格的选择 Solution 3:隐式调用 为了降低各模块之间的耦合度,提高复用性能,将模块之间的“直接调 用”改为“隐式调用”——事件驱动的体系结构风格。 采用与Solution 1相似的方式: – 四个功能模块 – 共享数据 不同之处: – 共享数据并不直接对外暴露数据格式,而是借鉴了Solution 2中的方式,对 数据进行封装,通过接口向外暴露对数据的操作; – 各功能模块之间不再通过主程序来控制,而是事件驱动。
体系结构风格的选择 Solution 3:隐式调用
回忆:事件系统的两种实现方式 Systems without a central dispatcher module 体系结构风格的选择 回忆:事件系统的两种实现方式 Systems without a central dispatcher module Systems with separate dispatcher module
Solution 3:隐式调用 Two LineStorage modules 体系结构风格的选择 Solution 3:隐式调用 Two LineStorage modules –第一个LineStorage模块负责保存最初输入的lines –第二个LineStorage模块负责保存所有经过循环移位/排序后得到的 lines Input:负责从输入文件读取信息并保存在第一个LineStorage模块中
Solution 3:隐式调用 CircularShifter: 负责移位并将结果存储在第二个lineStorage模块中 体系结构风格的选择 Solution 3:隐式调用 CircularShifter: 负责移位并将结果存储在第二个lineStorage模块中 Alphabetizer: 负责对移位结果进行排序 Output: 负责产生输出结果 Master control: 负责系统的全局控制)
事件分发策略 该案例中,使用观察者模式来处理事件 两个LineStorage模块被实现为“被观察者” 体系结构风格的选择 事件分发策略 该案例中,使用观察者模式来处理事件 两个LineStorage模块被实现为“被观察者” – CircularShifter和Alphabetizer模块被实现为“观察者” –CircularShifter 是第一个 LineStorage 模块的观察者, 而 Alphabetizer 是第二个 LineStorage模块的观察者。
运行时事件相互作用 CircularShifter向第一个LineStorage模块注册,以表明兴趣 体系结构风格的选择 运行时事件相互作用 CircularShifter向第一个LineStorage模块注册,以表明兴趣 当有新行被加入到第一个LineStorage模块时,它将发出一个事件 CircularShifter模块接收到该事件 作为对该事件的响应,CircularShifter模块对新加入的行进行循环移位, 并将产生的结果写入第二个LineStorage模块中
运行时事件相互作用 Alphabetizer模块向第二个LineStorage模块注册,表明兴趣 体系结构风格的选择 运行时事件相互作用 Alphabetizer模块向第二个LineStorage模块注册,表明兴趣 当有新的循环移位行加入到第二个LineStorage模块时,它发出事件 Alphabetizer模块接收到该事件 作为对该事件的响应, Alphabetizer对这些循环移位行进行排序
Solution 3: Implicit Invocation 体系结构风格的选择 Solution 3: Implicit Invocation Observer Observerable
Solution 3: Implicit Invocation 体系结构风格的选择 Solution 3: Implicit Invocation 优点:功能扩展比较容易 –新模块可直接被加到系统中,只需将其注册到事件系统中即可 –数据通过接口访问,数据格式的变化不会影响其他部分 –各模块之间的调用隐式化,从而复用性提高
Solution 3: Implicit Invocation 体系结构风格的选择 Solution 3: Implicit Invocation 难以控制各模块之间的处理次序 使用更多的存储空间
软件体系结构及应用 Solution 4: 管道-过滤器
Solution 4:管道-过滤器 使用管道-过滤器风格 –四个过滤器:输入、移位、排序、输出 体系结构风格的选择 Solution 4:管道-过滤器 使用管道-过滤器风格 –四个过滤器:输入、移位、排序、输出 –每个过滤器处理数据,然后将结果送至下一个过滤器 –控制机制是分布式的:只要有数据传入,过滤器即开始工作 –过滤器之间的数据共享被严格限制在管道传输
Solution 4: Pipes and Filters 体系结构风格的选择 Solution 4: Pipes and Filters
Solution 4:管道-过滤器 Filters: Pipe: 11 体系结构风格的选择 Solution 4:管道-过滤器 Filters: – Input filter (“输入”过滤器:从数据源读取输入文件,解析格式,将行写入输 出管道) – CircularShifter filter (“循环移位”过滤器) – Alphabetizer filter (“排序”过滤器) – Output filter (“输出”过滤器) Pipe: – in_cs pipe – cs_al pipe – al_ou pile
体系结构风格的选择 Solution 4:管道-过滤器 过程流非常直观 支持复用 –过滤器的功能相互隔离 –新功能容易加入 –容易修改
Solution 4:管道-过滤器 无法支持交互式系统 空间复杂性高 – 例如,为了删除某行,就必须有一些永久共享存储, 11 体系结构风格的选择 Solution 4:管道-过滤器 无法支持交互式系统 – 例如,为了删除某行,就必须有一些永久共享存储, 但这就违反了这种方法的基本原则 空间复杂性高
KWIC: Comparison of Solutions 11 体系结构风格的选择 KWIC: Comparison of Solutions
体系结构风格的选择 案例2 案例2 Tektronix公司仪器软件
问题描述 工程历时三年,是由Tektronix公司和计算机研究实验室合作展开 –目的是为示波器开发一种可重用的系统体系结构 体系结构风格的选择 问题描述 工程历时三年,是由Tektronix公司和计算机研究实验室合作展开 –目的是为示波器开发一种可重用的系统体系结构 –不同的示波器由不同的产品部门生产,有各自的开发约定,软件组织结构等 –硬件性能的变化和用户界面的新需求 –性能问题越来越严重,软件在仪器中不能被快速配置
解决方案1 面向对象模型 示波器对象 波形 最大-最小波形 X-Y波形 叠加波形
问题: 没有一个整体模型解释怎样结合对象类型 导致功能划分的混乱
解决方案2 分层模型 硬件 数字化 可视化 用户接口 操作
核心层提供信号处理功能 第二层提供波形采集功能 第三层提供波形处理功能 第四层提供显示功能 最外层为用户界面
优点: --功能分层明确定义的组 缺点: --层次间强加的抽象边界和各功能间交互的需要时是相互冲突的
解决方案3 管道过滤器模型 信号 耦合 采集 To-XY 裁剪 迹 时间 波形 测量 触发子系统 测量值
优点: 缺点: --在功能划分中没有将各个功能孤立 --模型将信号处理作为数据流问题比较合适 --允许在系统设计中硬件和软件构件的灵活混合和替换 缺点: --没有清晰地说明用户怎样与其交互
解决问题4 改进后的管道过滤器模型 耦合度 种类,速率 转换 大小 信号 耦合 采集 To-XY 裁剪 迹 时间 波形 测量 触发子系统 测量值
优点: --控制界面的引入解决了很大一部分用户界面的问题 缺点: --管道过滤器计算模式的性能非常差