[领域]一个简单的UML应用题

UML是一个语义丰富的建模语言,但是,在实际的使用过程中,出现了很多滥用和误用的情况。如果,你只是关心使用UML的最少集合进行建模,是可以的(我个人也比较喜欢这种做法,按照28原则,我们确实可以这么做)。但是,前提是,使用者至少应该掌握或者了解UML的语义中已经包含了哪些内容了,而不是加上过多的“我认为”,“我觉得”这样的扩展用法,如果是这样,那么UML的存在意义已经不大了。 有感于此,我在技术研究中心BBS上给大家出了这样一道题,在跟很多人交流后,我把我的答案贴出来,供大家参考。如果感兴趣或者有不同的意见,可以到BBShttp://219.146.159.167/forum/index.jsp)上继续进行讨论。

问题:

现在是分析阶段,请用UML类图表示出 “客户” “订单” “订单行” 之间的关联关系。

我的答案:

<shapetype id="_x0000_t75" stroked="f" filled="f" path="m@4@5l@4@11@9@11@9@5xe" o:preferrelative="t" o:spt="75" coordsize="21600,21600"><img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/xiaosun/answer1.JPG"><stroke joinstyle="miter"></stroke><formulas><f eqn="if lineDrawn pixelLineWidth 0"></f><f eqn="sum @0 1 0"></f><f eqn="sum 0 0 @1"></f><f eqn="prod @2 1 2"></f><f eqn="prod @3 21600 pixelWidth"></f><f eqn="prod @3 21600 pixelHeight"></f><f eqn="sum @0 0 1"></f><f eqn="prod @6 1 2"></f><f eqn="prod @7 21600 pixelWidth"></f><f eqn="sum @8 21600 0"></f><f eqn="prod @7 21600 pixelHeight"></f><f eqn="sum @10 21600 0"></f></formulas><path o:connecttype="rect" gradientshapeok="t" o:extrusionok="f"></path><lock aspectratio="t" v:ext="edit"></lock></shapetype><shape id="_x0000_i1025" style="WIDTH: 408pt; HEIGHT: 212.25pt" type="#_x0000_t75"><imagedata o:title="" src="file:///C:%5CDOCUME~1%5CDouDie%5CLOCALS~1%5CTemp%5Cmsohtml1%5C01%5Cclip_image001.png"></imagedata></shape>

<shapetype id="_x0000_t75" stroked="f" filled="f" path="m@4@5l@4@11@9@11@9@5xe" o:preferrelative="t" o:spt="75" coordsize="21600,21600"><stroke joinstyle="miter"></stroke><formulas><f eqn="if lineDrawn pixelLineWidth 0"></f><f eqn="sum @0 1 0"></f><f eqn="sum 0 0 @1"></f><f eqn="prod @2 1 2"></f><f eqn="prod @3 21600 pixelWidth"></f><f eqn="prod @3 21600 pixelHeight"></f><f eqn="sum @0 0 1"></f><f eqn="prod @6 1 2"></f><f eqn="prod @7 21600 pixelWidth"></f><f eqn="sum @8 21600 0"></f><f eqn="prod @7 21600 pixelHeight"></f><f eqn="sum @10 21600 0"></f></formulas><path o:connecttype="rect" gradientshapeok="t" o:extrusionok="f"></path><lock aspectratio="t" v:ext="edit"></lock></shapetype><shape id="_x0000_i1025" style="WIDTH: 408pt; HEIGHT: 212.25pt" type="#_x0000_t75"><imagedata o:title="" src="file:///C:%5CDOCUME~1%5CDouDie%5CLOCALS~1%5CTemp%5Cmsohtml1%5C01%5Cclip_image001.png"></imagedata></shape>

<shapetype id="_x0000_t75" stroked="f" filled="f" path="m@4@5l@4@11@9@11@9@5xe" o:preferrelative="t" o:spt="75" coordsize="21600,21600"><stroke joinstyle="miter"></stroke><formulas><f eqn="if lineDrawn pixelLineWidth 0"></f><f eqn="sum @0 1 0"></f><f eqn="sum 0 0 @1"></f><f eqn="prod @2 1 2"></f><f eqn="prod @3 21600 pixelWidth"></f><f eqn="prod @3 21600 pixelHeight"></f><f eqn="sum @0 0 1"></f><f eqn="prod @6 1 2"></f><f eqn="prod @7 21600 pixelWidth"></f><f eqn="sum @8 21600 0"></f><f eqn="prod @7 21600 pixelHeight"></f><f eqn="sum @10 21600 0"></f></formulas><path o:connecttype="rect" gradientshapeok="t" o:extrusionok="f"></path><lock aspectratio="t" v:ext="edit"></lock></shapetype><shape id="_x0000_i1025" style="WIDTH: 408pt; HEIGHT: 212.25pt" type="#_x0000_t75"><imagedata o:title="" src="file:///C:%5CDOCUME~1%5CDouDie%5CLOCALS~1%5CTemp%5Cmsohtml1%5C01%5Cclip_image001.png"></imagedata></shape>

注解:

首先,你应该明确的而是,我们应该先整理好我们的概念模型(或者说是领域模型),而不是先去考虑实现。实现是要考虑的,但不是在这个时间。做it这么多年,我得出的经验是:只有概念模型才是重用的,其他的设计和代码级的重用,意义不是很大。我相信我的这个总结是正确的,因为MDA也承认,他们现在,真正处理不好的,就是如何处理计算无关的模型(C I M)部分。

同时,我也想在此声明一下,我列出这7个要点的目的,并不是要大家都完全使用这7个要点进行工作,而是应该了解到,这7个要点在UML的语义中已经有了明确的定义和使用范围。所有,请大家不要乱用,不要自己去给它定义扩展的语义。你的语义是不标准的。

