MDA核心之MOF原理和实现

MOF原理和实现

陈健翔

2004-10-15

 

关键字:MDA MOF AOP

众所周知MOF是MDA的核心,下面我们来快速浏览一下什么是MOF。
序曲

一个应用系统可以被分为典型的3层结构。在《UML模式与应用》[1]一书中分别称为UI层、领域层、数据层。UI层和领域层的接口通过应用程序和应用框架来连接;领域层和数据层的接口通过持久化框架来连接。该书中关于持久化框架的实现是使用模板方法模式来实现的,基类定义了持久化基本接口,由每个子类来实现各自的持久化方法。子类的域(field)和关系数据库的字段的映射关系被直接编码到类代码中。该方案会导致系统复杂性的提高和系统维护的困难。为了解决该问题,该书引用另一本书的一种解决方案,即POSA[2](Pattern-Oriented Software Architecture: A System of Patterns)的反射模式。

 

 

POSA1中的Reflection一节讲述上述的反射模式,或称为映像[3]模式。映像模式将软件系统(领域层)分为基本层次和元层次。基本层实现程序的逻辑,元层次封装可更改的系统内部成分。元层次由一组元对象(metaobjects)组成,每个元对象封装了一个关于基本层次的结构、行为或状态的一方面的所选信息,所有元对象一起提供一个应用程序的自表示。将持久化方法封装到元层次后,基本层次通过调用元层次提供的持久化组件来序列化和反序列化内部数据。同时可以通过元对象协议(MOP)改变元层次的持久化方法,以影响整个系统的持久化行为。该模式示意图如下:

< img height=220  width= 417 src =https://p-blog.csdn.net/images/p_blog_csdn_net/jimconrad/56772/o_1.gif />


 

将元层次从系统中独立出来后,对元层次的访问变得十分重要了,这就直接导致了元层次的互操作性和兼容性问题,即不同模型系统表达的元层次能够互相访问、接口兼容。我们来看映射模式中元层次信息的结构:元层次保存的信息包括类型信息(type_info),存放在元层次类型库中;扩展信息(extTypeInfo),提供类大小、继承关系和数据成员信息等,对象与关系数据库的关系可以记录在扩展信息中。由于建模语言的不同,定义出来的元数据虽然内容相似,但是格式、接口却不同。为了解决这个问题,就需要一个统一的格式和接口来描述和访问元数据,这就是MOF要做的。
MOF体系结构

我们知道,为了实现跨语言和跨平台的对象访问,OMG提出了CORBA体系结构,并定义了IDL用于统一对象访问接口。MOF接口是OMG提出的在元层次上定义的统一的接口。和OMG一贯思想一样,它也是跨语言和跨平台可访问的。另外,注意到跨平台访问和跨平台运行是不同的两个概念,Sun的Java是跨平台运行的,但Eclipse就不一定了;C++程序通过CORBA能够做到跨平台访问,但是做到垮平台运行却比较难。

 

MOF体系结构是分层的元数据体系结构,该体系结构的经典框架有4个建模层次的,如下图所示:

=https://p-blog.csdn.net/images/p_blog_csdn_net/jimconrad/56772/o_2.gif />

每个层次的上一层是下一层的的模型,本层次的描述语言在它的上一层模型中。比如元层次股票报价类StockQuote用于描述软件系统中的报价对象;而元-元层的类Class则是用于描述模型层,如元层次类、包等的建模元素;同样,元-元-元层,简称为MOF Model层,该层的Class则是用于描述元-元层,也称为元模型层的中我们通常说的类,包,关联这些建模型元素;那么最后MOF Model由谁来描述呢?答案是MOF Model自己:“上层”MOF Model中的Class可以描述下层MOF Model的Class,Data Type,Association,Reference,Attribute,Operation等等这些Model Element类的派生类,包括Model Element类在内;“上层”MOF Model中的Package可以描述下层MOF Model的Model、Reflective、PrimitiveTypes、CorbaIdlTypes等这些包;“上层”MOF Model中的Association可以描述下层MOF Model的包括泛化在内的所有关联...更简单地说吧,就是:MOF Model包含了一个名为“Model”的Package,这个Package中有很多Class,这些Class使用一种名为“Generalizes”的Association关联成一棵树,根节点是“Model Element”这个Class。

 

