目标 1》确定与当前迭代相关的概念类 2》创建初始的领域模型 3》为模型建立适当的属性和关联。
简介 领域模型是OO分析中最重要的和经典的模型。它阐述了领域中的重要概念。领域模型可以作为设计某些软件对象的灵感来源,也将作为在案例研究中所探讨的几个制品的输入。本章还将展示UML表示法上OOA/D知识的价值。基本表示法非常容易,但是对于有用模型的一些深奥的建模准则,则需要数周或数月才能掌握。
和敏捷建模和UP精神中的所有事物一样,领域模型也是可选制品。在图9-1中所示的UP制品相互影响力中强调了领域模型。领域模型的范围限定于当前迭代所开发的用例场景,领域模型能够被不断地演进用以展示相关的重要概念。相关的用例概念和专家的观点将作为创建领域模型的输入。反过来,该模型又会影响操作契约、词汇表和设计模型,尤其是设计模型中领域层(domain layer)的软件对象。
示例 图9-2展示了以UML类图(class diagram)表示法绘制的部分领域模型。对领域模型应用UML类图表示法会产生概念透视图(conceptual perspective)模型。 确定一组概念类是OO分析的核心。如果能够通过熟练和快速(就是说,每次早期迭代不超过几个小时)的调查来完成这项工作,那么通常会在设计过程中得到回报,因为领域模型能够支持更好的理解和沟通。准则:避免瀑布思维倾向,为完成详尽或“正确”的领域模型而进行大量建模工作。这些方式都应避免,并且这种过量的建模工作反而会导致分析停滞,这种调查几乎不会有什么回报。
什么是领域模型 这一精髓的面向对象分析步骤是从领域到重要概念或对象的分解。领域模型(domain model)是对领域类或现实世界中对象的可视化表示。领域模型也称为概念模型、领域对象模型和分析对象模型。定义:在UP中,术语"领域模型"指的是对现实世界概念类的表示,而非软件对象的表示。该术语并不是指用来描述软件类、软件架构领域层或有职责软件对象的一组图。UP对领域模型的定义是,可以在业务建模科目中创建的制品之一。更准确地讲,UP领域模型是UP业务对象模型(BOM)的特化,“专用于解释业务领域中重要的‘事物’和产品”也就是说,领域模型专注于特定领域。更为广泛的BOM是扩展的、通常十分庞大和难以创建的多领域模型,BOM覆盖整个业务及其所有子域,本章并不涵盖这部分内容,并且也不提倡创建BOM(因为需要在是实现前进行大量建模)。
应用UML表示法,领域模型被描述为一组没有定义操作(方法的特征标记)的类图)(class diagram)。它提供了概念透视图。它可以展示:
- 领域对象或概念类。
- 概念类之间的关联
- 概念类的属性。
定义:为什么把领域模型称为“可视化字典”
请仔细观察图9-2.看看它是如何对领域词汇或概念进行可视化和关联的。领域模型还显示了概念类的抽象。因为这种抽象可以表达其他大量事物,例如登陆、销售等。
领域模型(使用UML表示法)描述的信息也可以采用纯文本方式(UP词汇表)表示。但是在可视化预言中更容易理解这些术语,特别是它们之间的关系,因为我们的思维更擅长理解形象的元素和线条连接。因此,领域模型是可视化字典,表示领域的重要抽象、领域词汇和领域的内容信息。
定义:领域模型是软件业务对象图吗 如图9-3所示,UP领域模型是对所关注的现实世界领域中事物的可视化,而不是诸如Java或C#类的软件对象,或有职责软件对象(参见图9-4)。因此以下元素不适用于领域模型:
- 软件制品,例如窗口或数据库,除非已建模的领域是针对软件概念的,例如图形化用户界面的模型。
- 职责或方法。
定义:“领域模型”的两个传统含义 在UP及本章中“领域模型”是现实世界中对象的概念透视图,而非软件透视图。但这一术语是多义的,也用来表示“软件对象领的领域层”也就是说,在表示层或UI层之下的软件对象层是由领域对象(domain object)组成的--领域对象是表示问题领域空间事物的软件对象,并且与“业务逻辑”或“领域逻辑”方法相关。我通常会使用领域层(domain layer)来表示领域模型针对软件的第二个含义,因为领域层也十分通用。
定义:什么概念类 领域模型阐述领域中的概念类或词汇。概念类是思想、事物或对象。更正式的讲,概念类可以从其符号、内涵和外延来考虑。
- 符号:表示概念类的词语或图形
- 内涵:概念类的定义
- 概念类所适用的一组示例
定义:领域模型和数据模型是一回事吗 领域模型不是数据模型(通过对数据模型的定义来表示存储于某处的持久性数据),所以在领域模型里,并不会排除需求中没有明确要求记录其相关信息的类(这是对关系数据库进行数据建模的常见标准,但与领域建模无关),也不会排除没有属性的概念类。例如,没有属性的概念类是合法的,或者在领域内充当纯行为角色而不是信息角色的概念类也是有效的。
动机:为什么要创建领域模型 领域模型和领域层使用相似的命名可以减少软件表示与我们头脑中的领域模型之间的差异。 动机:降低与OO建模之间的表示差异 这是OO的关键思想:领域层软件类的名称要源于领域模型中的名称,以使对象具有源于领域的信息和职责。图9-6阐述了这一思想。这样可以减少我们的思维与软件模型之间的表示差异。同事,这并非只是哲学上的考究--对时间与金钱也会有实际的影响。
准则:如何创建领域模型 1、寻找概念类 2、将其绘制为UML类图中的类 3、添加关联和属性
准则:如何找到概念类 既然领域模型表示的是概念类,那么关键问题是如何才能找到概念类。找到概念类的三条策略 1、重用和修改现有的模型。这是首要、最佳且最简单的方法,如果条件许可,通常从这一步开始。在许多常见领域中都存已发布的、绘制精细的领域模型和数据模型(可以修改为领域模型),这些领域包括库存、金融、卫生等等。我所参考的书籍包括Martin Fowler的《分析模式》(Analysis Patterns)、David hay的Data Model Patterns和Len Silverston的Data Model Resource Book(卷1和卷2) 2、使用分类列表 3、确定名词短语 重用现有的模型是最好的办法,但超出了本书的范围。第二个方法(使用分类列表)也很有效。 方法2:使用分类列表 我们可以通过制作概念类候选列表来开始创建领域模型。参看表9-1。 方法3:通过识别名词短语寻找概念类 在【Abbot83】中所建议的另一种有效(因为简单)技术是语言分析(linguistic analysis),即在对领域的文本性描述中识别名词和名词短语,将其作为候选的概念类或属性。 准则:使用这种方法时必须小心。不可能存在名词到类的映射机制,并且自然语言中的词语具有二义性。领域模型是重要领域概念和词汇的可视化。那么从哪里找到这些术语?其中某些术语来源于用例。另外一些术语则源于其他文档,或是专家的想法。无论如何,用例都是挖掘名词短语的重要来源之一。
示例:寻找和描绘概念类 参见图9-7 图9-8
准则:敏捷建模--绘制类图的草图 注意图9-8中UML类图的这种草图风格,让类框的底部和右侧呈开发状态。这样可以在发现新元素时对类方便地进行扩展。
准则:敏捷建模--是否要使用工具维护模型 敏捷模型在创建后通常很快就被抛弃了(即使这样,如果你使用白板的话,我还是建议用数据相机拍下来)。基于这种观点,则没有理由去维护或更新这些模型。但是这也不意味着更新模型就是错的。通常,进化的软件领域层对大部分重要术语会给予提示,而且长生命期的OO分析领域模型不会增加价值。
准则:报表对象--模型中是否要包括“票据”
准则:像地图绘制者一样思考;使用领域术语 地图绘制者的策略既可用于地图,也可以用于领域模型。准则: 以地图绘制者的工作思维创建领域模型:1》使用地域中现有的名称 2》排除无关或超出范围的特性 3》不用凭空增加事物
准则:如何对非现实世界建模 有些软件系统的领域与自然领域或业务领域几乎没有类似之处,例如电信软件。然而还是有可能为这些领域创建领域模型。此时需要高度的抽象,对常见的非OO设计进行回归,并且认真吸取领域专家所使用的核心词汇和概念。
准则:属性与类的常见错误 在创建领域模型时最常见的错误是,把应该是概念类的事物表示为属性。 准则:如果我们认为某概念类X不是现实世界中的数字或文本,那么X可能是概念类而不是属性。
准则:何时使用“描述”类建模 描述类(description class)包含描述其他事物的信息。在[Coad92]中,这种类通常被命名为项目-描述符模式。图9-9 准则:何时需要描述类 在以下情况下需要增加描述类(例如,ProductDescription)
- 需要有关商品或服务的描述,独立于任何商品或服务的现有实例
- 删除其所描述事物(如Item)的实例后,导致信息丢失,而这些信息是需要维护的,但是被错误地与所删除的事物关联起来。
- 减少冗余或重复信息。
图9-10
关联 找到并表示出关联是有助的,这些关联能够满足当前所开发场景的信息需求,并且有助于理解领域。关联(association)是类(更精确地说,是这些类的实例)之间的关系,表示有意义和值得关联的连接(图9-11)在UML中,关联被定义为“两个或多个类元之间的语义联系,涉及这些类元实例之间的连接”。
准则:何时表示关联 关联表示了需要持续一段时间的关系,根据语境,可能是几毫秒或数年。换言之,我们需要记录哪些对象之间的关系? 由于领域模型是从概念角度出发的,所以是否需要记录关联,要基于现实世界的需要,而不是基于软件的需要,尽管在实现过程中,会有出现大量对关联的需要。图9-11关联。 准则:在领域模型中要考虑如下关联:1》如果存在需要保持一段时间的关系,将这种语义表示为关联(“需要记住”的关联)2》从常见关联列表中派生的关联。
准则:为什么应该避免加入大量关联 在具有n个节点的图中,节点间有(n*(n-1))/2个关联,这可能是个非常大的数值。连线太多会产生“视觉干扰”,使图变的混乱,所以要谨慎地增加关联线。使用本章准则所建议的标准,并且重点关注“需要记住”的关联。
观点:关联是否会在软件中实现 在领域建模过程中,关联不是关于数据流、数据库外键联系、实例变量或软件方案中的对象连接语句;关联声明的是针对现实领域从纯概念角度看有意义的关系。也就是说,这些关系的大部分将作为(设计模型和数据模型中的)导航和可见性路径在软件中加以实现。但是,领域模型不是数据模型;添加关联是为了突出我们对重要关系的大致理解,而非记录对象或数据的结构。
应用UML:关联表示法 关联被表示为类之间的连线,并冠以首字母大写的关联名称。见图9-12。警告:阅读导向箭头对模型来说并不具有特别意义,只是对阅读图的人有所帮助。
准则:在UML中如何对关联命名 以“类名-动词短语-类名”的格式为关联命名,其中的动词短语构成了可读的和有意义的顺序。诸如“拥有”或“使用”这样简单关联名称通常是拙劣的,因为这种名称不会增强我们对领域的理解。关联名称应该使用首字母大写的形式,因为关联表示的是实例之间链接的类元。在UML中,类元应该首字母大写。以下是复合性关联名称的两种常见并且等价的合法格式:1》Records-current 2》RecordsCurrent
应用UML:角色 关联的每一端称为角色(role)。角色具有如下可选项: 1》多重性表达式 2》名称 3》导航 多重性将在后面讨论。
应用UML:多重性 多重性(multiplicity)定义了类A有多少个实例可以和类B的一个实例关联(见图9-13)。在图9-14中将给出一些多重性表达式的例子。多重性的值表示在特定时刻(而不是某个时间跨度内)有效关联的实例数量。多重性的值和建模者和软件开发者的关注角度有关,因为它表达了将要(或可能)在软件中反映的领域约束。见图9-15.
应用UML:两个类之间的多重关联 在UML类图中,两个类之间可能会有多重关联,这并不罕见见图9-16。
准则:如何在常见关联列表中找到关联 通过使用表9-2中的列表来开始添加关联。该列表中包含值得考虑的常见类别,对业务系统而言更是如此。
示例:领域模型中的关联 参见图9-17和图9-18。
属性 确定概念类的属性是有助的,能够满足当前所开发场景的信息需求。属性(attribute)是对象的逻辑数据值。
准则:何时展示属性 当需求(例如,用例)建议或暗示需要记住信息时,引入属性。
应用UML:属性表示法 属性在类框图的第二格中表示(参见图9-19)。其类型和其他信息是可选的。在UML中,属性的完整语法是: visibility name:type multiplicity = default {property-string},对该表达式译为中文是: 可见性 名称:类型 多重性=默认值 {特性表} 参见图9-20。依照惯例,大部分建模者会假设属性的可见性为私有的(-),除非有另外表示,所以我通常不会显式地标出可见性符号。 {readOnly}大概是属性的{property-string}部分最常用的值。 多重性用来指示可能出现的值,或者可以填充到(集合)属性中的对象数量。例如,许多领域要求知道某人的名和姓,但是中名是可选的。表达式middleName:[0..1]表示可选值,该属性可以出现0或1个值。准则:在哪里记录属性需求 有些建模者认可只在领域模型中保留这种规格说明,但是我发现这是一种错误倾向,并且被扩散了,因为人们往往不去仔细查看领域模型或需求指导。人们也通常不会维护领域模型。 我建议把所有这种属性需求置于UP词汇表(UP词汇表可充当数据字典)。可能我已经花费了一个小时和领域专家一起画出领域模型的草图;之后,我可以花费15分钟浏览这个草图并将其中表示的属性需求转移到词汇表中。另一种方法是,使用工具将UML模型和数据字典统一起来;这样所有属性会自动显示为数据字典的元素。 导出属性 Sale中的total属性可以从SalesLineItems中的信息计算或导出。当我们需要表达:这是重要属性,但是导出的,那么可以使用UML的约定:在属性名称前加以"/"符号。 收银员输入的数量可以被记录为SalesLineItem的属性(参见图9-21)。但该数量可以从关联的多重性的实际值计算出来,所以被表示为导出属性,即可以由其他信息导出的属性。
准则:什么样的属性类型是适当的 关注领域模型中的数据类型属性 通俗的说,大部分属性类型应该是“简单”数据类型,例如数字和布尔。通常,属性的类型不应该是复杂的领域概念,例如Sale或Airport。图9-22中Cashier类的currentRegister属性是不合适的,因为其类型是Register,并不是简单数据类型(例如Number或String)。表达Cashier使用Register的最有效的做法是使用关联,而不是使用属性。 准则 领域模型中属性的类型更应该是数据类型(data type)。十分常见的数据类型包括:Boolean,Date(或DateTime)、Number、Character、String(Text)和Time。其他常见的类型还有Address、Color、Geometrics(Point、Rectangle)、Phone Number、Social Security、Number、Universal Product Code(UPC)、SKU、ZIP或者是邮政编码、枚举类型。 准则:通过关联而不是属性来表示概念类之间的关系。参见图9-23。
数据类型 领域模型中的属性通常应该是数据类型(data type)。一般来说,数据类型是“基本”类型,诸如数字、布尔、字符、字符串和枚举(例如,尺寸={小,打})。更准确地讲,UML术语中的数据类型指的是一组值,而这组值的标识本身不具有任何含义(在我们的模型或系统的语境下)。换言之,对数据类型的等价性检验不是基于标识,而是根据值来判断的。 数据类型值往往是恒定不变的,例如,Integer的实例"5"是不变的;Date的实例“Nov.13,1990”可能也是不变的。而Person实例的lastName属性可能对不同人有不同的值。 从软件角度出发,很少会对Integer或Date实例的存储地址(标识)进行比较,一般是对值进行比较。另一方面,即使Person的不同实例具有相同的属性值,但还是可以区分和比较其存储地址,因为其唯一标识的重要性。
观点:代码中的属性 在领域模型中建议属性主要为数据类型,并不意味着C#或Java的属性只能是简单的基础数据类型。领域模型是概念透视图,不是软件透视图。在设计模型中,属性可以是任何类型。
准则:何时定义新的数据类型类 NextGen POS系统需要itemID属性,可以作为Item或ProductDescription的属性。注意,该属性看起来只是数字或字符串,例如,itemID:Integer或itemID:String。 但实际上,该属性并不仅仅是字符串或数字(商品项目标识符具有子域),更有效的做法是在领域模型中加入类ItemID(或者ItemIdentifier),并且将这个类作为itemID属性的类型。例如,itemID:ItemIdentifier。表9-3提供了一些准则,指明何时需要在模型中加入数据类型。
应用UML:在何处描述这些数据类型类 在领域模型里,ItemID类应该表示为单独的类吗?这取决于你想要在图中强调的事物。既然ItemID是数据类型(实例的唯一标识不用于等价性检验),那么可能只会表示在类框的属性分格中,如图9-24。采用哪种解决方式取决于如何使用作为沟通工具的领域模型以及领域里概念的重要性。
准则:任何属性都不表示外键 领域模型里的属性不应该用于表示概念类的关系。违反这一原则的常见情况是像在关系数据库设计中那样增加一种外键属性,用以关联两个类型。参见图9-25。可以用许多方法来表示对象之间的关系,外键就是其中一种方法,我们将推迟到设计时在决定如何实现对象关系,以避免设计蠕变(design creep)。
准则:对数量和单位建模 大部分用数字表示的数量不应该表示为纯数字。应该给这些数量加上单位,并且通常还需要知道单位之间的转换关系。领域模型(和软件)应该具备处理数量的技巧。一般情况下,可以把数量表示为单独的Quantity类,并且关联到Unit类。通常可以对Quantity加以规格说明。参见图9-26。
实例:领域模型中的属性 参见图9-27、 9-28
结论:领域模型是否正确 没有所谓唯一正确的领域模型。所有模型都是对我们试图要理解的领域的近似。领域模型主要是在特定群体中用于理解和沟通的工具。有效的领域模型捕获了当前需求语境下的本质抽象和理解领域所需要的信息,并且可以帮助人们理解领域的概念、术语和关系。
过程:迭代和进化式领域建模 在迭代开发中,我们会通过若干迭代对领域模型进行增量地演进。在每个迭代中,领域模型都会限定于之前和当前要考虑的场景,而不是膨胀为瀑布风格的“大爆炸”模型,以过早试图捕获所有可能的概念类和联系。因此,只创建部分领域模型反映这一情形,而不涉及其他。 准则:避免瀑布思维倾向,为完成详尽或“正确”的领域模型而进行大量建模工作,这些方式都应避免,这种过量的建模工作反而会导致分析停滞,这种投入几乎不会有什么回报。每次迭代的领域模型建模时间不超过几个小时。
UP中的领域模型 如表9-4的建议所示,UP中的领域模型通常开始和完成于细化阶段。
UP业务对象模型与领域模型 UP领域模型是较为少见的UP业务对象模型(BOM)的正式变体。不要与其他对BOM的定义混淆,UP BOM是一种描述整个业务的企业模型。BOM可以用来进行业务过程或再工程,而不依赖于任何软件应用。引证如下:【UP BOM】作为抽象,描述的是业务人员和业务实体应该怎样关联,以及它们如何协作以完成业务。 BOM使用不同的图(类图、活动图和顺序图)来阐述整个企业是如何运转的(或应该如何运转)。BOM通常有助于进行企业范围的业务过程工程,而在创建单个软件应用时并不常见。因此,UP定义了领域模型,作为BOM的常用制品子集或特化。引证如下:你可以选择开发“非完整的”业务对象模型,重点解释领域中的重要“事物”和产品。【...】这些都成为领域模型。