0%

仰望MDA,拥抱EMF

EMF与MOF的理想是类似的,只不过MOF在“仰望星空”,EMF更加“脚踏实地”。”

MDA的失败

尽管早在2001年,OMG组织就提出了MDA((Model Driven Architecture,模型驱动架构)
但是经过了火热的2005-2007年之后,MDA的关注度持续下降。

MDA关注度

长期以来,没有那个组织真正实现了MDA的工具或方案:Rational软件已经被IBM成功搞残;AndroMDA的最后一次发布还是在2010年;Eclipse GMT从2005年开始孵化,但到了2007年似乎已经死在了蛋中;将MDA的概念偷换为DSL的微软,也没有太多的建树;更有甚者,山寨出“KCOM商业工程”的凯科思特居然为5万元的项目惹上官司,后来更是销声匿迹。

怪只怪OMG的胃口太大,希望为各种语言、各种技术平台建立一个“大一统建模标准”:

大一统建模标准

结果忙坏了厂商,兴奋了开发商,苦了用户和程序员。最终一场闹剧黯然收场,消失个干干静静。

其实抛开MDA的各种理想化的标准(如MOF、CWM等),MDA提出了“从模型到模型”的软件开发周期:

从模型到模型

如果不是OMG太霸气,太死心眼,“强调MDA必须基于OMG的各项标准”,上述的路线图不失为一种好的思路。

比如,如果不过多强调PIM与PSM的差异和PSM的自动生成代码能力,而是使用一种在分析和设计阶段都可以使用的“领域模型”,就成立至今仍被广泛认可的DDD(领域驱动设计)方法。

EMF vs MOF

MDA为了支撑其“大一统建模标准”,提出了四层模型:

四层模型

  • M0: 实例层,表现为代码。是M1的实例化
  • M1: 模型层,比如,用UML设计的一个模型
  • M2: 元模型层,包括建模语言的元模型,如UML元模型等
  • M3: 元元模型层, OMG定义了一个”MOF”,目标是作为所有建模语言的元模型

MOF(MetaObject Facility,元对象机制)的目标是描述天下所有的模型,包括MOF自身。这让我想起了“元图灵机”——能够输出天下所有的图灵机,甚至包括自身的超级图灵机。

EMF与MOF的理想是类似的,只不过MOF在“仰望星空”,EMF更加“脚踏实地”。EMF的目标如下:

![EMF的目标](/images/e4/EMF_ purpose.png)

在开发过程中,一个“古板”的程序员可能会进行如下工作:

  • 用UML设计模型
  • 基于某种schema,用XML保存模型
  • 实现模型的接口定义
  • 编写模型的实现

这些工作中,UML、XML、代码(接口和实现)中都体现了模型的设计。或者说,信息是冗余的。对于冗余的信息,保持一致性是很麻烦的,
所以我们经常发现代码和设计文档/模型是不同步的。极端的程序员提出“代码是唯一的设计文档”的观点;而中庸的程序员设计了EMF。

Eclipse Modeling Framework是Eclipse提供的一套建模框架。可以直接编写EMF模型,也可以从UML、XML、Java(annotations)生成模型;反过来,EMF模型也可以转换生成UML、XML和Java代码。在EMF看来,”To model or to program, that is not the question.”

EMF元模型

EMF自身也是一个模型,当然也有其定义(元模型)。描述EMF的模型是Ecore元模型。Ecore模型已经可以描述自身,所以可以说Ecore兼具了MDA中的M3、M2层的功能。

一个简化的Ecore模型如下图所示:

Ecore模型

  • EClass 用于类
  • EAttribute 用于属性
  • EReference 用于类之间的关联
  • EDataType 用于值对象

EMF格式定义和编辑工具

EMF的模型保持XMI格式的文件。

XMI(XML-based Metadata Interchange,基于XML的元数据交互),是OMG基于XML、UML和MOF定义的一种元数据描述语言。微软也搞过一个与其类似的”开放信息模型”。

尽管可以从UML、XML、Java(annotations)等模型生成EMF模型,但更经常使用的方式是直接定义EMF模型。

Eclipse Modeling Project中,提供了模型编辑器:

模型编辑器

也有一些厂商提供了基于UML方式编辑EMF模型的工具。比如Omondo EclipseUML,但是目前只支持到Eclipse 3.7。

从EMF模型生成代码

如上所述,EMF模型可以生成UML、XML甚至RDB Schema,但是最常用的功能还是生成Java代码。

Eclipse Modeling Framework可以定义和编辑EMF Generator Model(.genmodel),该模型定义了从一个EMF模型(ecore)生成代码的各种行为。可以生成的代码包括:

  • Model Code: 模型代码,包括接口和实现
  • Edit Code: 对模型的”DAO”代码
  • Editor Code: 基于Eclipse Plugin的模型编辑界面,依赖 Edit Code
  • Test Code: 模型测试代码

如果不是开发Eclipse Plugin,可能更关注的是模型代码。
尽管一开始的时候对EMF生成的模型代码会不习惯,觉得不像自定义POJO那样简洁,
但是EMF生成的模型代码比自己编写的要健壮:

  • 接口和实现相分离。自己开发的模型,尤其是领域模型,可能不会这样实现
  • 模型通用接口。EMF生成的模型,每个接口是继承自EObject,该接口实现了一些通用的模型交换API
  • 事件通知。对于模型的变化,EMF统一提供了监听机制