OCL和MDA
闲聊:
我的BLOG又是一周没有更新了,倒不是因为懒,而是上周的大部分时间花在审阅两篇稿件上了。而尚未发表的稿件不能公开讨论,所以BLOG上面就空空如也了。这几天集中精力读《Object Constraint Language, The: Getting Your Models Ready for MDA, Second Edition》这本书,颇有心得。作者Jos Warmer是OCL的创始人,他对于这门语言的把握是最专业的,而且行文流畅,读原著如同读汉语一样,不由得大发感慨,“好书即是好老师”。全书一共十章,分为两大部分,第一部分User Manual包括前五章,主要讲述OCL的由来、概念、简单的使用和实现方法,以及与MDA的关系等;第二部分Reference Manual内容要深一些,讲述了OCL的一些高级使用方法。
这几天奋起疾“书”,以一天一章的速度看完了前五章,脑中彷佛有豁然开朗之感,尤其对于OCL和MDA的关系有了新的认识。
OCL和MDA的初感想
要谈OCL和MDA之间的关系,先要搞清楚它们各自的定义。OCL的定义上次已经说过了,再贴过来看看:UML图(例如类图)通常不够精细,无法提供与规范有关的所有相关部分。这其中就缺少描述模型中关于对象的附加约束。这些约束常常用自然语言描述。而实践表明,这样做经常造成歧义。为了写出无歧义的约束,已经开发出几种所谓的“形式语言”。传统上的形式语言,缺点是仅适合于有相当数学背景的人员,普通商务或系统建模者则难以使用。OCL即为填补这一空白而来。它是一种保留了易读易写特点的形式语言。它已在IBM的保险分部作为一种业务建模语言开发出来,根植于 Syntropy 方法。
而MDA的定义如下:MDA是OMG提出的一种新的软件开发方法,它定义了基于模型的开发过程,以及自动将模型映射到实现的方法。它提供了一种使用模型来指导系统的理解,设计,构造,开发,操作,维护和修改的方法。
直观的来说,MDA是OMG定义的一种软件开发方法,为了标准化这种开发方法,OMG定义一组规范来支持MDA,其中最重要的有:MOF,UML,XMI,CWM。目前MOF,UML和XMI的最新版本都是2.0(CWM不知道,本身就不熟悉它)。在UML2.0的规范中,用了一个单独的部分来专门定义OCL(OCL在UML的较早版本中已经定义,不过没有作为单独的部分来定义)。这说明,OCL和MDA的关系是:OCL是MDA众多标准中的UML标准中的一个子标准。
但是OCL在MDA中的重要性如何呢?
模型成熟度(Modeling Maturity Levels,MML)
在书中我首次见到了MML的概念,当然不一定是本书作者提出的,只不过是我以前孤陋寡闻罢了。MML指出了模型在你的软件开发过程中扮演了一个什么样的角色?并且指出了为了提高软件开发效率你应该采取什么样的措施。
下图画出了MML的六层示范图:
第零层:没有标准:模型存在于开发者的头脑中;
第一层:文本表达:用自然语言写下想法;
第二层:文本和图:用自然语言以及一些图来表达想法;
第三层:模型和图:用建模语言描述的图来表达模型,用自然语言加以辅助描述;
第四层:精确的模型:用一致而连贯的文本/图来精确的描述模型,它们都是没有歧义的,可以直接映射到编程语言;
第五层:只有模型:第五层的模型是对于系统的一个完备的、一致的、详细和精确的描述。它足以进行全部的代码生成工作,生成的代码不需要任何改动即可运行。总而言之一句话:“模型可运行”!
通过以上MML的描述我们可以了解,如果使用UML来描述模型,但是不使用OCL来描述模型中的约束,那么只能达到第三层。如果使用UML+OCL,那么模型就是精确的,MML可以达到第四层。如果模型可以达到MML5,那么是我睡着了。。。当然我们坚信MML5总有一天会达到,那时我们就可以像使用高级语言一样使用建模语言,而像不理今天的汇编一样不理明天的高级语言。也许有一种叫做MVM(Model Virtual Machine)的东西就像今天的JVM一样流行。
OCL用在了MDA的哪些方面?
从上一节可知,OCL是MDA的必要条件,但远远不是充分条件。但不可否认的是,OCL被广泛用于MDA的各个方面。下面的两张图可以说明一部分问题:
第一张图是MDA的一个典型的开发流程,建立PIM,描述转换定义,利用转换工具将PIM转换为PSM。第二张图是OCL在MDA典型开发流程中的使用。其中三个方面使用了OCL:第一是model的创建使用了OCL来描述模型中的约束;第二是模型转换的定义可以使用OCL来描述;第三是建模语言可以使用OCL来创建。
其中让人迷惑的是第一和第三有什么区别呢?用OCL来约束模型和用OCL来创建建模语言有什么区别?区别在于它们所属元层次的不同,也就是MOF中所描述的模型层次不同。这不是绕口令!其实我刚刚接触MDA的时候也认为模型、元模型、元元模型好像绕口令一样,但这些概念在接触中慢慢清晰起来。用OCL来约束模型是处于M1层,其模型是指对系统的描述,例如对一个信用卡管理系统的UML模型。而用OCL来建立建模语言是处于M2层,这时OCL是用来描述UML的元模型中存在的约束,因为元模型等于模型的语言,也就是用OCL来创建建模语言(可能叫用OCL来定义建模语言中的约束更好)。下面是一个UML元模型中使用OCL的例子:
context Interface
inv: features->select(f |f.oclIsKindOf( Attribute ) )->isEmpty()
这个OCL表达式说明,接口Interface中不能有属性存在。如果UML的元模型中缺少OCL的描述,那么此元模型就不是一个“精确”的元模型,那么UML也就不是一个精确的建模语言了。那么MDA就离我们而去了!
OCL,约束自己,约束父亲
由上可知,虽然OCL号称“对象”约束语言,其实它可以对MOF的模型层次中的任一层次进行约束,从而表达出精确的模型(四层模型中任一层的模型)。
OCL可以约束M2层的模型,例如UML的元模型,而OCL的元模型也处于M2层,那么OCL是否可以约束自己的元模型呢?答案是肯定的。
上图是OCL的元模型简化图,其中也用OCL对一些地方进行了描述:
context LoopExpression
inv: source.oclIsKindOf( Collection )
inv: iteratorVariable.type= source.oclAsType(Collection).elementType
上面的约束表达了LoopExpression中source的类型必须是Collection,而迭代子iterator的类型必须是source这个Collection中的元素的类型。由此可见,OCL的元模型也需要OCL来约束,否则这个元模型就是不“精确”的,可以说,OCL在某种程度上自定义了自己。
从M0(对象),M1(模型)到M2(元模型)都可以用OCL来描述,那么M3层呢?定义UML和OCL元模型的元模型MOF,是否需要用OCL来约束。答案是肯定的! 随便举一个例子:
[1] The multiplicity of Association::memberEnd is limited to 2 rather than 2..* (i.e. n-ary Associations are not supported).
context Association inv: memberEnd->size() = 2
[2] The type of Operation::raisedException is limited to be Class rather than Type.
context Operation inv: raisedException.oclIsType(Class)
约束1说明Association的memberEnd的数量必须是2,也就是说Association只能有两个memberEnd;约束2说明Operation抛出的异常类型必须是Class。以上摘自MOF2.0规范。这说明MOF作为OCL的定义者,父亲,同时也被OCL这个儿子约束着。
后记
OCL是MDA中不可缺少的一环,MDA即使离开了UML还有可能使用其他的建模语言来执行,但是离开了约束各层模型的OCL恐怕就处处漏风了。OCL以后很可能会作为一个单独的规范从UML中分离出来。因为它不仅仅是一个“对象”约束语言,更是一个MDA约束语言,渗透在MDA的各个方面。文中还提到了OCL可以定义模型转换,但是由于模型转换的规范QVT还没有最后确定,所以这个部分只是试探,而不是唯一标准。而目前的OCL如果要定义转换,还必须做一些扩充,所以这里没有介绍。
OCL和MDA,目前我的理解也仅限于此,希望看完整本书后,能够有进一步的理解。