作为OOAD中的第二步,概念模型的识别显得比用例识别更加困难。
为什么要创建领域模型
降低与OO建模之间的表示差异。
领域层软件类的名称要源于领域模型中的名称,以使对象具有源于领域的信息和职责。
打个比方,你可以用一长串0和1来表示“薪水册”,可是这种软件表示与我们脑中的薪水册领域模型之间存在巨大的差异,这将影响我们对软件的理解和修改。而OO建模则可以减小这一差异。
如何创建领域模型
那又如何创建领域模型呢?
可以通过以下三个步骤:
- 寻找概念类
- 将其绘制为UML类图中的类
- 添加关联
- 添加属性
如何找到概念类
1)重用和修改现有的模型。
这是首要、最佳且最简单的办法。可以从已发布的领域模型和书籍中获得。
2)使用分类列表
示例:
(图二)
3)确定名词列表
在对领域的文本性描述中识别名词和名词短语,将其作为候选的概念类或属性。
缺点:自然语言的不精确性,不同名词短语可能表示同一概念类或属性,此外可能还有歧义。
建议与概念类分类列表一同使用。
在实践中,在发现概念类时,一般直接为其绘制UML类图。
了解了几种识别概念类的方法,我们接下来讨论过程中可能出现的问题。
1)最常见错误:把应该是概念类的事物表示为属性。
准则:如果我们认为某概念类X不是现实世界中的数字或文本,那么X可能是概念类而不是属性。
考虑一下航空预定领域。destination应该作为Flight的属性,还是作为单独的概念类Airport?
(图三)
在现实世界里,目的地机场不会被看作是数字或文本,而是一占据大规模空间的事物。因此,Airport应该是个概念,而不是属性。
2)缺少描述类
描述类包含描述其他事物的信息。例如,ProductDescription记录Item的价格、图片和文字描述。
为什么使用描述类?
假设:雀巢咖啡,大受欢迎,销售一空。这就意味着雀巢咖啡的所有Item实例都从计算机存储器中被删除。这时如果有人问:雀巢咖啡多少钱一盒?那将没法回答。因为价格是记录在实例上的,而这些实例都已经被删除。由此可以看出,需要其他事物来记录雀巢咖啡的描述(规格说明)。
(图四)
又比如,虹桥机场每天有很多航班,同一架飞机有多个航线,但其一架飞机只有一个飞机号码。如果仅仅有两个概念类Flight和Airport,假设有一天天降大雾,所有航班取消,我们删除了所有Flight记录。这时如果我们想知道是否存在号码为12345的一架飞机,那我们将无法查到。由此可以看出,我们还需要一个描述类FlightDescription。
何时需要?
1. 需要有关商品或服务的描述,独立于任何商品或服务的现有实例。
2. 删除其所描述事物(如Item)的实例后,导致信息丢失,而这些信息是需要维护的,但是被错误地与所删除的事物关联起来。
3. 减少冗余或重复信息。
关联
什么是关联?
关联是类(类的实例)之间的关系,表示有意义和值得关注的连接。
(图五)
关联名
关联名来描述一个关联的本质。
角色(Role)
用来描述离角色名较近一端的类在另一端的类面前所呈现的面貌。
何时表示关联?
1. 如果存在需要保持一段时间的关系,将这种语义表示为关联(“需要记住”的关联)。
2. 从常见关联列表中派生的关联。
准则:要避免在领域模型中加入太多的关联。
在领域建模过程中,关联不是关于数据流、数据库外键联系、实例变量或软件方案中的对象连接的语句;关联声明的是针对现实领域从纯概念角度看有意义的关系。
在UML中如何对关联命名
以“类名-动词短语-类名”的格式为关联命名,其中的动词短语构成了可读的和有意义的顺序。
图五对应于:VideoStore Stocks Video
多重性
多重性定义了类A有多少个实例可以和类B的一个实例关联。(见图五)
多重性的值表示在特定时刻(而不是在某个时间跨度内)有效关联的实例数量。
(图六)
多重性是和语境有关的。
两个类之间的多重关联:
(图七)
常见关联列表
(图八)
一个例子
属性
在UML中,一个属性的完整语法是:visibility name : type multiplicity = default {property-string},即可见的名称 : 类型 = 默认值 {性质}。
什么是属性?
属性是对象的逻辑数据值。
何时展示属性?
当需求(例如,用例)建议或暗示需要记住信息时,引入属性。
(图九)
导出属性(derived attribute):可以由其他信息导出的属性。
准则:大部分属性类型应该是“简单”数据类型,例如数字和布尔。通常,属性的类型不应该是复杂的领域概念,例如Sale或AirPort。
准则:领域模型中属性的类型更应该是数据类型。
准则:通过关联而不是属性来表示概念类之间的关系。
(图十)
领域模型是概念透视图,不是软件透视图。在设计模型中,属性可以是任何类型。
准则:任何属性都不表示外键。
(图十一)