元层次和基本层次之间的关系是相对的,和元层次对基本层次之间的关系相似:元-元层次也起到封装元层次内部可变成分的功能。以此来看,在4层结构中,MOF Model是metamodel的元层次,包括了metamodel的元对象和对应的MOF接口,提供给特定的功能模块访问,该功能模块就像前文提到的持久化组件一样。模型层和元模型层也是相对的,任何一个模型层,包括元模型层,的上一层都称为本层次的metamodel,而MOF Model是它自己的metamodel。MOF metamodels则特指提供了MOF接口的元-元层。

 

而实际上,MOF元数据体系结构的元层结构不是固定的。虽然有典型的4层,其实是可多可少的,取决于MOF如何部署。在上面的4层结构中MOF部署在metamodel的上一层,这纯粹是为了方便于理解数据和元数据之间的关系。MOF可以用于描述任何一个模型层,为他们定义一致的接口。如:MOF用于定义model的统一接口,使客户程序可以通过MOF接口访问model;MOF也用于定义metamodel的统一接口,使客户程序可以通过MOF接口访问metamodel;其实当在model层使用MOF的反射接口时,就会获得metamodel的MOF接口。即MOF能够为每个元层提供接口。在下文谈到的MOF映射中,就是以MOF 部署在metamodel层描述model层为例的。明白这一点,就明白了MOF是什么了:为任何模型定义统一接口。“任何模型”可以是信息模型、元模型、MOF模型自身。如下图:

=https://p-blog.csdn.net/images/p_blog_csdn_net/jimconrad/56772/o_3a.gif  />


 

MOF提供了一套CORBA接口,使用CORBA IDL来定义,以此为基础统一了不同模型间的接口,使能够兼容和互访。之所以使用CORBA IDL,是因为对象访问是一种更一般的访问方法,而CORBA提供了对象访问的平台;MOF虽然是对模型的建模,但metaobject也是对像,MOF终究还是面向对象的;实际上,不但MOF是面向对象的,各个元层包括信息层(information)都是面向对象的;所以都可以使用IDL来实现无阻隔的对象访问。

 

由于MOF有三个元层次;并且在叙述不同层次时在词汇上共享了意思相近或相同的名词,有些名词仅在版上做了区分,比如MOF Model中的建模构造(Construct[4])Class和通常说的或者UML中的class的区别仅仅是首字母大写;同时MOF使用UML来描述,而UML的图元又不是MOF Model的建模元素,比如泛化在MOF中用关联来描述;所以刚开始时,它的规范和概念看起来容易迷惑。不过随着对规范的熟悉,就知道一些规则,如:首字母大写的名词如Class、Package、Association等表示的是上一层的构造元;MOF metamodel表示支持MOF接口的metamodel层的模型。顺序细读规范也会注意到它对一些术语的使用做了说明的,规范的前后文关系还是比较密切的。
插曲

MOF体系结构看起来很美,似乎超越了所有建模语言,是一个完美的形式系统。从集合角度看,MOF Model Package是这样一个集合:它是集合的集合,即它的元素也是集合,如Class,Package,Association。从它的元素中取出“子”元素来能够组成这样一个新的集合,这个新的集合居然还是MOF。就像魔术师一样,把一张报纸撕碎了并且烧掉,然后从残留的灰烬中取出那么一小点,“噗”一下又重新变出整张报纸。

 

