任务:子系统设计(SOA)
此任务通过特定于 SOA 解决方案的详细信息(特别是从业务分析模型确定子系统时)扩展了传统的 RUP 子系统设计。一旦进行从业务领域到 IT 域的转换,就要将业务领域所定义的已确定功能区域映射到子系统(即:它们的 IT 对等对象)。
用途

为了将业务模型与其 IT 对等对象相关联,需要执行下列操作:

关系
主要描述

一开始,我们确定并记录子系统之间的依赖关系,这些子系统对应于任务:功能区域分析期间已确定的功能区域。通常一个功能区域将对应于一个子系统,这是一个简化的假设,已证实对于许多(即使并非大多数)情况都正确。如果决定将一个功能区域映射到多个子系统,同样会是可行而有效的;然而,这通常意味着领域分解不够深入,功能区域的详细程度不够。

步骤
记录子系统来源

任务:功能区域分析期间,已确定了一组子系统,它们对应于从组件业务图(请参阅概念:组件业务建模)中收到的输入。流程分解期间,所确定的叶级别活动节点(概念:业务流程分解)可置于子系统上,作为该子系统(作为外观)将提供的操作或服务。这些操作的功能将由服务组件的功能组件实现。而且,您可选择将这些操作分组到子系统所提供的接口。将使用操作的非功能需求来挖掘子系统内所需的技术组件和服务。

这些已确定的子系统及其原始来源之间的关系应保持不变,这一点很重要。如果业务级别和服务模型工作产品都是以 UML 表示的,那么可方便地将依赖关系信息存储在这些模型中;否则,应将此类信息存储在模板:用 Word 表示的服务模型中,或保存在关联的工作产品中。

ISV 注意事项:可通过现有子系统(例如定制的应用程序、软件包和/或独立软件供应商)来实现服务。如以下部分所述,某些情况下,确定新的子系统可能涉及到根据数据亲缘性、成本以及性能之类的条件对服务进行实际分组,尽管子系统确定通常是在功能区域分析活动期间自顶向下进行的。将组件分配到体系结构中的各层,以满足非功能需求所施加的体系结构约束,这将在“服务实现”中进行说明。

示例

下表是以租赁机构为例的功能区域分析输出:

功能区域 子系统 描述
市场营销和客户管理 客户服务 客户服务 为功能区域提供所有自动化功能。
产品 促销管理 促销管理 为功能区域提供所有自动化功能。
租赁车队物流 车队管理 车队管理 为功能区域提供所有自动化功能。
租赁管理 租赁 租赁 为功能区域提供所有自动化功能。
租赁管理 预订 预订 为功能区域提供所有自动化功能。
租赁管理 定价 定价 为功能区域提供所有自动化功能。

下面是对于上面所确定的子系统生成的 UML 模型,请注意下面显示的模型中已提供了子系统依赖关系。

对于每个子系统,应记录工件:设计子系统所述的详细信息,或者可通过文档格式的服务模型(请参阅模板:用 Word 表示的服务模型)以类似于以下内容的格式进行捕获。

名称 预订
描述 “预订”子系统用于创建和管理租车预订。
接口
  • 预订车辆
  • 修改预订
  • 获取选项信息
  • 确认租赁协议
  • 查找预订
  • 取消预订
功能
  • 预订车辆
  • 修改预订
  • 获取选项信息
  • 确认租赁协议
  • 查找预订
  • 取消预订
依赖关系
非功能需求



确定并应用服务组件模式

指南:服务组件模式中,我们不仅介绍了通常用于实施此任务期间所确定子系统的各种不同组件,而且还介绍了一组模式,用于对这些子系统进行可伸缩而灵活的实施。这些模式(当然还有其他模式,这不是一个完整的集合)可指定为项目体系结构的组成部分。

特定模式的选择或定制将取决于:

  • 解决方案和特定子系统的功能需求和非功能需求。
  • 将部署组件的中间件所提供的能力和服务质量。
  • 不同模式之间的成本/复杂性与收益的权衡。
确定服务组件

