首页 UML约束

UML约束

举报
开通vip

UML约束UML约束 第12章 约束 到目前为止,本书中介绍的许多表示法都是图形的。这些图标表示了许多概念,同时通 过按一定方式连接这些图标,还表达了许多系统特性。例如,连接两个矩形的线表示了两个 类之间的关联,并说明了这些类的实例如何互相链接。图中的文字用来命名和标注模型元素, 添加特定的注文,例如,重数或监护条件。 图形表示法适合于展示系统的结构方面,但对于描述模型元素的细节特性,或者由相关 业务规则对这些模型元素所附加的限制方面,并不是很有效。这些附加特性可以用约束的形式添加到模型中。一个约束是关于一个或多个模型...

UML约束
UML约束 第12章 约束 到目前为止,本书中介绍的许多表示法都是图形的。这些图标表示了许多概念,同时通 过按一定方式连接这些图标,还表达了许多系统特性。例如,连接两个矩形的线表示了两个 类之间的关联,并说明了这些类的实例如何互相链接。图中的文字用来命名和标注模型元素, 添加特定的注文,例如,重数或监护条件。 图形表示法适合于展示系统的结构方面,但对于描述模型元素的细节特性,或者由相关 业务规则对这些模型元素所附加的限制方面,并不是很有效。这些附加特性可以用约束的形式添加到模型中。一个约束是关于一个或多个模型元素的断言,它指明了该系统处于合法状 态时,系统必须满足的特性。 例如,假定一个银行开设了一种具有优惠利率的新型储蓄账户,但要求该账户的余额必 须保持在0到250,000镑范围内。如果存款(deposit)或取款(withdraw)导致余额(balance)超出此范围则会被拒绝。图12.1表示了这种储蓄账户类(Saving Acount),在注解内非形式写出的是对它的约束。 图12.1 受约束的储蓄账户 UML中非形式写出的约束应当用花括号‘{ }’括起来,放在所描述的模型元素的内 部或紧靠所描述的元素的地方。也可以放在注解的图标内,并用虚线连接到所描述的模型元 素。 约束指明的特性可以是真或假。例如,给定图12.1中储蓄账户类的任一实例,约束的 真假值将取决于该实例的余额值是否在所述余额范围内。系统必须确保所有约束为真。例如, 如果一个账户的余额小于零,就会指出一个错误已经发生,系统已处于非法状态。 UML对于少量常见的情况定义了标准约束。更一般的约束可以用非形式化的英语、更 规范的约束语言或者目标程序 设计 领导形象设计圆作业设计ao工艺污水处理厂设计附属工程施工组织设计清扫机器人结构设计 语言的表示法写出。UML定义了一种约束语言,称为对象约束语言或简称为OCL。本章将描述OCL最重要的特征,并给出使用OCL的例子。 12.1 标准约束 UML规约定义了若干标准约束,用于不同的模型元素。例如,在交互图中的链接和实 例,或者对应的角色,可以如图9.10和9.12中那样,说明为‘new’,‘transient’或‘destroyed’, 以指明它们在一个具体交互中的生命期。 这些约束与常见的有点不同的是,它们是以描述了被约束元素的一般特性的面目出现 的,而不是陈述了一个系统状态可能是真或假的断言。更符合习惯的是对关联定义的标准约 束。 12.1.1xor ‘xor’约束可以应用到两个或多个关联。当一个类参与多个受约束的关联时,‘xor’ 约束是很用的。xor约束用于指明在任一给定时刻,该公共类只能参与一个受约束的关联。 图12.2表示的是用‘xor’约束指明,银行客户(customer)在同一时刻不能同时开有储蓄账户(saving account)和存款账户(deposit account)。注意,受该约束限制的关联必须包括重数 为0的情况。 图12.2 xor约束 12.1.2 关联的子集约束在UML规范中和其它地方只是作为例子说明的,而不是正式地作为标 准约束定义的。这种约束可以用在连接相同两个类的一对关联上,它说明作为一个关联的实 例的链接集合,必须是另一个关联的实例的链接集合的子集。 图12.3 子集约束 子集约束可以用一个附有此约束的依赖箭头,将这些关联连接起来表示。该依赖箭头尾 部所连接的关联的实例集,必须是该依赖箭头所指向的关联的实例集的子集。 图12.3表示的是使用子集约束的一个例子,此例子引自UML规范。它表示了两个关联, 分别说明谁是委员会(committee)的成员(member)和主席(chair)。如果没有这个约束,这 个图说明某个人可能是委员会的主席同时却不是该委员会的成员。子集约束通过断言:chair关联链接的任何一对对象也必须由Member Of关联链接,排除了这种可能。 12.2 对象约束语言 标准约束是很有用的,然而要一般地应对各种约束,还需要更灵活的手段。例如,考虑 图12.4所示的对象图,它表示了在银行应用中不多见的情况。这里一位借记卡(debit card)的持有者与该卡所属账户的持有者不是同一个人。我们希望对这个模型定义一个约束排除这 种情况,这种约束用前面定义的约束是做不到的。 非形式地说,为了排除这种情况需要附加的约束是,所有借记卡的持有者必须是该借记 卡所属账户(account)的持有者。在某些情况下,非形式的约束完全能胜任,但要用英语清楚 地、无二义性地指明一个复杂条件常常非常困难,即使在相对简单的情况下,说明约束的语 句也会有些费解,在初次阅读时其意思也不一定显而易见。 为了解决这些问题,计算机科学家已经开发了各种各样的形式规范语言。由于使用了数 学符号,这些语言显得有些难以接受。OCL对象约束语言试图提供一种可用的、基于文本 形式的规范语言,用来书写用于UML模型的约束。 图12.4 不常见的情况 在上述例子中,所要求的约束可以作为具有下述特性的借记卡来指明。设想有一个借记 卡实例,它直接链接到持有该卡的客户,但也间接地链接到另一位客户实例。沿着连接该借 记卡到所属账户的链接可以检索到该账户,然后可以检索到持有该卡的第二位持有者。一旦 检索到这两个客户对象,我们就可以很容易地简单、明确地指明约束的内容:在这两种情况 下,到达的必须是同一个客户对象。 这个例子使我们想到,像OCL这样的约束语言,应当提供三种必不可少的能力: 1.能够说明什么模型元素被约束。被约束的元素称为约束的语境,在12.3节讨论。 2.能够通过模型导航,确定与所定义的约束相关的其他对象。借助于在12.4节讨论的 导航表达式可以做到。 3.能够对语境对象和借助于导航表达式检出的对象做出断言。这些断言类似于程序设 计语言中使用的布尔表达式,但如12.6节所讨论的,断言具有更强的表达力。 12.3 约束的语境 每个OCL约束都有一个语境,把OCL表达式和被约束的模型元素连接在一起。OCL约束的语境可以是一个类或一个操作。这些约束可以表示在图上或者写在一个独立的文本文 档中附加到该模型,采用什么方式将约束与其语境联系在一起,依赖于用什么风格描述约束。 如果约束表示在图上,那么约束可以放在表示约束语境的符号的附近或内部。例如,如 果约束的是类,那么可以放在类的图标的内部。图12.5表示的是图12.1表示的账户类,附加到该账户的约束指明了该账户实例的余额必须在所指定的范围之内。 图12.5 简单约束 约束也可以如图12.1所示,用附加到模型元素的注解(note)表示。选择什么方法表示 约束纯粹是一个表示风格的问题。 代替在图上表示约束,也可以用纯文本形式表示约束。在这种情况下,必须明确地指出 语境。约束必须从语境声明开始。语境声明由关键字‘context’和约束的类名或操作名组成。 图12.5所示的约束用纯文本形式书写如下: 关键字‘inv’指明了这个约束是一个不变量。类不变量说明的特性是,在所有时间点 上这些属性值必须为真。这里表示的是在任何时候存储在余额属性的值必须大于0而小于250000。其他类型的约束将在12.7节讨论。 约束中的术语‘self ’指的是当前语境对象。由于约束总是针对当前语境计值的,所以 ‘self ’是可选的,然而使用self可以使约束容易阅读。在本章的其余部分常常会把self插入到约束中。 这个约束也说明了如何用OCL表示访问一个对象的特征(feature),即在表示要访问的对象的表达式的后边,添加一个圆点,然后写出特征的名称。选择这种表示方法是为了与 Java和C++中访问类的特征时使用的点表示法一致。 这种表示法允许在形式上有两个变化,即对语境对象可以提供一个可选名称,对约束本 身也可以给一个名称,使得在一个复杂模型中可以更方便地引用指明的约束。例如,如果将 上述语境对象命名为‘ acc ’,约束命名为‘ account Limits’,则上述约束可表示如下: 12.4 导航表达式 约束的使用并不只限于类的不变量,例如在12.1节给出的例子说明,有些约束是对某 些模型元素之间的关系加以限制。为此,OCL必须提供一些方法,引用在一个给定约束中 涉及到的相关模型元素。 非形式地说,OCL应当能够表示从一个语境对象开始,沿着链接得到其他对象,以确 定所需要的模型元素。由于这个过程需要遍历这个对象网的一部分,所以称表示这些对象的 表达式为导航表达式。 我们将使用图12.6中的类图,说明OCL表示法是如何构成导航表达式的。这个图表示 的是一个公司的人事部门所维护的信息模型。图中,公司(company)是作为由许多部门(department)聚合而成的聚合对象而被模型化的。公司中每个雇员(employee)被分配到一个部门。人员(person)类的自反关联表示公司的某些人是被谁管理。限定关联是公司可 以通过对雇员是唯一的工资号(payroll number)访问该雇员。 图12.6人事系统的简单模型 人员类和公司类之间的关联表示了人员为该公司服务的工作关系。作为关联类定义的合 同(contract)这个关系记录着雇用合同的细节。它记录了雇员开始工作的日期(start Date), 并维护与工资级(grade)类的关联。工资级类的实例记录了该组织内具体的工资级的工资 额(salary)。 12.4.1Following links 导航的基本形式是从一个对象到另一个对象的链接,每个链接都是某个关联的一个实 例。所以导航可以通过标明被遍历的关联来描述。 穿过一个关联的导航是用在语境对象名之后,用前面对属性使用过的点表示法,添加一 个圆点,再写上该关联端的远端的角色名表示。这个表达式的值是通过这些指明的链接,当 前链接到该语境对象的对象集合。 例如,给定图9.6所示的类和关联,下述表达式表示的是在当前时刻在该部门工作的雇 员的集合。 如果一个关联没有角色名,可以用该关联远端的类名代替,但开始字母应当小写。例如, 下述表达式引用的是该公司所有部门的集合。这个例子也说明,对导航表达式而言,聚合和 普通关联并没有什么不同。 如果用类名代替角色名有意思含糊不清的危险,则不能使用类名。例如,如果在一对类 之间有两个关联,则必须在关联端点添加适当的角色名,以无二义地构成所需要的导航表达 式。 12.4.2collection 导航表达式表示的是从语境对象出发,沿着指定的链接得到的对象。但是,依赖于遍历 的关联的重数,这些对象的个数也不相同。 例如,上述两个表达式,一般地将得到一个以上对象,即一个部门的全体雇员和一个公 司的所有部门。相反地,下述表达式表示的是一个雇员所属的部门和该雇员的管理者,在所 给出的关联定义下,不可能返回一个以上对象。 一般地,在OCL中,把可能返回多于一个对象的导航表达式说成是返回一个聚集,而 与聚集相对的简单地说返回单个对象(single objects)。由于每当需要时OCL都允许将单个 对象作为聚集处理,所以考虑导航表达式最简单的方式是,把每个导航表达式都看作一个对 象聚集。在某些情况下,聚集的特性很重要,我们将在12.5节进一步讨论。 12.4.3 导航表达式并不限于沿着一个关联导航。它也可以通过由用点号隔开的角色名或类名的 一个序列,指明更复杂的导航路径。例如,下列表达式表示了为该公司工作的所有雇员。 我们可以设想,这个表达式是用一步一步的方式求值的。首先检出的是该公司的所有部 门组成的聚集,然后接着对每个部门,一一检出在该部门中工作的所有雇员的聚集,这些人 员聚集合并到一起构成一个大聚集,它包括为该公司工作的每一个人。这个大聚集就是这个 表达式返回的值。 12.4.4 限定关联可以像一般关联一样用在导航中,但是它又提供了确定个别对象(individual objects)的附加能力。当导航向着限定符方向进行时,限定关联和非限定关联没有什么不同。 例如,下述表达式表示的是一个人为之工作的那个公司。 而当导航沿相反方向进行时,限定符提供了检出已知工资号的特定雇员的一种方法。下 述表达式检出的雇员,如果存在,其工资号是314159。 这种表示可以与子序列导航或被选出的属性自由组合。例如,下述表达式返回的是工资 号为314159的雇员的管理者。 遍历未指明限定符值的限定关联是可以的。在这种情况下返回的是所有被链接的对象。 例如,下述表达式表示的是公司的所有雇员的聚集。 12.4.5 我们也可以用角色名或类名,像通常那样,从一个关联类的一个实例导航到该关联端点 的对象。例如,下述表达式表示的是一个特定工资级的所有雇员的聚集。 为了沿着另一个方向导航,可以像用角色名那样,用关联类的名称直接导航。例如,下 述表达式表示一个特定雇员的工资级。 12.5 OCL数据类型和操作 OCL导航表达式可以表示单个的对象或一个对象聚集。本节将概述OCL定义的不同数据类型并讨论对每种数据类型提供的某些操作。OCL类型和操作的摘要可以在附录B中找到。 12.5.1 为了描述数据项,OCL定义了基本类型‘Boolean’、‘Integer’、‘Real’和‘String’,以及对这些类型的元素的一些操作。这些基本类型完全是标准的,这里不再深入讨论。 奇怪的是UML规范并没有清晰地说明OCL的基本类型和UML的数据类型之间的关系。特别是OCL中的‘Real’并没有作为UML的数据类型来定义。然而设想这些类型同 样是为了实用目的而定义的是合理的,否则,例如写约束时使用属性值同样不方便。 12.5.2 UML模型中定义的类可以作为OCL约束的类型(type)使用。通过这种方式得到的类 型称为模型类型。与模型类型有关的是模型类型的特性(property),这些特性来自于UML模型的特征(feature)。 首先,UML模型中的类的每个属性定义了模型类型的一个特性。其次,对应于连接到 这个类的每个关联的远端的类,也定义了一个特性。如果该类有角色名,那么就用该角色名 作为这个特性的名称;如果没有,则以该类名作为这个特性的名称。最后是UML模型中的查询操作引起的某些特性。对查询操作需要加以限制,是因为计算OCL表达式的值时,不允许改变该模型的状态。 在OCL中,模型类型的特性的值是在指明该模型类型的对象的表达式后,添加一个圆 点,然后写上该特性的名称来表示的。例如,下述表达式中第一个表示的是一个雇员的年龄 特性,第二个表达式表示的是该雇员的工资额。 在这些例子中,这些特性应用的表达式表示的是单个对象。如果一个特性应用到一个表 示了聚集的表达式,则这只是对于包含在该聚集中的每个对象的特性的值的一种简化表示。 例如,下述表达式表示的是由属于特定部门的所有雇员的名字组成的聚集。 UML模型中定义的枚举也可以在约束中使用。只是需要在所写的枚举字面值前加以枚 举名作为前缀。例如,指明一个特定交通信号只可能是‘红’或‘绿’的约束,用在图8.3中定义的枚举,可以如下写出。 12.5.3collection 假设在图12.6中的模型所描述的组织中定义了一个操作,使部门可以计算部门的工资 账单(bill)。完成此操作的一种方法是构造一个聚集,这个聚集包括了对应于该部门的每个 工作成员的工资级对象,然后将这些对象的每个工资额(salary)属性值相加,得到工资额合计。为了表示该部门所有雇员的工资级对象的聚集,自然会写出下述表达式。 然而,如果该部门包含有两个或多个雇员的工资级是同一个工资级就会产生问题。这 时,对该工资级的每个雇员都会找到一次,这样,同一工资级对象就会被检出多次。现在问 题就产生了,在上述导航表达式返回的聚集中,有多少个该工资级对象的当前值呢? 对这个问题的回答会使所计算的合计工资账单有很大差别。如果这个聚集,像数学中的 集合一样,在其中不可能出现重复对象,那么,不管该部门在同一工资级有多少个雇员,每 个工资级对象只能出一次。这样计算得到的合计工资额显然太低。这里需要代之的是一种能 够包括重复项的聚集形式,使得对有同一工资级的每个雇员,该工资级对象都可以存储一次, 这样就可以计算出正确的合计工资额。这样的聚集称为袋(bag)。 为了处理这类情况,OCL定义了三种不同类型的聚集,集合(set)、袋(bag)和序列(sequence)。在集合中,一个给定的对象只能出现一次,而在袋和序列中可以包含重复对 象。此外,在序列中的元素是按次序安排的。 当遍历一个重数大于1的关联时,导航表达式可能产生一个聚集。由关联的语义,从一 个单个元素导航产生的总是一个集合。如果重复发生,可能是由于原对象多次链接到同一个 对象,这在UML中是不允许的。然而从一个集合导航,使用上面描述的简化符号,一般会 产生一个对象袋。 在上述约束中,导航是从语境对象——部门类的一个实例开始的。应用‘staff’的特性,这个部门产生一个‘person’集合。应用‘contract’的特性到这个person对象集合得到的是contract对象袋。最后每个contract的grade被检出,产生一个grade对象袋。从这个对象袋可以计算出合计工资账单。 这样,OCL的语义保证了该表达式返回所需要的聚集。另一方面,假设需要的是按部 门打印出该部门的不同工资级的 报告 软件系统测试报告下载sgs报告如何下载关于路面塌陷情况报告535n,sgs报告怎么下载竣工报告下载 清单,这时,因为我们并不关心每个工资级有多少位雇 员,集合可能是更适合的聚集类型。为了适应这种情况,OCL提供了如下面描述的把bag转换为set的操作。 12.5.4 OCL定义了针对聚集的操作。‘sum’是这些操作中的一个,它把在该聚集中的所有元 素加到一起,返回一个合计值。使用‘sum’操作,一个部门的合计工资账单可以如下表示。 在OCL中使用?符号,指出这里应用的是一个聚集操作。 另一个常用的操作是‘size’操作,它返回的是聚集的大小。size操作与‘as Set’操作结合,返回的是一个部门内不同工资级的数目。 到目前为止,我们考虑过的导航表达式返回的都是一个聚集,它是由指定的导航得到的 所有对象组成。然而有时却有必要只考虑返回对象的一个子集。例如,一个特定的约束只用 于公司中工资额高于50000镑的雇员,而不能用于所有雇员。 如果可以从一个简单导航返回的较大的聚集中挑选出所需要的雇员,形成一个新的聚 集,就可以处理这个特定的例子。 为了执行这种任务,OCL对聚集提供了‘select’操作。例如,下述导航表达式返回的 是由公司内工资不低于50000镑的雇员组成的聚集。 这个表达式从检索公司所有雇员的简单表达式开始,返回的是雇员集合。然后将select操作用于这个集合,即将布尔表达式应用到这个雇员集合的每个对象,而仅选择使此表达式 为真的那些对象。所选择的这些对象的集合作为整个表达式的结果返回。 这个选择操作表示法包括一个‘局部变量’(‘local variable’)声明,它提供了在这个布尔表达式中导航的语境。在这种情况下,导航所形成的中间聚集是模型类型‘person’的实 例的聚集,所以,这个类型的变量就被定义,并作为其后的布尔表达式的语境对象。这个局 部变量声明和在所嵌套的导航开始的使用,通常并不需要,因为中间聚集的对象类型可以从 整个表达式的第一部分得到。 一个选择(select)操作的结果是一个聚集,它完全可以作为进一步导航的基础。例如, 下述表达式检出的是高收入雇员的管理者,这个例子也说明在选择操作中可以省略局部变 量。 常用的另一个聚集操作是‘collect’操作。这个操作是把导航表达式作为操作的变元, 返回的是由原聚集中的每个对象表达式的值组成的袋。例如,下述表达式返回的是一个部门 的所有雇员的年龄。正像对选择操作一样,这里的局部变量也是可选的,但为了清晰起见, 这里仍然包含了局部变量。 collect操作并不限于调用该模型的操作,如果需要还可以执行附加的计算。例如,下述 表达式使用了collect表达式计算公司所有雇员工资提高10%公司的工资账单。 collect操作特别简单的形式是把一个聚集中所有对象的一个属性的所有值聚集在一起。 在这种情况,可以使用本章已用过的惯用的简化表示形式。下述两个表达式是等价的,它们 返回的都是一个部门中所有雇员的名字。 12.6 约束 导航表达式允许我们写一个表达式,引用存储在模型中的部分数据,这就说明,导航表 达式作为面向UML的查询语言的基础是有用的。但就其自身来说,却不允许我们表述希望 这些数据具有的特性。表述希望这些数据具有的特性正是约束的作用。在OCL中,约束是通过用各种布尔运算符组合导航表达式构成的。 本节描述OCL可能采取的各种形式。首先是一些基本类型的约束,它们可用于构成简 单约束。其次是一些布尔运算符,它们可以用于组合约束,以表达某些更复杂的特性。最后 一种形式可以称为‘迭代约束’:这些约束可以递归地应用到一个聚集的所有元素,相当于 一阶谓词逻辑的量词。 12.6.1 约束的最简单形式是用比较两个数据项的关系运算符构成的约束。在OCL中,对象和聚集都可以用运算符‘=’和‘< >’比较相等或不相等。这些标准运算符可用于测试数值。 在12.3节中已经给出了这种例子。 由于写一个导航表达式就能够引用模型中的任何数据项,所以许多模型相当广泛的特性 只须测试导航表达式的相等或不等,就可以形式地表示,而无须使用任何其他方式。 例如,一个雇员工作的部门,应当是该雇员工作的同一个公司的一个部门这个约束,可 以用断言重新表述为:如果直接从雇员导航到公司,或者间接地从雇员导航到部门,再从该 部门导航到公司,将会达到同一个公司。这两个导航结果的等价性可以表示如下。 相等测试可以用于对象和聚集,另外还有一些基本约束只能应用于聚集。 例如,用‘isEmpty’可以测试一个聚集是否为空。虽然严格地说这是不需要的,因为 断言一个聚集是空和断言它的大小等于零是一样的。一个模型的全称特性,例如,断言所有 雇员的年龄不小于18,常常可以通过定义一个聚集,形式化地表述为:该聚集包括了除这 个特性之外的所有特性并断言这个聚集为空。下述约束给出了表达这个约束的两种等价方 式。 有两个操作允许写出约束,做出有关聚集的成员籍的断言。‘include’操作是:如果指定的对象是一个聚集的成员,则‘inclnde’操作为真。例如,该系统一个基本的完整性特性 是,它的每个雇员的工资级,是与该雇员相链接的工资级集合的一个成员,可以用下述约束 表示。 类似的操作是‘includeAll’操作,但它是以聚集作为它的变元,而不是单个对象。因 此,它相当于聚集的一个子集操作符。正如上述例子一样,这个操作常用于对模型中的不同 关联的一致性做出断言。下述OCL约束指明了一个部门的工作人员全体都是该部门所属公 司的雇员。 12.6.2 约束可以使用这些具有标准意义的Boolean运算符‘and’,‘or’,‘xor’和‘not’组合 构成。12.3节给出的类的不变量是使用‘and’约束的一个例子。 OCL不同于大多程序设计语言在于它定义了一个表示蕴含的布尔运算符。例如,假定 该公司有一项政策,即每位年龄超过50的雇员的工资额最低为25,000镑。这个约束可以用OCL描述如下。 12.6.3 迭代约束与select这样的迭代操作相似,它们都是定义在聚集上的操作符,返回的结果 由应用布尔表达式到该聚集的每个元素所确定。然而与其说它们返回一个新的聚集,不如说 它们返回的是依赖于对每个元素的应用结果的布尔值。 例如,操作符‘forAll’表示的是:如果将它应用于聚集的每个成员,指定的布尔表达 式为真,这个操作符返回真,否则,返回假。‘forAll’的一个简单应用是下述OCL约束, 它指明该公司的每一工资级至少有一位雇员。 与‘for All’互为补充的是操作符‘exist’,它表示的是:如果对该聚集中的至少一个元 素该布尔表达式为真,则返回真;如果对该聚集的所有元素,该布尔表达式均为假,则返回 假。‘exists’的一个简单使用是下述OCL约束,它指明每个部门有一位负责人,其含意是 该部门包含一位雇员,他没有管理者。 你会很容易地以为,为了写一个应用于一个类的所有实例的约束,必须使用‘for All’。 事实上并非如此,因为对于类的约束,就是应用到该类的所有实例。例如,下述约束指明, 对于该公司的每一工资级,该工资级的工资额高于20000镑。 这个例子说明,在简单情况下,为了断言一个给定的特性对该类的所有实例为真,没有 必要形成一个清晰可见的聚集。然而如果必要,可以形成这样一个聚集。OCL还定义了一个‘allInstance’操作,可应用于一个类型的名字,返回的是该类型名字所示意的类型的所 有实例组成的聚集。使用这个操作,上述简单约束可以用下述方式重写。 在这种简单情况下使用‘allInstance’使这个约束比需要的更复杂。然而在有些情况下, 使用‘all Instance’却是必要的。一个常见的例子是一个约束必须系统地比较不同的实例, 或一个类的值。例如,下述约束断言,没有两个工资级它们的工资额属性有相同的值。 这个约束隐含地应用到该工资级类的每个实例;作为通常情况,语境对象是由约束中的 self项引用的。这个约束反复通过应用‘allInstances’所形成的聚集,将语境对象与该类的 每个实例相比较。这个约束的第2行指明了被测试的条件,即该类的两个不同的实例不可能 定义相同的工资额。 12.7 构造型化的约束 约束通常用于指明不能在图形上表示的类和类的操作的特性。这些特性包括对该类的实 例的可能状态和该类所定义的操作的限制。 系统地应用这些类型的约束,提供了一种指明类的特性的一般方法。这种方式在形式规 约语言中使用得相当广泛,甚至像Eiffel这样的程序设计语言也使用了这种方式。为了支持 这种方式,UML定义了构造型,标明约束的不同使用。 12.7.1 类不变量是类的性质,它指的是对该类的所有实例,在所有时间,该不变量为真。在某 种意义上,本章前面所述的所有约束,都可以看作为不变量,因为它们指明的都是要求类的 实例具有的特性。但是术语‘不变量’通常仅用于限制一个类的属性的可能值的约束。 例如,图12.1中用来指明储蓄账户的余额必须在0到25000镑范围内,是简单不变量的一个典型例子。它既可以作为简单约束如下述方式写出,或者作为结构型约束用如图12.7的方式表示。使用注解(note)容易使类图显得凌乱,所以在许多情况下,文本形式可能更 可取,而表示不变量的这两种方式之间的不同只是风格上的差异。 图12.7 使用结构型约束的类的规约 12.7.2 定义类的不变量并不能保证该类的操作能够使该不变量保持不变。例如,如果储蓄账户 的取款操作允许提取任何数目的金额,那么指明余额必须大于0的不变量很容易失效。 前置条件和后置条件是特别为操作而使用的约束。正像名称所示,前置条件是在一个操 作调用时必须为真的事情,而后置条件是当操作完成时必须为真的事情。使用前置条件和后 置条件约束应当做到,如果它们在相应的时间都为真,那么该类的不变量在该操作完成时仍 然为真。 前置条件通常表示的是对一个类的实例的属性和指定的操作的实际参数的约束。例如, 如果储蓄账户的取款操作不引起账户透支,那么取款金额必须小于该账户的当前余额。形式 地讲,就是这个操作的前置条件。在图12.7中是用构造型标注的。 后置条件典型地是指明操作的结果,它通过比较该操作执行前和执行后的属性值表示。 在取款操作中,后置条件是,该余额应当是该账户的余额减去该操作的实际参数中指明 的金额。在图12.7中也是用相应的构造型标注的。 形式化地写后置条件时有一个表示法问题。在约束中一个属性的名称表示的是该属性的 当前值。后置条件是在一个操作执行之后计值的,这样,在取款操作的后置条件中的余额属 性表示的是,取款操作进行之后的余额。为了形式地表述后置条件,需要将这个当前值与该 操作被调用前的该属性值比较。在OCL中,正像图12.7那样,这个值是用在属性名后写一个@yre符号来标注的。 操作规约除了可以在图中表示外,也可以用文本形式给出。然而这时约束的语境不是给 定的类的一个对象,而是类的一个操作,并且要使用标号‘pre’和‘post’标注这些约束所 起的结构型作用。下面给出的约束,等价于图12.7中给出的约束,并说明了这种文本表示法。 12.7.3 使用前置条件和后置条件的操作规约有时可以看作是在该操作的调用者和操作实现之 间建立的一种契约。在这个模型中,操作的调用者有责任确保,如果操作的参数值会使前置 条件为假,该操作不会被调用。该操作的实现做出的相应保证是,如果前置条件为真,那么 该对象状态的任何交替都会确保,在该操作结束时该后置条件为真。 如果这个契约的这两个方面都满足,该类的不变量也会继续保持。这就产生一个问题, 如果这个契约被破坏会发生什么:依赖于是前置条件未能满足,还是后置条件失败,情况是 不同的。 一个操作不能控制传给它的是怎样的参数值。如果它被用无效参数调用,那就没有办法 确保在操作完成时它的后置条件会被满足。这种情况常常作为运行时错误考虑,类似于当试 图用0作除数时发生的错误。当前置条件不满足时,该系统的状态成为不确定的,该操作可 能表现出任何行为。 通常对于有前置条件的操作,在运行该操作体之前必须核实满足该前置条件。如果不满 足,可以采取适当的动作,譬如说抛出一个异常。一般地,对这种不满足约束条件的错误引 起重视是较好的策略,而不要不顾后果地继续下去而可能使系统数据变得面目全非。 另一方面,如果前置条件满足而后置条件不满足,只能说是该操作实现中存在错误。在 这种情况下补救的办法就是改正程序设计的错误。 12.8 约束和泛化 泛化关系不会引发对象之间任何可导航的关系,所以在约束中并不占有明显的重要地 位。 然而在某些情况,需要约束引用涉及到的对象在运行时的类型时,泛化可能会使写出的 约束非常复杂。 考虑图12.8中所示的多态的基本情况。这里客户可以有多个不同类型的账户。假定银 行对其客户有一个限制,在这些账户中至少有一个账户必须是活期账户(current account)。 图12.8 持有的多态账户 自然会想用约束形式化地表述这个限制。但是我们却不能用在本章中到目前为止介绍过 的OCL表示法表示这个限制。在图12.8所示的一个客户对象的语境中,导航跨过的关联提 供给我们的只是一个账户对象的聚集:我们需要另外某种方式,确定这些对象运行时的类型。 OCL定义了‘oclIsTypeOf’操作,它以类型作为它的变元,并且只有当该对象的实际 类型与指明的类型相等时才为真。使用这个操作,所要求的约束可以用下述方式写出: 约束中运行时的类型信息的另一种用法是用文本形式表达模型中并行结构之间必须保 持的约束。例如,图12.9所示的情况,该银行有两类不同客户并对每类客户提供了适应其 特殊需要的不同的账户类型。 在这种情况下,常常要限制这些子类之间的链接。例如,该银行要求只有个人 (individuals)才能持有个人(person)账户,只有公司才能持有业务账户。这个要求可以 用两个低层关联取代‘Hold’关联表达,但是正像8.5节讨论的,一般希望的是要保持高层 关联。因此,用另一种方式定义一个约束,表达要求图12.9中的实例具有的特性。 图12.9 并行泛化层次 所要求的这个约束可以用‘oclType’操作表示。它表示的是,当此操作应用于一个对 象时即返回该对象的类型。使用这个操作,下述约束断言,个人持有的所有账户必须是活期 账户。 12.8小结 ?约束是关于模型元素的断言,它指明了一个模型的实例必须具有的性质。 ?UML定义了一些可以用图形方式表示的标准约束。为了写出更一般的约束,UML定义了对象约束语言OCL。 ?OCL中的约束是一个布尔表达式,它断言一个指定模型元素或模型元素之间关系的 若干特性。 ?每个约束都有一个语境,它表示的是被约束的模型元素,或者说该约束是就被约束的 模型元素来表达的。约束的语境是一个类或一个操作。 ?导航表达式允许约束引用直接或间接地链接到该语境的对象,这就使约束能够描述对 象之间的关系。 ?导航表达式可以表示或返回单个对象或对象聚集。聚集可以是集合、袋、或者序列。OCL对聚集定义了多种不同的聚集操作。 ?约束由使用布尔运算符的基本约束和类似于限定符的迭代约束构成。 ?类的规格说明通常用构造型约束写出。不变量描述类的属性,前置条件和后置条件说明类的操作。 12.10 习题 12.1 画一个对象图,表示某个储户和若干个账户实例违反了图12.2中给出的xor约束。 12.2 画一个对象图,表示某个人和若干个委员会实例违反了图12.3给出的子集约束。 12.3 写一个OCL约束,具有与图12.2所示的子集约束同样的意义。给出一个一般规则, 说明如何用OCL约束替换子集约束。 12.4 写一个OCL约束,具有与图12.3所示的xor约束有同样的意义。给出一个一般规 则,说明如何用OCL约束替换xor约束。 12.5 画一个图12.4中对象图所暗示的类图。不使用储户约束,能够表示同一个储户持 有一个账户和多个属于该账户的借记卡这个要求吗? 12.6 在图12.4所指语境中,假定该银行发行一种只允许持有储蓄账户的储户才可以使 用的借记卡。这种限制能够用子集约束表示吗?给出支持你的回答的理由。 12.7 图12.6中的图表述了公司的雇员可以有0或1个管理者。假定实际上该公司运行着一个精确的流水线管理系统,因而每个雇员除这个管理主管外,有而且只有一位管理者。 修改这个图使之可以更准确地描述这个新情况。 12.8 根据12.6写一个OCL导航表达式,描述下列对象。如果必要,添加适当的角色名 以避免二义性。 (a) 具有工资号为123456的雇员所在的工作部门; (b) 一位雇员的管理者工作的部门; (c) 在一个给定的部门有指定工资级的雇员; 12.9 写一个OCL约束表达图12.6中类图的下列特性 (a) 雇员的管理者工作的部门同时该管理者又是该部门的雇员; (b) 管理者的收入高于他们所管理的人员; (c) 每个部门都有一位最低收入最少为100,000镑的工作人员。 12.10 下面所写的约束的意图是,针对图12.6的模型表述没有人能够是他们自己的管理 者,它错在哪里? 写出一个正确的OCL约束表述此要求。 12.11 针对图12.1中的类图写一个OCL约束,表述客户持有的每个账户有大于100镑的 余额。 12.12 说明如何用OCL表述图12.6中的关联的重数。 12.13 针对图8.22中的类图写一个导航表达式,表示一个给定的人工作的公司。用这个 导航表达式写一个OCL约束,指明一个人只能为一个公司工作。 12.14 针对图5.6写一个OCL约束,表述当前预约日期必须与预约系统对象中存储的当 前日期完全相同。 12.15 针对图8.43中的类图写一个导航表达式或约束表达: (a)一位学生选修的课程集合; (b)一位学生选修的一门特定课程的考试分数; (c)一位学生选修的所有课程的平均分数; (d)一位学生考试及格的课程; (e)一张给定的成绩单上的学生集合; (f)一张给定的成绩单只登记一门课程的考试分数。 12. 16 在图12.6中增加一个关联,使该模型能够记录每个部门的负责人的详细信息。写 一个OCL约束,表达每个部门的负责人必须是该部门的人员。 12.17 针对图12.7写一个适合于储蓄账户类的存款操作的前置条件和后置条件。 12.18 针对图12.9写一个在客户类语境下的一般约束,表达对不同类型的账户能够持有 的账户的限制。
本文档为【UML约束】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
该文档来自用户分享,如有侵权行为请发邮件ishare@vip.sina.com联系网站客服,我们会及时删除。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
下载需要: 免费 已有0 人下载
最新资料
资料动态
专题动态
is_180829
暂无简介~
格式:doc
大小:232KB
软件:Word
页数:33
分类:生活休闲
上传时间:2017-09-25
浏览量:80