请输入您要查询的百科知识:

 

词条 设计包
释义

§ 简介

设计包是由类、关系、用例实现、图和其他包组成的集合;它可用于将设计模型分成更小的部分,从而建立设计模型的结构。包主要用于模型组织,并且通常用作配置管理的单元。

为了便于理解,可以将设计模型分成更小的单元。通过将设计模型元素分组,将其归入到包和子系统中,然后显示这些分组之间的相互关系,就可以更容易地了解模型的整体结构。请注意,设计子系统是一种特殊的包,它具有行为语义(即实现一个或多个接口);有关详细信息,请参见工件:设计子系统和指南:设计子系统。设计子系统具有不同于设计包的目的,后者是静态的东西,在逻辑上类似于实施子系统。[1]

§ 设计特点

包内容可见性

一个包中可以包含公有类,也可以包含私有类。公有类可以与任何其他类相关联。私有类只能与其所在包中包含的类相关联。

包接口由包的公有类组成。包接口(公有类)隔离并实施对其他包的依赖关系。平行开发可通过这种方式得以简化,因为您可以及早建立接口,并且开发人员只需要了解其他包接口的变化。

包分区标准

您可以出于以下原因划分设计模型:

您可以在完成系统后将包和子系统用作订购、配置或交付单元。

由于资源分配以及不同开发团队的能力不同,可能要求将该项目划分给处于不同位置的不同组。通过带有明确定义的接口的子系统,可以在各团队之间以有控制、有协调的方式划分工作,从而使设计和实施能够平行地进行。

子系统可用于按照用户类型来建立设计模型的结构。许多变更需求都来自于用户;子系统可确保来自特定用户类型的变更需求只影响系统中与该用户类型对应的部分。

在某些应用程序中,某些特定信息应该只能由少数几个人访问。子系统使您能够在需要保守秘密的地方保守秘密。

如果您正在构建一个支持系统,就可以利用子系统和包向该支持系统提供一个与要支持的系统相似的结构。这样,您就可以使两个系统的维护实现同步。

子系统用于代表系统所使用的现有产品和服务(例如 COTS 产品和库),正如以下几节所述。

将边界类打包

在将边界类分发给各个包时,可以应用两种不同的策略。要确定选择哪种策略,取决于系统接口将来是否可能发生重大的变化。

如果系统接口可能被替换,或者可能经历相当大的更改,就应将接口与设计模型的其他部分隔离开。在更改用户界面时,只有这些包会受到影响。这种较大更改的示例是从基于行的接口转换为基于窗口的接口。

如果主要目的是简化较大的接口更改,就应在一个(或几个)单独的包中放置边界类。

·如果不打算进行任何较大的接口更改,指导原则的就应是对系统服务进行更改,而不是对接口进行更改。然后,应该将边界类和在功能上与它们相关的实体类及控制类放置在一起。这样,如果特定的实体类或控制类发生变化,就很容易看出哪些边界类受到影响。

如果要简化对系统服务的更改,就要将边界类和在功能上与它们相关的类打包到一起。

对于在功能上与任何实体类或控制类都不相关的必选边界类,应将它们和属于同一接口的边界类放置在单独的包中。

如果某一边界类与一项可选服务相关,就要在单独的子系统中将此边界类与协同提供该服务的类归为一组。该子系统将映射到在预定可选功能时所提供的可选构件上。

§ 示例展示

将功能相关的类打包

应该为每一组在功能上相关的类确定一个包。在判断两个类是否在功能上相关时,可以应用以下几项实用标准。这些标准按重要性递减的顺序排列:

如果一个类的行为和(或)结构的变化使得另一个类也必须相应地变化,这两个类就在功能上相关。

示例

如果向实体类 Order 添加一项新属性,则很有可能使控制类 Order Administrator 必须进行更新。所以,它们属于同一个包 Order Handling。

从某个类开始(例如一个实体类),检查从系统中将该类删除所带来的影响,这就有可能查明一个类与另一个类是否在功能上相关。如果在某个类删除后出现了多余的类,这些类就和与已删除的类存在一定的联系。之所以会变得多余,是因为该类只由已删除的类使用,或者它完全依赖于已删除的类。

示例

Depot Handling System 中有一个包 Order Handling,它包括两个控制类:Order Administrator 和 Order Registrar。这两个控制类都用于为库房中的订单处理服务建模。 所有的订单属性和关系都由实体类 Order 存储,它只为订单处理而存在。如果删除该实体类,将不再需要 Order Administrator 或 Order Registrar,因为它们只有在存在 Order 时才有用。因此,实体类 Order 应该与这两个控制类包含在同一个包中。

因为一旦从系统中删除 Order,Order Administrator 和 Order Registrar 就会变得多余,所以它们和 Order 属于同一个包。

如果两个对象进行大量的消息交互,或者以其他复杂的方式互相通信,这两个对象就可能在功能上相关。

示例

控制类 Task Performer 和 Transporter Interface 之间要收发大量的消息。这也表示了它们应包含在同一个包 Task Handling 中。

如果某个边界类的功能是显示一个特定的实体类,它就可能在功能上与该实体类相关。