子系统自身并非 IT 资产,不能部署到 IT 基础结构中,它们用于将业务面与 IT 面相连。每个子系统由一个或多个服务组件实现,其中服务组件是企业范围的资产(受管的软件元素,具有已保证的可用性、负载均衡、安全性、性能和版本控制)。服务组件随即由多个功能组件和技术组件实现(如下图)。

通常,分配到子系统的每个服务都有一个服务组件,功能组件和技术组件可在同一子系统内的服务组件之间共享。

确定功能组件

功能组件向服务组件提供更多的业务功能,在许多方面,服务组件所提供的能力完全地取决于其功能组件以及它在这些功能组件上实施的任何附加业务逻辑。

通常可在类型“管理器”中找到功能组件,功能组件是用于管理特定领域元素(例如:“车辆”、“客户”、“调度”等)的组件。这些领域元素通常是粗粒度(详细程度较低)的数据图,而不是简单结构,应该清楚这一点。

示例

请考虑租车示例,“预订”服务组件需要将关于客户、客户希望从何处租用以及针对他们所指定类型的可供车辆等详细信息组织在一起。并且,我们需要确定客户的级别,以便在发生“车辆不可供”之类事件的情况下提供相应级别的服务。下图说明了“预订”的组件模型。



确定技术组件

技术(或:基础结构)组件的作用是提供水平的平台能力,即:它们所提供的能力并不特定于业务领域,而是跨业务领域的。这些技术服务通常是由中间件产品(包括操作系统)提供的,且直接由服务组件或由这些技术服务所依赖的功能组件使用。

示例

完成租车组件模型(请参阅上面的功能组件步骤)时,我们在模型中包含两个技术组件,一个用于“预订”来记录预订请求的完成情况,一个用于表示“车辆”和“位置”组件依赖于 EJB 服务来保存其业务数据。

或者,您可以使用表格格式来表示所需的组件以及它们与先前确定的服务的关系,如下图所示。



将子系统行为分发给子系统元素
目的 指定子系统的内部行为。
确定满足子系统行为需求所需的新设计类设计子系统。 

子系统的外部行为主要由它实现的接口来定义。子系统实现某一接口后,它就承诺要支持该接口定义的每个操作。操作反过来可能会由子系统所包含的设计元素(即,设计类设计子系统)上的操作来实现;该操作可能要求与其他设计元素协作

子系统内模型元素的协作应该用显示子系统行为如何实现的时序图来记录。子系统在接口上实现的每个操作都应该有一个或多个记录的时序图。该图归该子系统所有,并用于设计子系统的内部行为。

如果子系统的行为高度依赖于状态并代表一个或多个控制线程,那么状态机一般在描述子系统行为时更有用。这种情况下的状态机通常与活动类一起用来表示系统(或者这种情况下的子系统)的控制线程的分解,并在状态表图中有所描述,请参阅指南:状态表图在实时系统中,工作产品:封装体的行为还将使用状态机来描述。在子系统内可能有独立的执行线程,这由活动类表示。

在实时系统中,工作产品:封装体将用来包括这些线程。

示例:

子系统协作执行系统要求的某一行为,这可以用时序图表示:

附带文本中描述的图。

该图显示子系统的接口如何用于执行场景。特别是对于“网络处理”子系统,我们发现了子系统必须支持的特定接口(在这种情况下是 ICoordinator)和操作。我们还发现“网络处理”子系统依赖于 IBHandler 和 IAHandler 接口。

在子系统内部,我们发现了 ICoordinator 接口是如何实现的:

附带文本中描述的图。

“协调程序”类充当 ICoordinator 接口的“代理”,处理接口操作并协调接口行为。

该“内部”时序图确切地显示了哪些类提供接口,内部需要发生什么情况才能提供子系统的功能,以及哪些类从子系统向外发送消息。该图阐明了内部设计,这对于内部设计复杂的子系统是必不可少的。它还能使读者很容易了解子系统行为,这样就有希望使其在各环境中可重用。

创建这些“接口实现”图时,可能有必要创建新的类和子系统来执行所要求的行为。流程与“用例分析”中所定义的类似,但我们处理的是接口操作而不是用例。对于每个接口操作,确定在当前子系统中执行该操作所需要的类(或者在所要求的行为很复杂的某些情况下,为包含的子系统)。在现有类/子系统无法提供所要求的行为的情况下,创建新的类/子系统(但先尝试重用)。