记住,你的身份最好是分析师(这样你会赚更多的钱^_^),然后再是设计师,然后再是编码实现者。

要点1  

大家应该注意,我的图是一个概念图(是一个分析类图),而非设计类图(也不是一个数据库图),我的分析类图,要表现的,是问题领域中的业务对象,而不是解决方案域的实现层面的东西。这一点,从应该这么看,我的类图中没有属性和方法。当然,为了更明细的表明是问题域的类图,建议大家使用stereotype(翻译过来叫版型),把它的版型设置为domain 。具体的做法:在Rose 中,右键双击你的类图,然后,在弹出窗口中设置stereotype domain。如果你发现你的类图遍成了一个小的圆地球,而你希望你的类图使用矩形的类图,那么我再教你一招。右键菜单中,选择options ->stereotype display,然后选择decoration.

<shape id="_x0000_i1026" style="WIDTH: 180.75pt; HEIGHT: 96.75pt" type="#_x0000_t75"><imagedata o:title="" src="file:///C:%5CDOCUME~1%5CDouDie%5CLOCALS~1%5CTemp%5Cmsohtml1%5C01%5Cclip_image003.emz"><font face="Times New Roman" size="3"></font></imagedata></shape>

要点2

“订购” 是一种 关联关系(association)的名字。 你可以不使用它,或者连同要点3一起使用。

要点3

图中的”<chmetcnv w:st="on" tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="1" unitname="”">1”</chmetcnv>是关联中的一个多重性(multiplicity)。

我们来看一下图中的多重性都说明了什么,这个图可以读作:一个客户,可以多次订购,形成多个订单,但是有的客户可能一次也没有订购过;一个订单,只能被唯一的一个客户订购。所以一个客户和订单之间的关系是0..n .你也完全可以用一个n 来代替,这只是说,你没有非常清楚的说明客户和订单之间的关系。我是用的词是“读作”,这表明,我真的是把UML当作一种语言来看。^_^

要点4

我希望用一种实心的组合关系,来表示一种强的关联关系。

组合是一种聚合(aggregation空心菱形箭头),但是关系表达更强烈。Class A ClassB 之间如果是组合关系,那么表示ClassA不存在的时候,Class B 也不存在了。(有点象数据库设计中的级联删除,并且,你也确实可以建立这种从UML语义 到数据库设计语义的映射)。而聚合是一种弱的关联,Class A Class B之间是聚合的话,Class A 不存在了,Class B还是可以存在的。就象是组织机构和人一样,机构撤了,人还是在的,你不能把原来机构里的人都给杀了。

我们也可以从rose工具中看到这种关系是如果表示的:在你设置订单和订单行之间的聚合关系时,你首先是在rose中选择的是aggregate,这时你如果确定退出,会看到它是一个空心的菱形,如果你不退出,在aggregate下面,你会看到一个containment ,里面有3个选项:by value by reference unspecified

by value ,是说,保有它的值,它的生死由我管,by reference 表示,我管不了它的生死。最后一个表示,我不清楚,现在还不能确定。 选择by value,就会变成一个实心的菱形。

建议,你打开一个工具,自己动手操作试一下。

要点5

lineitem 是一种角色(role),但是我们一般不用它。

要点6

 很多人会忽略注释,但是,这已经不仅仅是注释了。这里表示的是一种约束(constrain)。

当你发现有很多你无法表达(或者很难表达)的语义时,不要把它扔掉,用一种注释的方式把它表现出来,那么,很多后续的工作者(包括你自己)会因此而受益的。千万不要把东西老是放到你的脑子里,这不仅不利于交流,也很不安全。

要点7

你会发现,我没有使用箭头,为什么呢?因为,箭头表示一种navigable(导航)。导航的意思是,我知道你,但是你不用知道我。(Don’t call me I’ll call you later ,这是典型的好莱坞法则,^_^.用这个图来说,我们可以用客户去找到他的订单,我们也可以用订单去查找相应的客户,所以,这是一种双向的沟通(两个箭头,但是rose上只现实为一条直线)。如果我们只希望通过客户去统计它的订单,而不希望用订单找到客户的资料,你可以加上一个箭头。(题外话,订单和订单行之间,就可以是一个带箭头的关联,因为,很少有人通过订单行去找订单,但是确实也有这样的情况,当然,你可以偷偷说他这样要求很BT

再次声明,不是说你的图中用到了这些要点,你的UML图才是准确的。精确和准确是有概念差异的,我的图看起来精确了一些,但你的图只要保证准确性就可以了。一个很简单的例子,你仔细看看,我的“订单行”和订单之间,就是没有用到多重性,为什么?不好表示,如果你把订单行看作是一个个独立的对象,那么,我们问一个订单行和订单之间的关系,是11,还是10..1 ?我们不想纠缠于这样的问题(这个更学术性,呵呵)。所以我们就忽略它,用一种强组合来代替。我们甚至可以这样认为:强组合关系中被组合的对象,对它所在的宿主对象中,是唯一的。

同时,有时你不能要求1..n是正确的,n 是错误的。我们如果不要求那种强语义的约束的时候,是可以放弃要求的。1..n说明,至少有一个,可以有多个,而普通的n,表示是有多个。这样的语义,是你在讲究精确度时,给它加上去的。在这个业务场景中(而不仅仅是图中),我们要求一个订单至少要含有一个订单行,这是一种业务规则,而不是我们随意加上去的,UML只是一种语言。

另外,不要太迷信书籍了。有很多书中的UML图示有错误,其中不乏大师的作品。

你可能感兴趣的:(ext,F#,领域模型,bbs,UML)