后来才发现类似MOF这样形式语言的研究在其他领域很早就有了,在网上搜索“形式系统”、“元数学”,就会搜到:希尔伯特.D(Hilbert,David,1862~1943)在1920年代创立了元数学。更一步想:要是有一天形式语言发展到人的语言和计算机语言能够互相访问,那岂不是人说一句话就能产生一个可运行的程序,就像电影《The Matrix》中描写的:Neo和Trinity进入Matrix打算营救Morpheus,他俩站在系统中,Neo说了一句:“Guns, lots of guns...”,许许多多排的枪械“唰唰唰”的飞奔而来...胡思乱想,扯远了。不过最近日本人发明了一种语言翻译系统,据说不错,好像不是像以前比较原始的“东方快车”那样逐字翻译的,不知道它和MOF原理是否一样:先把一种语言的一段文字解释、建模,然后根据另一种语言的形式模型映射成另一种文字。关于映射我们来看下面。
MOF映射

MOF映射是在给定实现技术的环境中将MOF的语义用另一种实际的技术再实现的过程。一个客户程序通过MOF可以读出一个模型(比如metadata层的model)中有哪些Class实例,哪些Package实例等等,当把这些元素读出来以后,就要实现为Java模型中的Class实例和Package实例,或者UML模型中Class和Package实例,或者IDL中的Interface和Module实例。通过映射能将MOF描述的模型用具体技术重建出来。

 

映射中最重要的是抽象映射(Abstract Mapping),它描述如何将MOF metamodel充实为一个抽象的信息模型(information model);即如何使用metamodel的构造拼写出metadata的逻辑结构。抽象映射给出了映射的语义和规则,是所有MOF具体映射的参照和准绳;任何具体映射如果有违抽象映射规则,那么将和其它模型不具完全的互操作性,比如和CORBA IDL映射的模型之间。即不合法映射产生的模型和正确映射产生的模型之间不能完全互操作。

 

举一个例子能够比较形象的说明MOF映射问题。在MOF规范中有下面这样的例子。这个例子是MOF到IDL的映射,是规范中的图5-1。关于该图需要说明的是:规范中又将information、model、metamodel、MOF Model各层分别称为M0、M1、M2、M3层。

=https://p-blog.csdn.net/images/p_blog_csdn_net/jimconrad/56772/o_3.gif  />

图的最左边是对M1层模型结构进行描述的M2层:Package是M2层的构造(construct);P是Package在M1层的一个实例;类似的C和A分别是M1层Class实例和一个Association集合[5],C通过A产生自关联。如果是Java模型的话,A中的元素即一个链接(link)可以用Attribute实现,而Attribute是有类型的,所以又关联回C,我们可以画一个展开图来看:

 

 

< img src =https://p-blog.csdn.net/images/p_blog_csdn_net/jimconrad/56772/o_attr.JPG />


   

所以左图的意思简单的说是:M1层有包,包中有类,类通过关联连接起来。为了实现这个概念模型,通过最右边的方法来进行:一个包工厂创建一个包实例P,包实例中有一个类代理,类代理创建多个类实例,类实例之间的关联全部存储在关联的实例集合A中。直接一点理解可以把P对应Java中的Package,C对应Class。图的中间部分是概念模型到映射结果的五种接口,通过它们访问具体的IDL映射模型。而这五种接口也正是MOF Model的Interface![6]这五种接口的每种接口可能不止一个接口实例。比如C这种接口,每个在M1层的C实例分别对应一个接口,如可能是IClass1,IClass2这样的多个接口实例;P也是一样,可能包括IPackage1,IPackage2,IPackage3等等这样多个接口实例。
模型互访

通过映射将MOF和具体建模技术结合起来了,下面我们来看看MOF实现结构。图中每个模型(Model1和Model2)都提供了MOF接口,客户程序(包括访问其它model的model,如图中Model1)通过MOF看到的是Model1和Model2的MOF模型,而不再是具体技术(如UML)构建的特殊模型了。至此可以看出MOF设计思路其实和CORBA是很相似的。