创建新的设计元素时,应强制重新考虑子系统内容和边界。要小心避免两个不同子系统中的类实际相同。存在这样的类则意味着子系统边界可能定得不大好。定期重新访问任务:确定设计元素,这可重新平衡子系统职责。

有时创建两个单独的子系统内部模型会很有用,一个是以子系统客户端为目标的规范,而另一个是以实施者为目标的实现。规范可以包括“理想”的类和协作,根据理想的类和协作来描述子系统的行为。另一方面,实现则更与实施紧密相符,并可能演变为实施。有关设计子系统规范和实现的更多信息,请参阅工作产品指南:设计子系统、子系统规范和实现

记录子系统元素
目的 记录子系统的内部结构。 

记录子系统的内部结构,创建一个或多个类图来显示子系统所包含的元素以及它们的相互关联。一个类图应该就足够了,但使用多个类图可降低复杂度并提高可读性。

类图示例如下所示:

附带文本中描述的图。

订单输入系统的类图示例。

子系统的内部内容是作为组件来建模的,该内容还可以在组件图中的组件矩形内表示。这种表示法还让我们将该子系统的交互点包含到系统的其他部分中,这是通过其接口来实现的。

组件图示例如下所示,该图描绘了“订单”子系统、其内部内容以及其提供的和所要求的接口。

附带文本中描述的图。

“订单”子系统的组件图示例

因为组件是结构化的类,因此它可以紧密封装起来,方法是强制从外部通过服从所声明接口的端口进行通信,这使得该组件的规范和互连接更为精确。这种表示法使我们能够通过连接器“传导”部件实例,以在组件实施中扮演特定的角色(有关其他信息,请参阅概念:结构化类)。

下面显示的是使用接口和端口的“订单”子系统的组合结构图示例。

附带文本中描述的图。

“订单”子系统的组合结构图示例



此外,可能需要通过状态表图来记录子系统可能会呈现的状态,请参阅技术:状态表图

子系统本身所包含的类的描述是在任务:类设计中进行处理的。

描述子系统依赖关系
目的 记录子系统所依赖的接口。 

当一个子系统所含的元素使用另一子系统所包含元素的某个行为时,封闭的子系统之间就建立了依赖关系。为了提高重用性并降低维护依赖关系,我们希望根据对子系统的特定接口的依赖关系来表示这一点,而不是根据对子系统本身或者对子系统中所包含元素的依赖关系来表示。

这样做的原因有两方面:

  • 我们希望模型元素(包括子系统)能互相替换,前提是它们提供相同的行为。我们根据接口来指定所要求的行为,因此一个模型元素对另一个模型元素的任何行为要求都应根据接口来表示。
  • 我们希望设计人员完全有自由设计子系统的内部行为,前提是它提供正确的外部行为。如果一个子系统中的模型元素引用另一个子系统中的模型元素,设计人员就不能再随意删除该模型元素,或者将该模型元素的行为重新分配给其他元素。结果,系统就变得更加脆弱。

创建依赖关系时,请确保子系统所包含的模型元素与其他子系统所包含的模型元素之间没有任何直接依赖关系或关联。还要确保各子系统和各接口之间没有循环的依赖关系;一个子系统不能既实现某一接口而又依赖于该接口。

如下所示,可以直接绘制出子系统之间以及子系统和包之间的依赖关系。 如果这样显示依赖关系,则说明一个子系统(例如“发票管理”)直接依赖于另一个子系统(“支付调度管理”)。


附带文本中描述的图。

使用直接依赖关系的子系统分层示例

当有可能将一个子系统替换为另一个子系统时(它们有相同的接口),依赖关系可以绘制到该子系统实现的一个接口,而不是绘制到子系统本身。这就允许使用任何实现相同接口的其他模型元素(子系统或类)。使用接口依赖关系,则允许使用可替代的设计元素来设计灵活的框架。


附带文本中描述的图。

使用接口依赖关系的子系统分层示例

 

属性
多次出现
事件驱动
正在进行
可选
已计划
可重复
更多信息