示例

Depot Handling System 中有一个边界类 Pallet Form,它用于向用户显示实体类 Pallet 的实例。现在更改了该类的接口。在屏幕上,每个 Pallet 都由一个标识号来代表。如果更改了有关某个 Pallet 的信息(例如为该 Pallet 还指定了一个名称),就可能还必须更改该边界类。因此,Pallet Form 应包含在 Pallet 所在的同一个包中。

如果两个类与同一个主角进行交互,或受到对同一个主角更改的影响,这两个类就可能在功能上相关。如果这两个类不涉及同一个主角,它们就不应存在于同一个包中。当然,如果有更加重要的原因,也可以忽略最后一条规则。

示例

在 Depot Handling System 中有一个包 Task Handling,它包含有控制类 Task Performer。这是唯一与主角 Transporter 相关的包,Transporter 是在库房中运输托盘的实际运输机。此主角通过边界类 Transporter Interface 与控制类 Task Performer 进行交互。因此,此边界类应包含在包 Task Handling 中。

Transporter Interface 和 Task Performer 都会受到对 Transporter 主角更改的影响,所以它们属于同一个包。

如果两个类之间存在某些关系(关联关系、聚合关系等),这两个类就可能在功能上相关。当然,不能不假思索地遵从这一标准,但在其他标准都不适用时,就可以使用它。

一个类可能与创建其实例的类在功能上相关。

以下两条标准可确定何时不应将两个类放在同一个包中:

与不同主角相关的两个类不应放在同一个包中。

可选类和必选类不应放在同一个包中。

评估包的内聚度

首先,一个包中的所有元素必须具有相同的可选性:在必选的包中不能有可选的模型元素。

示例

必选的实体类 Article Type 包括一项名为 Restock Threshold 的属性。但重新进货功能在系统中是可选的。因此,Article 应分成两个实体类,其中的可选类与必选类相关。

被视为必选的包不能依赖于任何被视为可选的包。

一般来说,单个包不能由两个不同的主角使用。其原因是,一个主角行为的变更不应同时影响其他主角。此规则也有例外,例如对于那些构成可选服务的包。无论有多少主角在使用这种类型的包,都不应对其进行划分。因此,如果包不是可选的,就应拆分所有由几个主角使用的包或类。

同一个包中的所有类都必须在功能上相关。如果您遵循了“从功能上相关的类中查找包”部分中的标准,则一个包中的各个类将彼此在功能上相关。但特定的类可能会自行包含“过多”行为或包含不属于该类的关系。在这种情况下,应该将该类的一部分移出去变成全新的类,或者并入可能属于另一个包的其他类。

示例

一个包中控制类 A 的行为不应过多依赖于另一个包中的类 B。为了隔离 B 专有的行为,控制类 A 必须分成两个控制类 A' 和 A"。将 B 专有的行为放在新控制类 A" 中,并将 A" 和 B 放在同一个包中。另外,新类 A" 还获得了与初始对象 A' 的关系(如泛化关系)。

为了隔离 B 专有的行为,将缺乏同种性的控制类 A 分成两个控制类 A' 和 A''。

说明包依赖关系

如果一个包中的类与另一个包中的类之间存在关联关系,这两个包就互相依赖。包依赖关系的模型是使用包之间的依赖关系来建立的。依赖关系可以帮助我们评估更改的结果:一个由许多包所依赖的包要比一个没有包依赖的包更难于更改。

因为在对包进行说明时会发现几种与此类似的依赖关系,这些关系必然会在工作过程中发生变化。对依赖关系的说明可以包括有关哪些类关系导致了该依赖关系的信息。由于这种信息很难得到,因此只有在该信息相关并具有一定价值时才应将其包括。

示例

在 Depot Handling System 中,从包 Order Handling 到包 Item Handling 存在依赖关系。之所以会发生这种关联关系,是因为 Order Handling 中的实体类 Order 与另一个包中的实体类 Item Type 存在关联关系。

包 Order Handling 依赖于 Item Handling,因为这两个包中的两个类之间存在关联关系。

评估包的耦合度

包耦合有利有弊:其利在于耦合代表着复用,其弊在于耦合代表了使系统更难变更和演进的依赖关系。可以遵循以下的一般原则:

不应对包进行交叉耦合(即互相依赖),例如两个包不应互相依赖。

在这种情况下,需要对包进行重组,删除交叉依赖关系。

较低层中的包不应依赖于较高层中的包。包只应依赖于同一层及下一层中的包。

在这种情况下,需要对功能进行重新划分。一种解决方案是,按照接口说明依赖关系,并在较低层中组织接口。

通常,依赖关系不应跳层,除非依赖行为在所有层之间都是共同的,另一种方法是简化各层之间的传递操作调用。

包不应依赖于子系统,而应只依赖于其他包或接口。

随便看

 

百科全书收录594082条中文百科知识,基本涵盖了大多数领域的百科知识,是一部内容开放、自由的电子版百科全书。

 

Copyright © 2004-2023 Cnenc.net All Rights Reserved
更新时间:2025/1/19 14:39:54