< img src= https://p-blog.csdn.net/images/p_blog_csdn_net/jimconrad/56772/o_mofimp.JPG />

有了这样的平台,通过MOF模型与模型之间就可以建立大使级外交关系了。不但是MOF的model层与model层之间,metamodel层和metamodel层之间,还可以是model层和metamodel层之间...只要遵循MOF规范就能互访。同时由于MOF是建立在CORBA之上,所以它还做到了跨语言和跨平台。补充说明一下:一般而言分层系统是不允许交叉访问的,每个层只能建立在它下面的层之上,但像MOF这样描述性分层系统,层与层之间是允许双向依赖的[7]。
尾声

回到本文开始。我们开始说的持久化框架用于领域模型,其实GUI模型也是可以持久化的,就像许多开发系统所做的那样,开发人员定义的用户界面及其界面相关数据,往往需要被持久化,如保存在某个特定格式的文件中或保存到数据库中。当程序编译时这些数据再被静态连接到可执行文件中;或程序运行时再去读数据然后加载到系统中。就像领域层设计的方法一样,我们可以使用映像模式来实现它。当然是在如果有需要这么做的情况下,因为映像模式还是有它的缺点的。
花絮1: 元元层和AOP

应用系统使用到元-元层的可能比较少被人所知,下面对元元层的功能做一补充描述,该描述属于推测、猜想类,并不是从已知应用引用而来。我们来看个例子:比如在Java环境中,元-元层可以将方法(Method)调用(invoke)的信息存储到一个“元-元对象”中,当一个代理类调用该方法的invoke()时,可以通过元-元层的组件Invoker来实现invoke()。Invoker通过读取元-元数据来执行操作调用的行为。比如元-元层可能记录了方法调用时需要记录日志,则Invoker将会把每个调用记录到日志中;元元层也可能记录了方法调用时通过特定的通信协议,那么Invoker将使用该协议执行本次调用。由此得知,元-元层可以影响到整个模型和信息系统的行为。——看出来没有,这不就是一个AOP的思想吗?!目前AOP Framework也大都采用了动态代理来实现 。上述内容如下图所示。图中,StockQuote是一个领域层的类;ClassProxy实现了java.lang.reflect.InvocationHandler接口。本图只是示意图,不是标准的UML图。

 

 


花絮2: 宇宙设计语言

MOF规范的1.2节Software Development Scenarios讲述了一个案例:用MOF定义一种新的建模语言,称为宇宙设计语言(UDL: Universal Design Language)。围绕该语言,构建了一个软件开发系统。该系统建立起来的软件模型通过MOF实现了互操作性...具体请参见规范原文。该案例对我们根据具体领域和业务构造一个适合的建模语言和方法有一定参考价值。


[1] 该书第一版。该书第二版做了修订,改进了原方法,引入object-relational (O-R) mapping的概念。

[2] 因为写书当时还没有出POSA2(Pattern-Oriented Software Architecture, Volume 2: Patterns for Concurrent and Networked Objects),所以是POSA而不是POSA1。而POSA2同样精彩,而且对模式语言做了更详细的描述,值得推荐。

[3] 机械工业出版社那本书之所以将Reflective翻译为“映像”可能是因为类和它的反射就象镜子前的物体和镜子里的像一样,和镜子里的像相对的,类的反射称为“映像”。而反射是动词用作名词,偏重于产生像的动作本身,所以用名词“映像”作译词。

[4] 暂译为构造,是因为它是一个表达单元,能够被实例化(instance),实例化的过程就是构造对象的过程。“构造”动词用作名词化,或者译作构造元,构造体,构件,结构等。

[5] 为什么是一个请参见MOF规范5.2.1 Meta Object Type Overview

[6] 参见MOF规范3 MOF Model and Interfaces。

[7] 参见POSA1的Reflection一节。

你可能感兴趣的:(Architecture,class,语言,uml,跨平台,aop,blog)