通过示例进行模型驱动开发和原型设计






4.78/5 (4投票s)
当您思考重复性工作是多么无聊时,请考虑一下模型驱动开发。
引言
这篇介绍性文章是关于模型驱动开发与原型设计相结合,以快速获得解决方案的。它通常与数据库应用或业务应用相关,这些领域最能体现其优势。对于本文演示的示例和使用的应用程序,您需要一个 Windows 操作系统,但这并非普遍要求,例如,如果您使用另一个面向 GTK+ 的模板。
背景
编写软件通常是一项耗时的工作。幸运的是,通过智能的集成开发环境(IDE),一些耗时的任务被简化为几次鼠标点击,但并非所有可以节省时间的工作都已简化。XSLT 以及代码生成或模型转换是幕后使用的技术。最终,我们使用两个应用程序来实现更高程度的自动化——一个 UML 编辑器和一个能够理解特定 UML 模型的应用程序原型工具,它能将这些模型作为原型运行,并最终输出代码——同样是通过 XSLT 转换。
所需工具
在这里,我将简要描述阅读本文所需的工具。首先,您需要一个应用程序来为您的 UML 图建模。其次,您需要一个能将 UML 模型表示为应用程序原型的应用。第三,您需要本文中使用的模板,该模板负责生成代码。最后是一个商业框架,生成的代码会使用它。这是一个非常好的 DevExpress 框架,其评估版也可以下载。
第一个应用程序是 ArgoUML,可能广为人知。您可以从这里下载该软件。下载并安装后,您也可以对第二个应用程序执行同样的操作,点击这里。这是我的开源项目DMF: Distributed Multiplatform Framework中的主要应用程序。第三个软件是模板,它也是我开源项目的一部分,可从这里获取。最后但同样重要的是,您需要 DevExpress 框架才能编译生成的代码。别忘了,您当然还需要 Visual Studio 或 SharpDevelop。要编译并运行本文中的应用程序,您还需要一个 SQLite .NET 程序集。您可以从这里获取。请根据您的系统选择正确的版本(例如 32 位或 64 位)。
在您的项目中找到重复点
在我们开始使用 UML 建模并创建原型之前,理解我们为何使用这些工具非常重要。有些人学习 UML 只是为了文档编写,另一些人则将其视为开发过程中的一等公民。我属于第二类。
言归正传:您项目中的重复点,例如数据库表单,或者这些表单中使用的实体类。这些部分可以通过强大的 IDE 自动创建。
为什么?
因为这些部分是自动化的理想对象。相关信息来自数据库模式,因此可以简化为这些信息。
接下来,您可能会抱怨这些生成的表单不太适合您的需求。确实如此。
但为什么呢?
您无法控制生成的布局,除非逐个选择表中的列并选择您想要的控件,或在 IDE 中进行这些设置。数据源的基本设置是按列进行的。
在我看来,这并不好,因为您必须在通过拖放创建表单之前就做出选择。因此,这也不好,因为您是针对每个表单单独进行这些更改,而不是根据项目需求,这可能导致因疏忽而做出不同的选择。例如,您在一个表单中忘记了电话号码的格式化,但在另一个表单中却做了。
有解决办法吗?
您可以选择在 IDE 中进行设置。以下是设置界面:
但这仍然不是问题的最佳解决方案。您无法按项目来设置这些配置。您或许可以导出和导入 IDE 设置,并可能自动化这个过程,但这与 IDE 相关,而不像您的选择那样与元数据相关。而且,这也与工具相关,如果您将来更换 IDE,这些信息可能会丢失。
在我看来,最好的解决方案是将有关使用何种控件的信息间接地附加到列的类型上。为此,您可以创建自定义的数据库列类型并使用它们,或者您可以将整个模型信息从目标数据库中移出。
转向建模方法
上一部分展示了直接使用工具并在项目中通过为每个表行或在 IDE 的项目设置中选择控件类型而添加过多信息时出现的一些问题。这里的要点是以下几个问题:
- 当您想更改应用程序表单中所有电话号码的控件类型时,您会怎么做?
- 您会逐个检查每个表单并修改所用的类型吗?
- 您如何知道所有电话号码都在哪里被使用?
这时,您应该开始考虑建模和使用元信息了。您不仅可以通过代码生成加速所有表单和实体类的创建(IDE 只部分实现了这一点),而且如果您在架构设计中将手写代码与生成代码分开,就可以一次又一次地重复这个过程。
如果您能控制表单和其他源代码工件的创建,您就可以通过从您的领域类型进行映射来控制所使用的控件(也就是说,不为电话号码类型使用文本字段,而是使用 phonenumber 类型本身)。这样做,您就可以通过所用类型的映射来定义目标控件类型,因此该类型的每次使用都会反映出一致的外观和感觉。
开始建模
为了展示一些实际操作,我将为您开始建模一个小的通讯录应用程序。这是最终生成的应用程序,100% 自动生成,包括完整的项目文件:
该应用程序应将您的联系人存储在数据库中。这是一个典型的数据库相关应用类型,是使用 UML 建模和代码生成的理想选择。请注意每个联系人的子网格。一个联系人可以有多个电话号码和多个地址。
如果您已经下载并启动了 ArgoUML,请按照以下步骤创建一个有效的模型。首先,您需要为模型命名。将其命名为 AddressBook。
更改项目名称和内部的包名后,您将得到以下模型:
包名稍后将用作应用程序名——对于更大规模的模型和项目,以后可能需要多个包,但这是另一个问题。
完成初始设置后,向模型中添加一些基本类型。这里您可以看到一些后续步骤原生支持的基本类型。
具体来说,添加一个 phonenumber 类型,您将在**接下来的文章**中使用它。电话号码将演示如何更改并解决前面提到的问题。然后,您需要为新应用程序创建一些类。添加 Contact、Address 和 Telephone 类,并为其包含的属性指定类型。(在 Telephone 类中,Number 属性请继续使用 string 类型)
要得到最终的模型,您需要添加一个新的构造型(stereotype)以在聚合关系中使用。所用的构造型定义了对应用程序的一个需求。为了在应用程序中启用子网格并打开详细信息,您必须以某种方式指定它。这样做是为了不必对模型中的每个聚合都进行此操作,而只针对您想要的类关系(聚合)。要创建构造型,请在图中的 AddressBook 上右键单击,并添加一个新的模型元素(构造型)。
将构造型命名为 masterdetail_action,并检查其基类(Basisklasse)是否为 Association。然后在构造型属性中为聚合关系选择这个构造型。如果您没有看到新的构造型,说明基类没有设置。(注意:**在模型导出时,基类必须为空**——稍后会详细说明)。
现在您有了一个如下图所示的模型:
这些关系(聚合)都有名称。其含义如下:如果在表单或网格中显示外键值,应改用下拉框,并且显示名称是关联关系括号中的名称。
现在模型已经完全创建好了,您可以准备将其转换成一个应用程序了。因此,您需要从“所需工具”部分下载二进制示例安装程序。安装后,您会在桌面上找到这样一个图标:
它会启动应用程序原型工具,您可以在其中导入模型。但首先,您需要将 UML 模型导出为 XMI 文件(在文件菜单中)。
注意:在导出 XMI 文件之前,请从构造型中移除基类。否则,目前这会导致导入和后续步骤中断。您只需要基类,以便在建模时能够在属性中选择该构造型。(我有时间的话,会在 XSLT 模板中创建一个变通方法)
完成此操作后,启动应用程序原型工具,我仍然称之为 lbDMF,但其背后的应用程序是 wxWrapper。这是因为您将要启动的应用程序本身也是一个原型!
当您开始导入 XMI 文件时,请注意您会看到一个红色的属性字段。这是为了提醒您在更改 XMI 输入文件时,不要忘记将初始数据库名称命名为项目名称或更好的应用程序名称。
另请注意,为撰写本文档,出于安全考虑,我没有覆盖我上一个 XMI 文件。我已将文件命名为 *AddressBook1.xmi*。这不重要。请将数据库名称更改为您为包选择的名称,例如 AddressBook。然后从文件菜单导入 XMI 文件。
然后您会看到一个安全对话框,如果一切正常,您必须点击“否”。
如果您没有勾选一个写入 XMI 设置的菜单项。这或多或少已经过时了,因为设置是通过 XSLT 参数传递到生成过程中的。
或者
这是因为当您第二次重复导入并选择为建模的应用程序创建数据库模式时,您可能没有选择覆盖应用程序数据库。这会影响生成的 SQL 脚本,其中将包含 **drop table** 语句。请确保您没有重要数据会丢失!
在这种情况下,应用程序数据库将是第一次创建,不会删除任何表,否则您会看到如下消息提示:
接下来的两个对话框会询问您是否要对应用程序数据库和模型数据库执行此操作。第一次都可以回答“是”。第一个问题让您跳过创建应用程序数据库,第二个问题让您跳过导入到系统数据库(其中包含应用程序的模型)。
当您完成导入步骤后,可以从菜单中重新加载应用程序。起初您不会看到 AddressBook 应用程序,但在第一次重新加载正在运行的 lbDMF 管理器后就会出现。
此时,您可以打开导入的应用程序并尝试输入一些数据。这是应用程序的原型阶段。可以像这样导入一个应用程序模型(XMI),然后直接运行该应用程序。原型是您在决定最终通过代码生成创建的目标应用程序之前的任何阶段。
注意:您正在使用一个来自 XMI 模型(使用 BoUML 和 XMI 2.1)的原型。
但我将跳过这一步,直接进入生成的应用程序。因此,您需要下载 CAB DevExpress 编译安装程序,并将其安装到建议的位置(C:\lbDMF),即使它提示文件夹存在问题。完成后,您就可以创建我在开头展示的应用程序了。
点击“Next”(下一步),直到在名称字段中找到 AddressBook。然后按下“Codegenerieren”(代码生成)按钮,并为本文要使用的模板选择一个目标文件夹(本例中为 C:\lbDMF)。
然后点击“Ja”(是)。
并从 CAB DevExpress 编译文件夹中选择模板。
如果一切顺利,您将创建一个应用程序,只需要一个 Sqlite .NET 程序集即可编译和运行。
使用代码
以下下载包含您需要的所有必要材料,例如 UML 模型。重复建模可能会引入错误。因此,我将包括 XMI 文件(原始文件和本文档编写时使用的文件)以确保您成功。zargo 文件也包括在内。重复建模所需的工具不包含在此处,因为它们可以从其原始来源获取,并在上面的“所需工具”部分中链接。
如果您在操作过程中遇到任何问题,或者对本文有任何改进建议,请联系我告知。
- AddressBook 模型文件:下载 AddressBook.zip
兴趣点
下一篇文章将包含自定义模型和创建一个电话号码控件,以用格式化的电话号码文本框替换第一个版本中的文本字段。相关问题已在上面提到,在我看来非常重要。但这超出了简单建模的范畴,涉及到修改 XSLT 模板,包括生成新的格式化电话号码文本框的代码片段。
我也希望得到普遍的反馈。如果您关注这里在 CodeProject 上的产品公告,我至少创建了一个统计页面,通过打开该页面来尽可能地获取一些反馈。
历史
这是初始版本。