架构描述与面向对象设计映射的探索
1. 架构描述的演进
架构描述的规范方法目前相对静态,它们各自定义了一套“完整的”架构描述产品,但未提供任何排序或流程,只是明确了架构描述的最终状态,却未对中间表示给予指导。例如,C4ISR 框架文档通常暗示操作和技术视图产品先于系统视图产品,但该文档本身并未明确规定。
架构规范正从如报告和矩阵等“纸质产品”的规范,向更具交互性的架构表示形式转变。C4ISR 框架文档和 IEEE 推荐实践都定义了“纸质产品”,而 CADM 作为数据模型,适合通过数据库实现,美国陆军对 C4ISR 框架文档的实现就同时使用了数据库和网络绘图工具。
随着对架构这一学科经验的积累,架构描述技术将向产品的时间/事件序列发展。MITRE 架构方法包含了一组初步产品(目标、愿景、需求),这些先于 IEEE AWG 文档所涵盖的内容(视角和视图)。因此,架构描述可能会朝着更动态的表示形式发展,包括定义产品何时以及如何产生的过程导向,以及将架构表示为数据库和工具数据集而非纸质产品的工具导向。
2. 架构描述的发展方向
目前存在两种不断发展的概念,即“系统架构”和“软件架构”。“软件架构”主要关注软件系统的(内部)结构,而“系统架构”方法更侧重于给定系统在其环境中的作用。常见的有“客户端 - 服务器软件架构”或“管道和过滤器软件架构”等术语,但在系统架构表示中尚未形成类似描述常见风格或“模式”的术语。
不过,系统架构方法比软件架构表示能涵盖更广泛的主题。系统的许多属性,如安全性、容错性、可维护性、适应性等,在系统架构分析中很常见。仅关注结构的软件架构定义不太适合捕捉系统的这些非结构属性。
两个领域都在研究工具,特别是能够捕捉系统和软件动态属性的工具。相关项目中使用的工具专注于捕捉描述背后的数据,以实现架构描述的各种表示形式。以数据为中心的表示的一个动机是,包含特定架构表示的数据库已被用作其他尝试对所得架构进行建模或模拟的工作的输入,这些模型包括经典的网络性能分析、军事模拟(战争游戏),以及在较小程度上作为架构组件系统测试的输入。
未来的架构描述应包括以下方面:
-
涵盖系统非结构方面的表示
:能够全面描述系统的各种属性,不仅仅局限于结构。
-
通用的视角集
:提供统一的观察和分析架构的角度。
-
增强的工具支持
:尤其是用于架构表示的交互式规范和分析。
-
基于通用视角和底层信息描述的架构表示“互操作性”
:确保不同架构表示之间能够有效交互和协作。
系统架构和软件架构方法都将为这一演进做出贡献。
3. 架构描述技术总结
“架构设计”的演进已到了广泛认可“架构很重要”的阶段,但以往描述架构的临时方法已不足够。因此,近期有多项工作致力于独立于任何特定架构来描述架构的内容。
相关的“架构描述技术”包括美国国防部 C4ISR 架构框架文档的文本描述、相关的核心架构数据模型以及 IEEE 架构描述推荐实践。所有这些方法都认识到需要多个视图来描述单个架构,但它们在定义视图内容以及对“文档”、“数据库”和“视角”作为关键架构框架决策的侧重上有所不同。
捕获架构表示后,下一步自然是进行比较。目前支持多种生成架构描述方法的比较技术基于数据建模。我们需要更多架构分析经验,才能确定架构数据模型是否足以进行架构的分析和比较。
架构过程的演进将改变架构规范技术。当前实践倾向于基于纸质的静态表示,随着工具和交互式表示(如万维网)的发展,架构元技术将向过程和行为模型转变。定义架构描述内容和含义的方法应不断发展。
4. 面向对象设计映射到 Ada 语言的介绍
Fusion 是一种系统的面向对象软件开发方法,可用于开发顺序反应系统和某些受限的并发系统。该方法基于一组简洁而全面的明确定义的模型,并提出了软件开发过程。在 Fusion 过程的最后阶段,详细设计(包括类描述和方法的高级算法设计)需要映射到编程语言。为了保持与编程语言无关,Fusion 只提供了一般的映射策略,但这可能导致低估实现阶段的难度。
相关内容展示了如何将 Fusion 设计映射到 Ada 95 编程语言,它扩展和改进了之前的工作,并通过一个案例研究进行说明,该案例足以说明大多数实现决策。为避免混淆,使用“变量”代替 Ada 中定义的“对象”一词,“对象”的含义为“类的实例”。
5. 银行交易案例研究
5.1 问题陈述
银行管理账户,有支票账户和储蓄账户两种类型。每个账户由一名客户拥有,客户可以拥有支票账户、储蓄账户或两者皆有。银行处理金融交易,包括获取账户余额、从账户提取现金、向账户存入现金以及将资金从一个账户转移到另一个账户。交易涉及一个或两个账户,并且会被记录,每月末会向所有客户发送报告,显示其账户在上一期间进行的所有交易。
为简化起见,假设所有交易均由银行职员代表客户执行,客户随后会通过邮政邮件收到交易确认及其结果。转账操作需在取款被授权的情况下进行,储蓄账户取款不超过余额时授权,支票账户取款不超过信用额度时授权。操作完成后会记录交易并通知账户所有者,其他金融交易的处理方式类似。
5.2 分析阶段
根据 Fusion 过程,使用实体 - 关系方法的符号和语义,通过类模型对问题域中的概念进行建模。此时类仅具有值属性,如客户的姓名和地址。
下一步是识别外部代理及其与系统通过事件交换的交互。系统与银行职员和邮政服务两个外部代理进行交互,输入事件触发系统操作,为简便起见,输入事件和系统操作使用相同名称。应用程序需提供检索余额、存入现金、提取现金、转账和生成月度报告等系统操作。
每个系统操作(如转账)通过模式进行规范,该模式通过前置和后置条件描述操作如何改变系统状态以及向外部代理发送的输出事件。在分析金融交易创建时,发现需要当天的日期,因此在类模型中添加了 Calendar 类,并通过时钟代理发送的 new_day 输入事件触发 Calendar.date 属性的更新。
下面是系统类模型的简单示意表格:
| 类 | 属性 |
| ---- | ---- |
| Transaction | date, amount |
| Account | number, balance |
| Checking | credit_limit |
| Savings | interest_rate |
| Customer | name, address |
| Postal_Service | - |
| Clerk | - |
| Calendar | date |
mermaid 流程图展示分析阶段流程:
graph LR
A[问题域概念建模] --> B[识别外部代理及交互]
B --> C[定义系统操作]
C --> D[规范系统操作模式]
D --> E[添加 Calendar 类]
6. 设计阶段
6.1 交互图
在分析阶段结束时,我们知道了系统的主要类和所有操作,但操作尚未与类关联。Fusion 将此步骤推迟到设计阶段,为每个系统操作设计交互图。交互图显示操作的控制器(如转账操作中的源账户)以及控制器如何通过与其他对象协作实现操作效果。协作通过消息发送系统地进行,例如源账户向其所有者客户发送“记录交易 t”的消息。需要注意的是,交互图建模的是控制流而非数据流,数据可能双向流动,参数沿箭头方向,结果沿相反方向,无需额外箭头返回结果。
以下是转账操作交互图的简单说明:
1. 源账户发起转账操作。
2. 获取当前日期。
3. 创建交易对象。
4. 源账户取款。
5. 目标账户存款。
6. 记录交易。
7. 通知账户所有者。
mermaid 流程图展示转账操作交互流程:
graph LR
A[源账户] --> B[获取日期]
B --> C[创建交易]
C --> D[源账户取款]
D --> E[目标账户存款]
E --> F[记录交易]
F --> G[通知所有者]
6.2 可见性图
在所有系统操作及其调用的方法的设计通过交互图描述后,下一步是生成可见性图。客户端对象向服务器对象发送消息时,需“知道”服务器对象的“名称”。若该引用存储在客户端对象中,Fusion 称可见性为永久的,用实线箭头表示;否则为动态可见性,例如服务器对象仅在方法调用期间作为参数传递给客户端对象。动态可见性会导致类之间的依赖,永久可见性会使客户端对象具有所谓的对象属性,即持有对服务器对象引用的组件。
银行交易系统的可见性图考虑了所有系统操作的可见性需求。根据转账操作的交互图,源账户需要对其所有者的永久引用,同时也需要对目标账户所有者的动态引用,但由于永久可见性链接已使客户端类依赖于服务器类,可从可见性图中删除该动态引用。此外,打印机和日历对象被设定为全局可见,即对所有对象可见。
Fusion 还区分共享和独占服务器对象,独占服务器对象在任何给定时间只能由一个对象持有引用,如客户的交易集合。若服务器对象的生命周期与客户端对象绑定,则服务器在图形上包含在客户端内,如客户拥有的支票账户和储蓄账户。若引用不能更改,服务器对象名称前会加上关键字 constant。
类描述方面,现在可以在类描述中记录类的接口,这几乎是一项机械任务,无需新的创造性工作。类和值属性来自系统类模型,对象属性源自可见性图,关键字 bound/unbound、shared/exclusive、constant 和 col 的含义与可见性图中相同,交互图显示了类必须提供的操作和方法及其参数。
通过以上对架构描述和面向对象设计映射到 Ada 语言的介绍,我们可以看到架构领域的发展趋势以及如何将设计理念转化为实际的编程实现,这对于软件开发和系统架构设计具有重要的指导意义。
7. 类描述的详细内容
类描述是将前面分析和设计阶段的成果进行整合,形成清晰的类接口定义。以下是对银行交易系统中主要类的详细描述:
| 类名 | 属性 | 属性类型 | 操作 | 操作参数 | 操作说明 |
| ---- | ---- | ---- | ---- | ---- | ---- |
| Account | number | String | retrieve_balance | - | 获取账户余额 |
| | balance | Money | withdraw | amount: Money | 从账户提取现金 |
| | | | deposit | amount: Money | 向账户存入现金 |
| Checking | credit_limit | Money | - | - | - |
| Savings | interest_rate | Percentage | - | - | - |
| Customer | name | String | - | - | - |
| | address | String | - | - | - |
| Transaction | date | Date | - | - | - |
| | amount | Money | - | - | - |
这些类描述明确了每个类的属性和操作,为后续的编程实现提供了清晰的蓝图。
8. 从设计到 Ada 95 语言的映射
将 Fusion 设计映射到 Ada 95 编程语言需要遵循一定的规则和步骤。
-
类的映射
:在 Ada 95 中,类通常对应于包(package)。例如,对于 Account 类,可以创建一个名为 Account_Package 的包。
package Account_Package is
type Account is tagged private;
function retrieve_balance(This : Account) return Money;
procedure withdraw(This : in out Account; amount : Money);
procedure deposit(This : in out Account; amount : Money);
private
type Account is tagged record
number : String;
balance : Money;
end record;
end Account_Package;
- 操作的映射 :类中的操作对应于包中的子程序。如上述代码中的 retrieve_balance、withdraw 和 deposit 子程序。
- 属性的映射 :类的属性对应于包中私有类型的记录成员,如 Account 类的 number 和 balance 属性。
9. 相互依赖关系的处理
在面向对象设计中,类之间的相互依赖关系是一个重要的问题。在银行交易系统中,账户类与客户类、交易类之间存在依赖关系。
-
永久可见性的处理
:当存在永久可见性时,如账户类对客户类的永久引用,可以在账户类的记录中添加一个客户类型的对象属性。
package Account_Package is
type Account is tagged private;
-- 其他操作声明
private
type Account is tagged record
number : String;
balance : Money;
owner : Customer; -- 永久引用客户对象
end record;
end Account_Package;
- 动态可见性的处理 :动态可见性通常通过参数传递来实现。例如,在转账操作中,源账户需要临时引用目标账户的所有者,可以在转账操作的参数中传递该引用。
procedure transfer(Source : in out Account; Destination : in Account; amount : Money; Dest_Owner : Customer);
10. 总结与展望
通过对架构描述的演进、面向对象设计映射到 Ada 95 语言的研究,我们可以看到软件开发领域的不断发展和变化。
-
架构描述方面
:未来架构描述将更加注重动态性、过程导向和工具支持,能够更好地涵盖系统的非结构属性,实现不同架构表示之间的互操作性。
-
面向对象设计映射方面
:将 Fusion 设计映射到 Ada 95 语言为软件开发提供了一种有效的实现途径,但在处理类之间的相互依赖关系等方面还需要进一步优化和完善。
mermaid 流程图展示从设计到实现的整体流程:
graph LR
A[架构描述演进] --> B[面向对象设计]
B --> C[分析阶段]
C --> D[设计阶段]
D --> E[类描述]
E --> F[映射到 Ada 95]
F --> G[处理依赖关系]
G --> H[最终实现]
总之,架构描述和面向对象设计映射是软件开发中不可或缺的环节,它们的不断发展和完善将推动软件开发行业朝着更加高效、可靠的方向前进。我们需要不断探索和实践,以适应不断变化的技术需求和市场环境。