软件体系结构风格 - Software Architecture Style
北京大学软件与微电子学院 周立新博士《软件体系结构》课程 第 2 讲 教材/参考书:David Garlan & Mary Shaw《Software Architecture: Perspectives on an Emerging Discipline》(Prentice Hall, 1996)
概述
本讲系统梳理了 软件体系结构风格(Architectural Style) 的核心概念,以及 Shaw & Garlan 经典分类法中的 8 大经典架构风格。风格是描述系统组织模式的 recurring pattern,每种风格定义了组件/连接件词汇、拓扑约束和语义解释。
一、软件体系结构再定义
组件与交互
- Component(组件):系统的封装构造块。如过滤器、客户端/服务器、控制器、接口组件等
- Interaction / Relationship(交互/关系):组件之间的连接方式
Len, Clements & Kazman 定义
软件体系结构是系统的结构(一个或多个),由软件组件、组件的外部可见属性、以及它们之间的关系组成。
“外部可见”的含义
- 提供的服务、性能特征、故障处理方式、共享资源使用方式等
- 架构必须抽象掉某些细节,但又需提供足够信息支撑分析、决策、风险降低
架构在开发过程中的定位
需求 → 架构 → 设计 → 可执行代码
| 架构层关注 | 设计层关注 |
|---|---|
| 高层设计、特性、组件、接口、交互、时机、风格、可靠性、约束、指南、质量、复用、标准 | 分解、算法、数据结构、分布、调度、恢复、语言、内存分配、动态实例化、调用栈、垃圾回收、加密、机器码 |
二、架构风格的定义与价值
什么是 Architectural Style
架构风格定义了一类系统的结构组织模式:
- 组件与连接件词汇表(vocabulary of components and connector types)
- 配置规则/拓扑约束(configuration rules / topological constraints)
- 语义解释(semantic interpretation)—— 约束下的组合具有明确含义
风格的优势
- 复用:成熟方案应用于新问题
- 沟通:统一词汇(如”客户端-服务器”)让组织更易理解
- 风格特定分析:可针对某种风格做专项质量分析
评价一种风格的 7 个问题
- 设计词汇是什么?(组件和连接件类型)
- 允许的结构模式有哪些?
- 底层计算模型是什么?
- 风格的核心不变量(essential invariants)是什么?
- 常见应用实例有哪些?
- 优缺点是什么?
- 常见的特化/变体有哪些?
三、Shaw & Garlan 八大架构风格
1. 管道过滤器(Pipes and Filters)
核心思想:整个应用是计算的组合,每个计算是对数据的增量变换,过滤器的输出作为下一个的输入。
组件
- Filter(过滤器):转换数据流。有输入端口和输出端口。增量式、局部计算——读入部分数据、变换、写出结果。
连接件
- Pipe(管道):连接输出端口到输入端口,控制数据流向并完成传输。
不变量/约束
- 过滤器必须是独立实体,不与其他过滤器共享状态
- 过滤器不知道上下游过滤器的身份——只知道输入输出的数据格式
典型实例
- Unix shell 管道
- 传统编译器(词法→语法→语义→优化→代码生成)
- 信号处理领域
- 并行编程 / 函数式编程
优缺点
| 优点 | 缺点 |
|---|---|
| 整体 I/O 行为可理解为个体行为的简单组合 | 容易陷入”批处理”思维 |
| 支持复用 | 不适合交互式应用 |
| 易于维护和增强 | 错误处理困难 |
| 支持特定类型的专业分析 | |
| 支持并发执行 |
2. 数据抽象 / 面向对象组织(Data Abstraction / OO)
核心思想:组件是对象,连接件是方法调用(过程/函数调用)。
两个关键特征
- 对象负责维护自身表示的完整性(通常通过维护不变量)
- 表示对其他对象隐藏(封装)
连接件
- 过程调用 / 方法调用
优缺点
| 优点 | 缺点 |
|---|---|
| 可更改实现而不影响客户(封装带来的可演化性) | 必须知道对方对象的身份 |
| 将问题分解为相互交互的智能体集合 | 副作用问题:A用B,C也用B,C对B的修改对A来说是意外的副作用 |
3. 基于事件 / 隐式调用(Event-Based / Implicit Invocation)
核心思想:组件不直接调用过程,而是发布(publish)事件;其他组件**注册(subscribe)**感兴趣的事件并关联过程。事件发布时,系统自动调用所有注册的过程。
别名
- 发布-订阅模式(Publish-Subscribe)
- 中断驱动是特例
关键不变量
- 事件发布者不知道哪些组件会受到影响,也不知道处理顺序
典型实例
- 用户界面(UI事件)
- 语法制导编辑器
- 数据库管理系统
- 调试器
- 消息代理 / EJB
优缺点
| 优点 | 缺点 |
|---|---|
| 复用性强:注册事件即可接入新组件 | 失控:不知道谁会响应、处理顺序不确定 |
| 易演化:替换组件不影响其他组件 | 数据交换需共享仓库,可能有全局性能和资源管理问题 |
| 正确性分析困难:难以穷举所有可能性 |
4. 分层体系结构(Layered Architecture)
核心思想:将软件组织为多个层,每层构建在更通用的下层之上。上层更面向应用,下层更通用。
组件
- 每层提供一组服务
连接件
- 通常是过程调用
- 层可以是不透明的(只看到相邻层)或半透明的
不变量
- 拓扑约束:每层只能与相邻的上下层通信
封闭式 vs 开放式
| 封闭架构(不透明层) | 开放架构(透明层) |
|---|---|
| 虚拟机只能调用下一层 | 虚拟机可以调用任意低层 |
| 目标:高可维护性 | 目标:运行时效率 |
典型四层划分
- 应用软件层:面向最终用户的用例
- 业务特定层:问题域特有的组件系统
- 中间件层:通用工具、平台无关服务(GUI builder、CORBA、DB接口等)
- 系统软件层:OS、驱动、Socket 等基础设施
优缺点
| 优点 | 缺点 |
|---|---|
| 支持递增抽象层次的设计 | 并非所有系统都能轻易分层 |
| 支持复用 | 性能问题(高层不能直接调低层) |
| 易于维护和增强 | 难以确定合适的抽象层数 |
| 内层完全隐藏,只暴露显式入口 |
5. 仓库风格(Repository)
核心思想:中心化数据存储(通常是结构化的),多个独立计算组件与之交互。
两种变体
| 数据库式 Repository | 黑板式 Blackboard |
|---|---|
| 外部输入流的事务类型触发执行哪个进程 | 黑板当前状态是触发进程选择的主因 |
| 例:传统数据库应用 | 例:语音识别、模式识别 |
黑板风格三大组成
- 知识源(Knowledge Source):独立的应用相关知识模块,只通过黑板交互
- 黑板数据结构:问题求解状态数据,按应用层次组织。知识源修改黑板,逐步逼近解
- 控制:完全由黑板状态驱动。知识源在黑板变化使其适用时机会主义地响应
优缺点
| 优点 | 缺点 |
|---|---|
| 大数据量共享高效 | 控制逻辑复杂(机会主义响应) |
| 安全/访问控制/恢复等集中管理 | 知识源之间依赖隐含 |
| 只要符合数据模型即可添加新工具 | 难以做正确性推理 |
其他实例
- 带全局数据库的批处理系统
- 编程环境(共享程序库 + 工具集)
- 现代编译器的多阶段共享信息(符号表、AST 等)
6. 解释器风格(Interpreter)
核心思想:模拟一个虚拟机,将一种指令集翻译成另一种,实现硬件不直接支持的功能。
四大组件
- 解释引擎(interpretation engine)—— 执行工作
- 存储器(memory)—— 存放待解释的伪代码
- 解释引擎控制状态表示
- 被模拟程序的当前状态表示
典型实例
- JVM(Java 虚拟机)
- Pascal 虚拟机
- 各种脚本语言解释器
目的与代价
- 目标:可移植性(portability)
- 代价:额外计算带来的性能开销
7. 过程控制风格(Process Control)
核心思想:来源于控制工程,关注过程变量的调节。
基本概念
- 过程变量:被控变量、输入变量、操纵变量
- 设定点(Set point):目标值
两类控制
| 开环控制(Open-Loop) | 闭环控制(Closed-Loop) |
|---|---|
| 无反馈,按预设执行 | 有反馈,根据实际输出调整 |
两种闭环策略
| 反馈控制(Feedback) | 前馈控制(Feedforward) |
|---|---|
| 根据被控变量偏差调整操纵变量 | 根据输入变量提前预测调整 |
软件范式三大组成
- 计算元素:过程定义、控制算法
- 数据元素:过程变量、设定点、传感器
- 控制循环范式:收集信息 → 调整过程变量 → 驱动实际状态向目标状态靠近
8. 其他常见架构
分布式进程(Distributed Process)
- 拓扑:环形、星形等
- 进程间协议
- 客户端-服务器
主程序/子程序组织
- 经典的调用-返回结构
特定领域软件架构(DSSA)
- 通用模型(Generic models):真实应用的抽象,如编译器模型
- 参考模型(Reference models):描述一类系统的抽象模型,如 OSI 网络模型
状态转移系统
- 基于状态机的建模
四、客户端-服务器与多层架构
Client-Server 不变量
- 客户端进程向服务器进程请求服务
- 组件:客户端 + 服务器
- 连接件:API、RPC、网络协议
分类
- 2 层 C/S:客户端直接连服务器
- 3 层 C/S:中间有代理层(事务监控、翻译、智能代理等)
多层架构(Multi-tiered)
- 每层可以驻留在不同的硬件/软件平台上
- 子系统分解是多层架构的基础
- 可同时提升安全性和可维护性
典型 3 层 Web 架构
- Tier 1(客户端):浏览器
- Tier 2(服务器):Web 服务器 + 应用服务器(Servlet/JSP + 业务逻辑)
- Tier 3(后端):数据库服务器
五、异构架构风格(Heterogeneous Architecture)
现实:系统通常不是按单一一致的风格开发的。不同抽象层次可能有不同风格。
异构的三种途径
- 通过层次(Through hierarchy)
- 允许单个组件使用混合的架构连接件
- 在一个架构描述层次上用完全不同的风格详细展开
Layered
├── Objects
│ └── Component(内部含 Method Call)
├── Pipe-Filter(RPC 连接)
└── RDBMS(Subscribe 模式)
六、关键术语对照表
| 英文 | 中文 | 说明 |
|---|---|---|
| Component | 组件 | 系统构造块 |
| Connector | 连接件 | 组件间的连接方式 |
| Style | 风格 | 结构组织模式 |
| Pattern | 模式 | 设计层面的复用方案 |
| Framework | 框架 | 可实例化的代码骨架 |
| Reference Architecture | 参考架构 | 某类系统的抽象模型 |
| DSSA | 特定领域软件架构 | Domain-Specific Software Architecture |
| Product Family | 产品族 | 系列产品的架构复用 |
七、参考资料
- Mary Shaw, “The Coming-of-Age of Software Architecture Research,” ICSE 2001
- Paul Clements and Mary Shaw, “A Field Guide to Boxology,” COMPSAC 1997
- David Garland and Mary Shaw, Software Architecture: Perspectives on an Emerging Discipline, Prentice Hall, 1996
- Mary Shaw, “Some Patterns for Software Architecture,” PLoPD vol. 2, 1996
- Mary Shaw, “Patterns for Software Architectures,” PLoPD vol. 1, 1995
- David Garland and Mary Shaw, “An Introduction to Software Architecture,” Advances in SE and KE, 1993
关联笔记
- 软件体系结构概述-第1讲-周立新 — 课程第1讲,架构定义、重要性、建筑类比、4+1视图
- IEEE 1471-2000 软件体系结构标准 — IEEE 标准定义
- 设计模式课程-第3讲-原则 — 设计原则(SRP/OCP/LSP/DIP/ISP),更小粒度的设计复用
- A Tour of C++-第二版-Bjarne-Stroustrup — C++ 语言层面的抽象机制
- CLFS流式细胞仪软件概要设计说明书-V1.4 — 实际项目的三层架构案例