基于 XML 的模型驱动工程






3.55/5 (14投票s)
使用XML技术进行模型驱动工程。
概述
以下文章介绍了一种基于XML的模型驱动工程方法,并讨论了建模和代码生成的益处,以及使用XML技术进行这些操作的优势,例如XML技术的广泛采用、成本效益、灵活性和可扩展性、易于协作以及与OMG标准的兼容性。
文章还展示了一些基本的XML模型示例,然后讨论了一个成功应用该方法于多个大型软件系统的案例研究。
模型驱动工程
传统上,软件设计师和架构师一直使用模型来表示正在构建的系统的某些关键方面,而忽略与这些关键方面无关的细节。这类模型往往能极大地促进项目各方之间的沟通,并有助于在开发早期验证设计或架构并发现潜在问题。
通过模型驱动工程 (MDE),有时也被称为模型驱动开发 (MDD),这些模型成为软件的组成部分,并经常用于生成其他开发工件,或者被软件的其他部分直接使用。
在软件系统中,模型通常描述正在建模的系统的动态行为或静态结构。
描述动态行为的模型可以以多种方式应用,从生成构成系统一部分的3GL代码到系统运行时对模型的实际解释,这实际上可以模糊模型和专用脚本语言之间的界限。后者在问题域可以通过领域特定语言 (DSL) 进行良好定义时更有意义,而模型通常就是以这种语言表达的。某些模型也可能描述在设计时无法确定的业务规则,因此可以在运行时由业务分析师或最终用户进行更新。
另一方面,描述系统静态结构的模型非常适合用于生成高级语言(如Java、C#或C++)的代码,然后由开发人员手动增强以构建完整的系统。
代码生成
诚然,代码生成可以带来生产力的大幅提升,因为它省去了开发人员编写实现模型的基础代码,让他们能够专注于模型所代表的系统的关键方面。此外,它还可以提供更高质量的产品,因为生成的代码可能比手动编写的基础代码错误少得多。更不用说由于模型定义清晰且能够快速将任何更改纳入产品,因此在产品维护和增强方面可以节省大量成本。
一些代码生成器只生成开发人员可以修改以构建系统的存根,类似于IDE中的向导。虽然这种方法在初始开发期间仍能带来显著的节省,但如果生成的代码在稍后无法重新生成,其价值可能会受到限制。通常,为了启用重新生成,开发人员不应修改生成的代码,而是应单独对其进行扩展、自定义或覆盖。在大多数面向对象语言中,这可以通过继承生成的类并根据需要添加或覆盖功能来实现。然而,有些生成的工件可能不易在不更新生成代码的情况下进行自定义。例如,使用标准的IDE设计器允许编辑生成的富客户端表单或服务器端网页,同时保持生成代码不变,这可能会相当棘手。
为什么是XML
到目前为止,已经有很多专有的格式用于定义模型、模型转换和代码生成。OMG组织已进行了一些工作,以标准化建模语言(UML)并在模型驱动架构™ (MDA) 计划中定义模型转换框架。
尽管OMG规范已被许多供应商实现,但使用XML定义模型和转换提供了一种非常强大且廉价的替代方案。以下是使用XML进行建模的关键优势:
- XML是一个更广泛的行业标准,围绕它构建了各种各样的工具和技术。作为行业标准,在寻找有XML技术经验的资源来构建模型和转换方面,比寻找熟悉OMG规范和供应商特定工具的专家要容易得多。
- 与基于标准构建的模型相比,XML中定义的模型更加灵活和可扩展,因为如果要在非标准方式下增强模型,您可能需要等到标准得到增强并被您的供应商采用。
- 只要XML存储为纯文本格式,您的模型就可以轻松地存储在标准的版本控制系统中,如Subversion或CVS,这样多个开发人员就可以同时处理一个模型,然后像处理任何其他文本文件一样查看和合并差异。您不必为模型购买任何特殊的昂贵版本控制系统,就像用于存储UML图的那种。
- 为了定义您的元模型(即模型的语法),您可以使用标准的XML模式定义语言(XSD),这不仅可以验证您的模型,还可以在您编辑XML时通过提示允许的值来帮助您构建模型。
- 对于模型转换和代码生成,您显然可以使用强大的XSLT技术,该技术有许多供应商实现,包括免费的。
- 最后,您的模型始终可以通过创建到XML元数据交换格式(XMI)的转换来与OMG标准保持兼容,XMI是UML所使用的。
XML中的对象模型
让我们来看一个在XML中定义的业务对象模型的例子。这种模型的主要目的是在一个地方描述系统的业务对象及其操作,并为系统的每个层生成业务对象的表示。在一个典型的多层系统中,包括数据库(DB)、业务层(BL)和用户界面(UI),一个业务对象的单个字段可能在各种层中出现多达六次,例如:
- 数据库列;
- 用于更新数据库列的存储过程的参数;
- 业务层对象的字段;
- 用于UI和业务层之间通信的值对象的字段;
- 用于UI表单的数据模型的UI数据对象的属性;
- 绑定到该字段的用户界面控件。
换句话说,一个看似简单的向业务对象添加新字段或更改现有字段的操作,可能会导致所有层发生一系列的更改,这可能需要大量的工作。此外,开发人员需要确保该字段的类型和大小在所有层之间保持一致。
为了解决这个问题,我们将把所有必需的类型和业务对象定义在一个XML模型中,该模型将用于为系统的每一层生成这些业务对象的表示。
XML模型中定义的每种类型都将具有名称、大小和一个它扩展的基类型,这样我们就可以有效地在模型中定义类型层次结构。此外,每种类型都可以指定它映射到的每一层的物理类型。如果给定类型上未指定任何属性,则将使用基类型的属性。因此,我们的类型定义可能如下所示:
<type name="phone number" size="15" base="string">
<ui-control>PhoneNumberBox</ui-type>
<ui-type>String</ui-type>
<bl-type>PhoneNumberType</bl-type>
<db-type>varchar</db-type>
</type>
在定义了模型中的类型后,我们可以开始描述业务对象及其操作,这些对象将引用这些类型。作为简单的例子,我们可以描述一个客户对象,它有几个字段和一个读取操作来检索这些字段,如下所示:
<object name="customer">
<fields>
<field name="customer id" type="number" key="true"/>
<field name="first name" type="name"/>
<field name="last name" type="name"/>
<field name="home phone" type="phone number"/>
<field name="cell phone" type="phone number"/>
<field name="fax" type="phone number"/>
</fields>
<operations>
<operation name="read">
<request>
<arg name="customer id"/>
</request>
<response>
<arg name="first name"/>
<arg name="last name"/>
<arg name="home phone"/>
<arg name="cell phone"/>
<arg name="fax"/>
</response>
</operation>
</operations>
</object>
仅凭这样的对象描述就包含了足够的信息,可以生成数据库表、更新它们的存储过程,以及业务层和用户界面端的所有必需对象,包括从业务层读取对象的方法。
显然,生成器的复杂性将很大程度上取决于生成对象所使用的框架的强大程度。如果未使用任何框架,那么生成的类将必须自己实现所有标准的底层代码,这需要将大量代码构建到生成器中,使得调试非常困难。另一方面,如果生成的类使用的是一个强大的框架,它实现了所有必需的底层代码并提供支持,那么生成器可能非常容易编写,以至于它们仅仅使生成的对象继承正确的基类,并声明或添加正确类型的字段。由于这样的框架可能非常棘手,因此代码生成器通常会处于这两种方法的中间。
正如我所说,用XML定义这样的自定义模型的最佳之处在于,您可以轻松地对其进行任何增强,以使您的模型和生成器超负荷,并允许自定义输出。这使得可以将现有对象改造为使用新模型并利用代码生成器,从而大大降低该代码的维护成本。
对象模型并不是唯一一个可以有效地在XML中定义的模型。例如,您还可以用XML定义您的安全模型(包括所有角色和权限),该模型可以由代码直接使用,或者用于生成SQL脚本以将安全数据加载到数据库中。此外,生成用于从用户界面和业务层代码内部访问安全模型的代码是有意义的,这样当XML模型更改时,编译器可以捕获代码中尚未相应更新的地方。
另一个例子是XML中定义的系统配置模型。与安全模型一样,系统配置可以作为XML直接使用,或者用于生成SQL脚本以加载到数据库中。同样,生成用于访问系统配置的代码也具有上面为安全模型描述的相同好处。
案例研究
本文所述的基于XML的建模已成功应用于多个大型运输管理系统(TMS),这些系统包含300至400个业务对象。系统具有三层结构,包括关系型SQL数据库、C++业务层以及C#富客户端GUI或Web前端。与业务层的通信通过专有协议进行,但没有框架支持来确保消息始终有效。
开发所有业务对象及其支持的操作的XML模型,允许在运行时使用此模型使所有业务层消息都符合该接口。该模型还在设计时用于在GUI端生成C#数据对象,这些对象使用灵活的模型-视图-控制器(MVC)框架,从而实现了GUI从Visual Basic 6到.NET平台的低成本迁移。
除了GUI对象之外,该模型还可以生成数据库表、更新这些表的存储过程,更重要的是,还可以生成业务对象的基类,这些基类定义了对象的结构(包括其父子关系),并实现了数据库创建-读取-更新-删除(CRUD)操作的所有必要底层代码。
除了生成所有这些可以在模型更新后随时重新生成的工件之外,还开发了几个一次性生成器,用于创建扩展生成的基类或用户界面表单原型的存根类,这些类可以作为全面开发的基础。
XML模型中的每个关键元素都有一个相关的文档标签,这还允许生成基于HTML的文档,以便所有业务对象易于浏览并有助于更好地理解业务模型。最重要的是,这些描述标签还在运行时用于向用户提供关于各种字段的上下文帮助。
结果是,开发人员更专注于系统的业务模型和业务逻辑,而不是低级的基础代码,这显著减少了开发和维护时间,并整体提高了产品质量。
结论
模型驱动工程与代码生成相结合,可以在提高开发人员生产力、降低开发和维护成本、缩短上市时间以及提高产品质量方面提供巨大的好处。
事实证明,使用XML技术进行建模、验证、转换和代码生成是一种成本非常低但功能极其强大的模型驱动开发方法。
历史
- 2008年9月25日:本文初版。