概要设计与体系结构
概要设计的任务与工程过程、软件设计原则(抽象/模块化/信息隐藏/模块独立性)、耦合与内聚等级,以及分层、C/S、B/S、MVC、管道过滤器等体系结构风格。
🎯学习目标
- 掌握系统概要设计的任务,理解概要设计的工程过程(9 个活动);
- 掌握软件设计原则:抽象与逐步求精、模块化、信息隐藏、功能独立性;
- 掌握衡量模块独立性的两个指标——耦合度(7 种)与内聚度(7 种);
- 掌握软件体系结构的概念与三要素(构件、连接件、约束);
- 理解常用体系结构风格:分层、C/S、B/S、MVC、管道过滤器、数据共享、总线等。
1概要设计的任务
设计阶段要解决的问题是系统"怎么做"。对较大规模项目,软件设计分两阶段:概要设计(系统/总体设计,确定基本框架)和详细设计(部件级设计,确定内部细节)。概要设计是从软件需求规格说明书出发,把问题结构(软件需求)映射为软件结构。
设计的元素
- 软件系统采用什么样的体系结构;
- 需要创建哪些功能模块以及模块间的关系;
- 公共的数据结构;
- 需要什么样的网络环境支持;
- 需要什么类型的后台数据库。
概要设计的三大内容
软件体系结构设计
选择适合需求的体系结构风格,开展物理架构、逻辑架构设计。如何划分系统、标识组件、组件如何通信。
接口设计
接口是外部可见操作的说明。包括与其他系统/硬件的外部接口、各构件间的内部接口。
数据设计
确定文件系统结构、数据库模式/子模式,进行数据完整性和安全性设计,确定输入输出文件的数据结构。
2概要设计工程过程(9 个活动)
概要设计主要包括三方面:系统物理架构设计、软件结构设计(接口)、数据结构设计,具体任务分为 9 个活动:
| # | 活动 | 要点 |
|---|---|---|
| 1 | 制定规范 | 设计文档编制标准、信息编码格式、硬件/操作系统接口规约、设计目标与原则 |
| 2 | 系统体系结构设计(物理架构) | 分解为独立子系统、分析通信与外部接口、确定软硬件/网络/数据环境、整体物理部署优化 |
| 3 | 软件体系结构设计(逻辑结构) | 确定子系统模块元素、定义模块功能与接口、确定模块间调用返回关系、评估质量进行结构优化 |
| 4 | 公共数据结构设计 | 公共数据变量结构与作用范围、输入输出文件结构、数据库表/视图结构及数据完整性 |
| 5 | 安全性设计 | 操作权限、操作日志管理、文件与数据加密、特定功能校验 |
| 6 | 故障处理设计 | 对软硬件、网络故障进行备用设备、出错处理、数据备份 |
| 7 | 可维护性设计 | 设置系统监测专用模块、预计今后功能扩充的模块 |
| 8 | 编写概要设计报告 | 概要设计说明书、数据库设计说明书、测试初步计划 |
| 9 | 概要设计评审 | 需求确认、接口确认、模块确认(高内聚低耦合)、风险性、可维护性、质量 |
3软件设计原则(一)
3.1 抽象与逐步求精
抽象:基本策略是从特殊到一般,上层概念是下层概念的抽象,下层概念是上层概念的精化;用于在软件规模逐渐增加的情况下控制复杂性。软件设计的抽象包括:
过程抽象(功能抽象)
任何一个完成明确定义功能的操作都可以被当作单个实体对待。
数据抽象
定义数据类型和施加于该类型对象的操作,并限定对象的取值范围。
逐步求精:把问题求解过程分解成若干步骤或阶段,每步比上步更精化、更接近解法。抽象与求精的关系:抽象描述过程和数据而忽略低层细节,求精则揭示低层细节;软件工程过程的每一阶段都是对软件解法的一次求精。
3.2 模块化
模块是数据说明、可执行语句等程序对象的集合,单独命名并可通过名字访问(如过程、函数、子程序、类、构件)。模块化是把软件按规定原则划分为较小的、相互独立但又相互关联的部件,体现了系统分解和抽象的过程。
3.3 信息隐藏
每个模块的实现细节对其它模块应该是隐蔽的;模块所包含的信息(数据和过程)不允许其它不需要这些信息的模块使用。通过信息隐藏可定义和实施对模块过程细节和局部数据结构的存取限制(如把成员设为 private)。
- 信息专家原则:将职责(方法)分配给具有实现该职责所需全部信息的直接类;尽量避免越级操作(如 Sale 类不越级操作 Item,只汇总 SalesLineItem)。
- 创建者原则:若 A 组合/聚合/记录/紧密使用 B,则由 A 创建 B 的实例,保证外部类无法控制实例、避免级联影响。
- 控制器原则:控制器是 UI 层之上的第一个对象,负责接收和处理 UI 产生的事件(如 Listener、Handler、Action、Controller),使功能与 UI 按钮解耦。
4功能独立性:耦合与内聚 ⭐(核心考点)
功能独立性指每个模块只完成系统要求的独立子功能,且与其他模块联系最少、接口简单。衡量指标为内聚度与耦合度。目标:高内聚、低耦合。
内聚(块内联系,越高越好)
| 内聚类型 | 说明(由弱到强) |
|---|---|
| 偶然内聚 | 各处理元素之间没有任何联系,最差,不易理解也不易修改 |
| 逻辑内聚 | 执行几个逻辑上相似的功能,通过参数确定完成哪个功能 |
| 时间内聚 | 把需要同时执行的动作组合(如初始化一组变量、同时打开若干文件) |
| 过程内聚 | 处理相关且必须以特定次序执行 |
| 通信内聚(信息内聚) | 所有处理元素在同一数据结构上操作,或使用相同输入/产生相同输出 |
| 顺序内聚 | 各处理元素密切相关于同一功能且顺序执行,前一元素输出是下一元素输入 |
| 功能内聚 | 最强,所有元素共同完成一个功能、缺一不可,最易理解修改、利于重用 |
耦合(模块间联系,越低越好)
| 耦合类型 | 说明(由弱到强) |
|---|---|
| 间接耦合 | 两模块无直接关系,通过主模块的控制和调用间接实现,耦合最弱 |
| 数据耦合 | 有调用/引用关系,传递的是数据值(值模型传递) |
| 标记(对象)耦合 | 传递的是数据对象/数据结构(引用模型传递) |
| 控制耦合 | 传递的信息中有控制信息(开关、标志),被调模块据此选择执行某功能;中等程度耦合 |
| 外部耦合 | 一组模块访问同一全局简单变量,且不通过参数表传递 |
| 公共耦合 | 通过公共数据环境(全局变量、共享区、文件等)相互作用,复杂度随模块数增加 |
| 内容耦合 | 最高/最差,一模块直接访问另一模块内部数据、非正常入口转入、代码重叠 |
5软件体系结构概念与三要素
软件体系结构是软件模块(构件)之间关系的表示,决定整个系统的结构,也确定系统的质量。它高度抽象、超越了算法和数据结构,两个基本着眼点是系统的结构及需求与实现间的交互。最早指出 SA 重要性的是 Dijkstra(1968:"the larger the project, the more essential the structuring!")。
三个核心元素
构件 Component
连接件 Connector
规约/协议 Protocol
构件 vs 连接件:构件主要负责业务层面的计算,连接件主要对构件之间的交互进行抽象。连接子内部规约包括通信链路、时序编排和监控设施三部分。
6常用体系结构风格 ⭐
体系结构风格描述某一特定应用领域中系统组织方式的惯用模式,从已有成功系统的组织结构中抽取而来。每种风格用构件、连接件、规则/配置三要素描述。
6.1 分层体系结构(Layered)
将系统组织成分层结构,每层包含一组相关功能,每层提供服务给毗邻的上一层,最底层是核心服务。是典型的调用-返回体系结构。
| 三要素 | 内容 |
|---|---|
| 构件 | UI 层、业务逻辑层、数据实体层、算法层 |
| 连接件 | 过程调用 |
| 规则/配置 | 上层调用下一层,不能跨层调用 |
特征:关注点分离、层间隔离(不跨层调用,仅用下层接口)。优点:降低开发成本与复杂度、可扩展可维护、接口不变即可重用、某层接口变化只影响相邻上层。缺点:每层处理解释导致效率降低(可用缓存改善)、根本性需求改变可能产生跨层级联修改(可用依赖倒置改善)。适用于企业级应用、大型 Web、需特定安全/可靠性要求的系统。
6.2 C/S 与 B/S 体系结构
C/S(客户端-服务器)
基于资源不对等实现共享,由服务器、客户应用程序、网络组成。客户端发请求、服务器返回响应。优点:强大的数据操作与事务处理、分布式任务、适应性强。缺点:客户端设计复杂、开发成本高、移植维护升级困难。
B/S(浏览器-服务器)
利用浏览器技术简化客户端、便于升级。由数据库服务器、Web 服务器、客户浏览器、网络组成。优点:安装修改维护在服务器端解决、自动升级、开放性好。缺点:安全性难控制、动态交互性不强、响应速度低。
C/S 多层演变:① 两层结构——信息表示与应用逻辑都放客户机("胖客户机"),服务器只管数据库事务;管理简单但客户机越多越难维护。② 三层结构——把易变化的应用逻辑提取到专门的"应用服务器"上(客户机变"瘦"),需求变化时只需改少数应用服务器。
6.3 MVC(模型-视图-控制器)
MVC 在传统 B/S 基础上加入控制器,由控制器决定视图与模型之间的依赖关系,保持功能内核独立于用户接口,适用于交互式软件开发。
| 组件 | 职责 | 对应传统 B/S |
|---|---|---|
| 模型 Model | 管理应用行为和数据,响应状态查询与更改指令 | 业务逻辑和数据 |
| 视图 View | 管理数据的显示 | 用户界面 |
| 控制器 Controller | 解释用户的鼠标键盘输入,通知模型和视图更改 | 新增元素 |
变更-传播机制是模型与视图、控制器之间的唯一连接,基于事件的隐式调用(构件不直接调用过程,而是触发或广播事件),保证模型与用户接口的一致性。适用于需要分离业务逻辑和用户界面、或支持多种用户界面(Web/移动/桌面)的应用。
6.4 数据流体系结构(管道-过滤器)
语境:数据源源不断产生,系统需对其进行处理。解决方案:把系统分解为几个连续处理步骤,步骤间通过数据流连接,一个步骤的输出是另一步骤的输入;每个步骤由过滤器(Filter)实现,数据传输由管道(Pipe)负责。包括管道过滤器风格和批处理风格。
优点:整个系统的输入输出行为可理解为单个过滤器行为的叠加组合;任意两过滤器只要遵守共同规约即可相连;易于维护和升级。典型应用:编译器、Unix 管道、图像处理、信号处理、网络监控等。
6.5 其他风格
数据共享(容器)体系结构
所有数据在一个中央容器中管理,可被所有组件访问,组件只通过容器交互。优点:组件独立、数据一致管理;缺点:容器是单点失效、通信低效、分布困难。适用数据密集型应用(金融、医疗、企业信息系统)。
总线体系结构
基于消息驱动和硬件总线概念,消息总线根据"构件-消息响应登记表"分派消息。优点:简单、灵活、可扩展;缺点:总线瓶颈、单点故障、实时性限制。适用小型/嵌入式系统(传感器网络、控制系统、家庭娱乐)。
7设计决策与"4+1"视图
体系结构设计决策
体系结构模式是经过实践验证、可在系统中复用的组织方式。体系结构设计是创造性过程,并不存在公式化的设计过程,取决于系统类型、架构师经验、系统特定需求。架构师应考虑:是否存在通用体系结构模板、系统如何分布到硬件/处理器、用什么策略控制构件运行。
- 性能:将关键操作局部化到少量构件、部署在同一台计算机、用大粒度构件节省通信开销;
- 信息安全:使用层次化体系结构,把最关键资产放在最内层;
- 可用性:包含冗余构件,以便不停机更换/替换构件;
- 可维护性:使用细粒度、自包含的构件,将数据生产者与消费者分离。
软件体系结构的"4+1"视图模型
Kruchten(Rational,1995)提出用 5 个视图描述软件体系结构,每个视图只关心系统的一个侧面:
| 视图 | 面向 | 关注内容 |
|---|---|---|
| 逻辑视图 | 最终用户 | 功能和数据处理的逻辑组成(类图、对象模型、状态图) |
| 开发视图(模块视图) | 系统开发人员 | 子系统的分解、接口及依赖(包图、类图),建议 4-6 层 |
| 进程视图 | 系统集成人员 | 并发性、同步性、互操作性(进程、线程、通信) |
| 物理(部署)视图 | 系统部署人员 | 功能如何分布于各节点,考虑性能、可用性、可靠性、可扩展性 |
| 场景视图(+1) | — | 用例汇总,将其他四个视图结合起来 |
⭐重点例题
taxMaker.calculate(taxpayer.getFlag()),被调方法 calculate(int flag) 内部用 if(flag==0)... else if(flag==1)... 选择执行不同分支。
判断:传递的 flag 是控制变量(开关/标志),被调模块据此选择执行某功能,故为控制耦合(中等程度)。
风险:未来税率变化时会导致相关模块级联修改。改进:用多态或策略模式替代 flag 分支,降为数据/对象耦合。
🎯自测(点击展开)
概要设计要解决系统的什么问题?包含哪三大内容?
衡量模块独立性的两个指标是什么?目标是什么?
内聚最强和最弱的类型分别是什么?
耦合最强(最差)和最弱(最好)的类型分别是什么?
体系结构的核心公式与三要素是什么?
MVC 相比传统 B/S 新增了什么元素?它的作用是什么?
📝强化题库
选择题点选即时判分;填空题输入后"检查"或"显示答案"。