第五章支持构件组装的开发环境
本章以上述相关理论与技术研究为基础,实现了一个支持构件组装的开发环境,MyWebFw,并详细说明了MyWebFw实现的指导思想、环境构成、关键技术以及开发流程等内容。MyWebFw是基于DSM的支持构件组装的开发环境,在实际应用中,可明显的提高软件开发效率与产品质量。
5.1MyWebFw指导思想
图5-1 MyWebFw概念层次
MyWebFw是一个支持构件组装的开发环境,以DSM作为开发环境技术实现的指导,以构件组装作为开发环境开发方法的指导,借助XML模式描述特定领域元模型,作为GMF输入并快速生成特定领域建模工具,包括数据建模、构件组装建模、UI建模、流程建模、对象建模以及代码生成等工具,通过SWT/JFace实现其他图形化开发工具。借助特定领域模型与建模工具生成的快速性,可以快速且灵活的对其进行调整以适应特定领域。同时,MyWebFw面向应用开发,以构件组装作为应用系统分析、设计以及实现的指导,指导系统架构与框架的搭建,以构件组装作为特定领域建模工具内容搭建的指导,指导建立相应的面向应用的特定领域建模工具,以辅助系统分析、设计以及实现。最后,通过通用代码生成引擎,结合特定领域模型与样例代码整体模板化后的代码模板,生成100%的程序代码,从而实现了从高层构件组装模型产生完整的程序代码的目标。
MyWebFw首先是一个开发环境,以Eclipse作为基础开发环境,借助Eclipse Plug-in架构,以GMF(GEF/EMF)、MDT/OCL、SWT/JFace等Plug-in支撑技术构建Eclipse之上的图形化辅助开发工具,而以构件组装作为辅助开发工具开发方法的指导。同时,MyWebFw面向应用开发,提供应用开发的基础,SA与SF,并提供将以SF为基础构建的覆盖不同业务类型的样例代码整体模板化后的代码模板。最后,MyWebFw通过辅助开发工具调用通用代码生成引擎,结合特定领域模型与代码模板,生成100%的程序代码。
因为代码级构件无法直接在接口处显式定义组装,所以构件组装主要体现在MyWebFw的辅助开发工具以及SA上,而SF则以面向对象技术作为其实现的支撑技术。但,构件模型与代码级一一对应,并且存在如下2种应用场景:
(1)已存在代码级构件,建立该代码级构件的构件模型;
(2)不存在代码级构件,建立构件模型,通过代码模板生成代码级构件。
同时,组装模型不与代码存在关联,存在如下3种原因:
(1)构件组装的本质是通过接口或连接件建立关联并协调行为;
(2)连接件是构件组装的具体表现,粘接代码是连接件的最终实现。构件组装产生新构件后,连接件生命周期即告结束。连接件只存在于构件组装的短暂过程中。MyWebFw中,连接件与粘接代码的代码模板一一对应;
(3)组装过程,即通过连接件连接不同构件提供服务的接口,并重新封装为新构件提供服务的接口。同时,声明被连接构件提供服务的接口为新构件引用服务的接口,暴露被连接构件某些属性为新构件属性,最终形成新构件模型以及通过粘接代码模板与构件模板生成新代码级构件的过程。
MyWebFw不再重点刻画描述SA的抽象ADL,因为从程序语言发展的角度,ADL作为更高级的程序语言应兼容低级语言,即构件组装通过构件组装模型显式定义后,可具体映射到任何低级程序语言上,即以构件组装模型为基础,任何低级程序语言均可进行构件组装,只存在与模型语言语义断层的距离而已,所以,本文认为SA仅指导SF的搭建,SA最终具体体现在SF上。以SF为基础,建立起样例代码,并以构件组装为指导通过整体模板化制作为代码模板,其中包括构件模板与连接件的粘接代码模板,以及其他各类模板,如界面模板、Sql模板、各种属性及配置文件模板等。
与SF、代码模板相对应,MyWebFw建立起各种高层的抽象模型,以构件组装模型为核心,其他各类模型辅助,形成各种辅助开发工具,覆盖了软件过程中的设计与实现,设计即为各种建模过程,实现即为代码生成,而体现分析阶段工作的ADL则不具体刻画。MyWebFw的重点在于生成100%的程序代码,而ADL仅是SF搭建的指导,代码中无法具体体现,所以本文不进行刻画。
图5-2 MyWebFw概念层次
由于以构件组装模型与代码生成为基础,任何低级程序语言均可进行构件组装,MyWebFw可适应多种系统框架,默认提供目前较为流行的SSH(Struts,Spring,Hibernate)框架、样例代码以及代码模板,并可更换为其他系统框架,如WSB(WebWork,NanoContainer,iBatis)、JSB(JSF,PicoContainer,iBatis)等,只需相应的更换样例代码以及代码模板即可,从而借助通用代码生成引擎与代码模板实现无需变动辅助开发工具,即可完成对各种系统框架的灵活应对。
MyWebFw实现了从高层构件组装模型产生完整的程序代码的目标,使得开发人员可更多的面向业务分析与设计,可尽可能多的与用户讨论、界定以至最后准确掌握需求,而面向模型开发更使得软件开发接近于开发人员的思考与使用习惯,消除了面向代码开发的学习曲线与技术障碍,并使得在传统软件开发中由于分析、设计、实现之间的语义断层,造成的分析、设计意图不能完整地在实现中表达的问题得以解决,从而有效的提高了软件开发效率与产品质量。
5.2MyWebFw环境构成
图5-3 MyWebFw环境架构
如图所示,MyWebFw以Eclipse作为基础平台,以DSM作为开发环境技术实现的指导,以构件组装作为开发环境开发方法的指导,通过定义各种应用开发相关的元模型提供给GMF/EMF作为输入,迅速生成面向应用开发的各种辅助开发与建模工具,并在SA指导下迅速建立起SF,形成各种样例代码,通过样例代码的整体模板化形成代码模板,最后,代码生成引擎读入建模工具建立的特定领域内具体的业务模型并结合代码模板生成100%的程序代码。
MyWebFw具体包括如下几个层次:
(1)Eclipse Platform
EclipsePlatform基于OSGi建立的Plug-in架构提供了强大的扩展机制,使得开发人员将所需功能开发成Plug-in,即可发布、部署到Eclipse Platform上进行使用。目前Eclipse社区提供了丰富的Plug-in资源,为基于Eclipse Platform的功能扩展开发提供了各种基础类库与工具。
(2)基础层
基础层,即可运行在Eclipse Platform上的各种Plug-in,主要来自Eclipse社区。包括:图形化编辑框架GEF(Graphical Editor Framework)、MOF实现框架EMF、重新封装了GEF与EMF的GMF、模型开发工具MDT/OCL、SWT/JFace以及其他第三方Plug-in。MyWebFw主要通过定义元模型的XML模式、由GMF生成各种拖拽式的图形化辅助工具,以SWT/JFace为基础开发其他辅助工具。
(3)图形层
以基础层的各种基础Plug-in为基础,通过Eclipse提供的多种核心扩展点添加各种图形化功能,主要包括:
1)Platform runtime相关扩展点;
2)Workspace相关扩展点;
3)Platform text相关扩展点;
4)Workbench相关扩展点;
5)Team相关扩展点;
6)Debug相关扩展点;
7)Console相关扩展点;
8)User Assistance相关扩展点;
9)Language Toolkit相关扩展点;
10)其他。
常用的扩展点主要包括:
1)org.eclipse.ui.perspectives,透视图扩展点;
2)org.eclipse.ui.views,视图扩展点;
3)org.eclipse.ui.newWizards,新建向导扩展点;
4)org.eclipse.ui.editors,编辑器扩展点;
5)org.eclipse.ui.menus,菜单扩展点;
6)org.eclipse.ui.popupMenus,右键菜单扩展点;
7)其他。
(4)业务层
业务层面向应用开发,实现包括构件组装建模在内的各种辅助开发功能,以上述扩展点为基础,构建各种辅助开发功能的图形化实现。主要包括:
1)项目生成,用于生成包含SF,如SSH、WSB、JSB等,的空项目。
2)数据建模,用于简单的实体关系建模。
3)领域建模,用于划分业务领域,针对每个业务领域进行具体建模。
4)对象建模,对包括数据对象、域对象、视图对象等在内的多种对象建模。
5)构件建模,实现对各种构件的管理,包括新建、修改、删除以及查找。
6)组装建模,实现构件的组装建模,组装后重新生成新构件。
7)UI建模,用于简单用户界面建模,包括资源、逻辑、布局、UI构件等。
8)流程建模,用于简单业务流程建模,遵循XPDL、BPMN等规范。
9)代码生成,通过指定模板、模型以及生成位置等信息实现代码生成。
10)配置管理,包括数据库连接管理、类型映射管理等配置管理功能。
11)环境帮助,提供业务层各辅助开发功能的帮助文档。
12)其他功能,集成其他常用的功能Plug-in,包括国际化、正则表达式等。
(5)引擎层
引擎层主要为业务层提供各种图形化辅助开发功能的必要实现,主要包括:
1)通用代码生成引擎,与业务层中的代码生成图形化功能相对应。
2)数据库正反向引擎,与业务层中的对象建模图形化功能相对应。
3)通用项目生成引擎,与业务层中的项目生成图形化功能相对应。
4)其他通用引擎,与业务层中的其他图形化功能相对应。
(6)资源层
资源层为业务层提供辅助开发的各种资源文件,主要包括:代码模板与SF。代码模板主要用于代码生成,SF主要用于项目生成。通常在SA的指导下,搭建SF,并以此为基础建立样例代码,通过将样例代码整体模板化,形成代码模板,用于代码生成与项目生成。
(7)元模型层
元模型层主要提供给GMF作为输入来构建各种辅助开发建模工具,主要包括:数据建模、对象建模、构件组装建模、UI建模、流程建模等。
5.3MyWebFw关键技术
MyWebFw以Eclipse及其Plug-in作为开发环境的基础平台与扩展形式,以DSM作为开发环境技术实现的指导,以构件组装作为开发环境开发方法的指导,可以看出,MyWebFw实现关键技术主要包括Eclipse Plug-in开发技术,XML模式、EMF、GEF、GMF、SWT、JFace等建模与图形化开发技术,SA、SF、样例代码等系统基础设施搭建技术,代码模板、通用代码生成引擎等代码生成技术。
5.3.1环境层次
图5-4 环境用例
如图所示,MyWebFw面向应用开发、以构件组装为核心指导思想、参考MVC三层架构来搭建整个开发环境,在图形化界面方面指导各种模型设计,在代码模板方面指导SA、SF、样例代码的搭建,制作代码模板,完成代码生成。
MyWebFw需要同时考虑SA与模型设计两方面,均以构件组装为设计指导。
图5-5 SA层次
如图所示,SA的层次结构使用的是标准的Web应用中的MVC结构。
Client,默认为Web浏览器,也可支持其它形式的图形化客户端。
View,负责推送并接收页面展现,默认为Jsp文件,可支持其它形式。
Controller,负责流转控制,默认控制为Action。
Model,提供服务的模块,默认为被Action直接调用的Service。
Dao(Data Access Object),数据访问对象,提供对数据访问包装的对象。
图5-6 模型层次
如图所示,与SA对应建立上述模型层次,以支持开发时建模,主要包括:
数据层,负责实体关系建模,支持数据库正反向工程;
构件层,负责后台构件建模,构件可以为DAO、Service、Util、DO、PO等;
组装层,负责后台构件组装,可以由DAO组装成Service,可以由PO组装为DO,借助不同连接件及其代码模板,实现由小到大、由简单到复杂的组装。
控制层,负责前后台数据交换以及页面流转控制,支持各种界面框架。
界面层,负责简单界面建模,支持各种界面框架、UI构件与展现样式。
上述模型在设计、实现时遵循如下原则:
(1)组装原则,每层模型可以实现同层组装,上层模型可以实现对下层的组装,但各自的组装模型不同。
(2)开关原则,每层模型遵循针对具体SF的开关原则,即不需要时可关闭。
(3)MDA原则,每层模型尽可能划分为平台无关的描述模型与平台相关的实现模型,描述模型面向建模工具,实现模型则面向SF。
(4)翻译原则,实现模型对描述层遵循谁使用谁翻译谁实现的原则。
图5-7 SF层次
如图所示,根据SA以及模型层,SF采用SSH框架,并分为如下层次:
界面层,即UI层,负责接收用户命令、请求以及数据并传递给构件层处理,并负责展现处理结果。
控制层即MVC中的Controller,负责界面层与构件层之间的数据交互,界面流转的控制,同时负责简单的数据验证和格式化等功能。
构件与组装层,负责业务逻辑处理,包括数据验证、事物处理、权限处理等业务相关操作,是整个应用系统的核心。通常业务逻辑处理分为业务数据与业务操作两部分。业务操作由构件与组装层负责,业务数据即为各层间传递的对象。
值对象(ValueObject),泛指用于表示和携带数据的对象。它其中又包含了一些特殊的,对系统有特殊作用的对象,有数据对象(Persistent Object,PO)、域对象(Domain Object,DO)和视图对象(View Object,VO)。这些特殊对象将在以下做具体定义。
图5-8 对象关系
数据对象,表示需要被持久化的值对象。域对象,表示业务对象,指在业务操作时与业务流程直接相关的对象。本文认为Domain Object和Business Object表示的是相同的意思,因此在下面的沟通和开发中将使用Domain Object或其缩写DO对业务对象进行称呼。视图对象,指展示对象,只用来负责存储用于页面展示数据的对象,不参与业务的流程。封装类型(Encapsulated Type),实现技术语言相关。视图对象由多个域对象及封装类型聚合而成,域对象由多个数据对象及封装类型聚合而成。
图5-9 对象关系
在以上所定义的4种对象中,值对象的定义比较泛,它包含了其它3种对象。而其它3种对象也不是相互独立的,一个对象可以同时为数据对象、域对象和视图对象(见上图中的D区域),也可以只是数据对象或域对象或视图对象。例如,一个购物车对象参与了业务流程,但是它通常并不需要被持久化,因此它是一个域对象却不是一个数据对象;而一个配置信息对象通常需要持久化却不参与业务流程,因此也只是一个数据对象;一个用户对象通常既参与业务流程也需要持久化其状态,所以它既是域对象也是数据对象,既A区域;而当我们需要直接将这个用户对象推送到页面去显示时它又同时肩负起了视图对象的责任,既D区域。
数据层为构件组装层提供与数据源交互的最小操作方式,构件组装层完全依赖数据层所提供的服务。这些服务负责从构件组装层接收数据或业务实体,它屏蔽了实际业务数据与机器存储方式的差别。数据层由DAO层和系统服务层两部分组成。DAO层为每个业务实体提供最基本的数据访问服务,系统服务层为系统全局提供与业务关系不大的通用数据访问服务。
5.3.2元模型
本文使用EMF创建元模型,作为GMF配置生成构件组装建模工具的输入。EMF支持3种类型输入,本文使用XML模式。
<!-- 数据模型 --> <xsd:element name="data"> <xsd:complexType> <xsd:sequence> <!-- 实体 --> <xsd:element name="entity" type="entity"/> <!-- 关联 --> <xsd:element name="relation" type="relation"/> <!-- 连接集 --> <xsd:element name="connections"> <xsd:complexType> <xsd:sequence> <!-- 连接 --> <xsd:element name="connection" type="connection"/> ...... |
表5-1 数据元模型主体XML模式描述
如表所示,数据模型负责实体关系建模,主要由实体、关联以及数据库连接组成。详细约束如下:
(1)单个数据模型内可以存在多个数据实体;
(2)实体之间的关联关系存在1对1、1对多、多对多等多种关系;
(3)单个数据模型内可以存在多个数据库连接。
<!-- 构件 --> <xsd:element name="component"> <xsd:complexType> <xsd:sequence> <!-- 描述信息 --> <xsd:element name="descirptions" type="descirptions"/> <!-- 实现 --> <xsd:element name="implementations" type="implementations"/> <!-- 属性 --> <xsd:element name="properties" type="properties"/> <!-- 提供服务 --> <xsd:element name="services" type="services"/> <!-- 引用服务 --> <xsd:element name="references" type="references"/> ...... |
表5-2 构件元模型主体XML模式描述
如表所示,构件模型主要包括描述、实现、属性、提供服务、引用服务等。详细约束如下:
(1)单个构件模型只包含单个构件。
(2)每个构件模型只对应单个代码级构件,通过“实现”指定。
(3)每个构件模型存在多个属性、多个提供服务以及引用服务。
(4)每个“提供服务”对应单个组装模型。
(5)描述信息包含多种关键字,以方便构件的管理与检索。
<!-- 连接件 --> <xsd:element name="Connector"> <xsd:complexType> <xsd:sequence> <!-- 类型 --> <xsd:element name="type" type="type"/> <!-- 服务 --> <xsd:element name="refInterfaces" type="refInterfaces"/> <!-- 执行顺序 --> <xsd:element name="sequence" type="sequence"/> <!-- 实现 --> <xsd:element name="implementations" type="implementations"/> <!-- 属性 --> <xsd:element name="properties" type="properties"/> <!-- 保障机制 --> <xsd:element name="ensurence" type="ensurence"/> ...... |
表5-3 连接件元模型主体XML模式描述
如表所示,连接件模型主要包括类型、服务、执行顺序、实现、属性以及保障机制等。详细约束如下:
(1)单个连接件模型只包含单个连接件。
(2)每个连接件必符合顺序、选择、循环、并行中的某种类型。
(3)每个连接件通过服务连接多个构件提供的服务与引用的服务。
(4)每个连接件根据类型设定构件之间的执行顺序以及数据流转。
(5)每个连接件对应单个实现。
(6)实现可绑定到运行级的服务构件,也可绑定到静态的代码模板。
<!-- 流程 --> <xsd:element name="process"> <xsd:complexType> <xsd:sequence> <!-- 流程参数 --> <xsd:element name="parameter" type="parameter"/> <!-- 节点 --> <xsd:element name="node" type="node"/> <xsd:complexType> <xsd:sequence> <!-- 节点参数 --> <xsd:element name="parameter" type="parameter"/> <!-- 动作 --> <xsd:element name="action" type="action"/> <!-- 路由 --> <xsd:element name="next" type="next"/> ...... |
表5-4 流程元模型主体XML模式描述
如表所示,流程模型主要包括参数、节点、动作、路由等。详细约束如下:
(1)单个流程模型只包含单个流程。
(2)每个流程包含多个节点,每个节点可存在多个动作,动作之间可交互。
(3)每个节点对应单个路由,路由支持顺序、分支、合并、会签、传阅等。
(4)每个流程可设置流程全局参数,每个节点可设置节点局部参数。
(5)此定义可通过模型转换支持jPDL、XPDL、BPEL等其他流程定义语言。
<!-- UI --> <xsd:element name="ui"> <xsd:complexType> <xsd:sequence> <!-- 引用 --> <xsd:element name="reference" type="reference"/> <!-- 资源 --> <xsd:element name="resource" type="resource"/> <!-- 逻辑 --> <xsd:element name="logic" type="logic"/> <!-- 布局 --> <xsd:element name="layout" type="layout"/> <!-- UI构件 --> <xsd:element name="uicomponent" type="uicomponent"/> ...... |
表5-5 UI元模型主体XML模式描述
如表所示,UI模型主要包括引用、资源、逻辑、布局、UI构件等。详细约束如下:
(1)单个UI模型只包含单个界面描述。
(2)每个UI模型包含多个引用、逻辑、UI构件,包含单个资源、布局。
(3)资源以DOM描述,以XPath描述元素之间关系,对应后台视图对象。
(4)每个UI构件的数据描述通过XPath绑定到资源。
(5)每个UI构件的事件以及逻辑处理绑定到逻辑。
(6)每个UI构件均绑定到布局的某个位置。
(7)此定义通过模型转换支持XUL、XForms等标准。
(8)引用包括对CSS、Js、Tag、File等资源的引用。
(9)逻辑负责对自定义CSS、Js等描述。
(10)布局包括横向、纵向、Grid、Group、Tab、Stack、Deck等样式。
(11)UI构件包括Labe、Image、Text、Select、List、Tree、Button等。
图5-10GMF生成过程
通过上述元模型XML模式描述,即可输入EMF产生元模型ECore,再通过GMF快速定制生成上述特定领域建模工具。GMF生成过程如上图所示。
图5-11EMF/GMF生成向导
以数据建模为例,生成后建模工具如下图所示:
图5-12数据建模工具
以构件组装为例,生成后构件组装工具如下图所示:
图5-13构件组装工具
5.3.3代码生成
上述特定领域建模工具生成完成后,即可面向具体应用系统进行分析、设计,形成具体应用的特定领域模型,作为代码生成的数据模型。
图5-13 代码生成过程
代码生成的整体过程如上图所示,其基本原理即在代码生成时将各数据模型动态填充入或替换掉代码模板中的特性部分,也即动态内容。
运行机制为:将数据模型注入到上下文中;生成引擎从上下文中取得数据模型;生成引擎取得代码模板;根据数据模型和代码模板,生成引擎生成代码。
以域对象为例,使用VTL建立代码模板如下:
Package $packageName; public class $className implements IDomainObject{ #foreach($property in $thisClass.getProperties()) private $propertiy.getType() $propertiy.getName(); public $propertiy.getType() get${propertiy.getName()}(){ return this.${propertiy.getName()}; } public void set${propertiy.getName()}($propertiy.getType() $propertiy.getName()){ this.${propertiy.getName()} = $propertiy.getName(); } #end } |
表5-6 VTL代码模板示例
通用代码生成引擎核心代码如下:
//建立生成环境上下文 VelocityContext context = new VelocityContext(); //放入构件组装模型 context.put("ComponentModel",(new org.jdom.input.SAXBuilder("org.apache.xerces.parsers.SAXParser")).build("Component.xml")); //建立并初始化代码生成器 VelocityEngine engine = new VelocityEngine(); engine.init(); //读取代码模板 Template template = engine.getTemplate("Component.vm","UTF-8"); //设置生成代码名称 BufferedWriter bw = new BufferedWriter(new OutputStreamWriter( new FileOutputStream(new File("Component.java")) ,"UTF-8")); //生成代码 template.merge(context,bw); |
表5-7代码生成引擎核心代码
5.3.4关键类
MyWebFw实现关键类如下:
图5-14 模型相关关键类
通用代码生成引擎从提高性能的角度考虑,对应各特定领域模型分别实现了上述模型相关关键类,在代码生成时,将各特定领域模型数据赋值给上述关键类,在内存在多次、反复提取模型数据并生成代码,从而提高代码生成的性能。
图5-15 生成引擎相关关键类
上述为通用代码生成引擎的关键接口,即可以根据实际情况选择不同的生成技术实现,只要符合上述接口规范即可,从而支持多种类型代码模板的代码生成。
图5-16 Builder模式关键类
对应模型设计时遵循的开关原则,建立上述Builder模式关键类,即当不需要生成某层代码时,只要关闭该层代码的生成开关即可,提高了生成时的灵活性。
图5-17 代码生成界面
5.4MyWebFw开发流程
图5-18 MyWebFw运行流程
MyWebFw运行流程如下图所示:
(1)新建项目工程,建立包含SF或带有样例代码的项目工程。
(2)领域建模,针对某领域建立该领域的开发目录,并包含基本领域信息。
(3)域对象建模,针对该领域内的关键概念,建立其领域对象模型。
(4)数据对象建模,对应领域对象,建立其持久化用的数据对象模型。
(5)构件组装建模,针对领域内的业务逻辑建立各层次上的构件模型。
(6)UI建模,建立简单的用户界面模型,后期需加入美工相关工作。
(7)视图对象建模,建立领域对象与用户界面数据展示间的数据映射。
(8)控制建模,建立用户界面之间的流转控制以及与后台的交互控制。
(9)调整代码模板,针对特定领域调与SF整或新建代码模板。
(10)代码生成,结合特定领域模型与代码模板通过生成引擎生成程序代码。
如下图所示,上述建模与代码生成工作均在.model建模区内完成,代码模板则放在.template模板区,通过下述目录上的右键菜单目录调用具体的建模工具。
图5-19 开发目录界面
图5-20 右键菜单命令
5.5本章小结
本章建立起一个支持构件组装的开发环境,MyWebFw,以Eclipse及其Plug-in作为开发环境的基础平台与扩展形式,以DSM作为开发环境技术实现的指导,通过XML模式描述特定领域元模型,使用GMF快速定制生成特定领域建模工具通过SWT/JFace实现其他图形化开发工具。同时,以构件组装作为开发环境开发方法的指导,指导应用系统分析、设计以及实现,构建SA与SF以及样例代码。最后,通过通用代码生成引擎,结合特定领域内各具体的业务模型与样例代码整体模板化后的代码模板,生成100%的程序代码,从而实现了从高层的构件组装模型产生完整的程序代码的目标。