转自博客中国 MIDDLEWARE 著,陈龙译
1 执行摘要
最近,对象管理组织(Object Management Group, OMG)发布了一种新的服务器端软件开发的思维模式,即模型驱动架构(MDA)。MDA 不同于以往传统开发方法之处在于使用MDA 你首先要用UML 构建对象模型,然后通过代码生成工具和模式库(pattern repository)从对象模型生成代码。OMG 认为MDA 有许多优点,其中最令人兴奋的
就是开发人员生产率的提高。
这一案例研究的目的就是验证或反驳关于基于MDA 的开发工具可以提高软件开发生产效率的声明。两个团队开发同样的J2EE PetStore 应用,一个团队使用了基于MDA 的开发工具,而另一个团队使用传统的企业级集成开发环境(IDE)以代码为中心(code-centric)的开发方式开发。
研究的结果是,MDA 团队的开发速度比传统的团队快35%。MDA 团队在330 小时内就完成了开发任务,而相比之下传统的IDE 团队用了507.5 小时。作为这一案例研究的结论,The Middleware 公司推荐那些致力于提高开发效率的项目组可以在他们的项目中尝试使用基于MDA 的开发工具。
2 介绍
通过这一案例研究,你将了解到MDA 开发方式的概况,并且能够看到一个接受这种开发方式的团队获得了什么样的生产率。如果你正在寻求如何使项目中的开发人员的生产率最大化,这份案例研究是你必读的。
2.1 什么是模型驱动架构(MDA)?
模型驱动架构是一种旨在使业务逻辑和应用逻辑与技术进展相分离的软件开发思维模式。MDA 可以帮助你快速构建出与中间件无关的,具有优良架构,坚固的,可维护的代码。
MDA 开发方式的关键点在于以下这几步开发过程:
1. 确定应用程序的业务需求。
2. 画出业务模型的UML 图,这些图与任何具体实现它的开发技术(J2EE,.Net,CORBA 等)都无关。这个UML模型代表了核心的业务服务和组件,例如可以有定价引擎,购物车,订单处理等模块。因为它完全和技术无关,所以这个UML 模型叫做平台无关模型(Platform-Independent Model, PIM)。也就是说,不管你使用J2EE 还是.Net,这个UML 模型都是一样的。你可以用一个MDA 专用建模工具来建造这种UML 模型。
3. 画出应用程序的UML 图,这些图指定与某种技术(比如说J2EE)相关。这个UML 模型包含特定技术的元素,比如说特殊的J2EE 设计模式。这个UML 模型叫做平台相关模型(Platform-Specific Model, PSM)。你可以手工建模,也可以用一个MDA 工具生成它的大部分,然后手工调试需要特制的部分。
4. 最后,用一个MDA 工具生成应用程序代码。也就是说,不是基于UML 模型手工编写程序,而是从UML图生成程序的大部分。如果是J2EE,MDA 工具可以生成绝大部分servlet, JSP 和EJB。你剩下的工作就是填补上UML 无法建模的细节,比如业务逻辑。
2.2 谁支持MDA?
对象管理组织(OMG)创造了模型驱动架构。OMG 是一个业界标准组织,有几百个组织成员,包括IT 用户和开发商。OMG 是几种被广泛使用的标准的管家,包括统一建模语言(UML)和通用对象请求代理架构(CORBA)。因为用OMG 的开放过程制定,所以MDA 是一种中立于开发商的方法,任何厂商都可以创建一个用于辅助MDA 开发过程的MDA 工具。关于MDA 的更多信息请参考OMG 关于这一主题的白皮书,位于http://javacentral.compuware.com/pasta下载)测试了双方的代码的非循环依赖性(acyclic dependencies)。两个团队在非循环依赖性测试中都得了90%的高分。
最后,因为我们知道很多代码生成工具能够产生"坏代码",所以我们检查了双方生成的代码。根据我们的检查,我们相信生成的代码质量很好。
3.5 团队概况
我们竭尽全力确保两个团队具有大体相近的技术集(skill-set),不会让一个团队比另一个具有无法比拟的优势。每一个团队成员都具有在多种应用服务器上进行J2EE开发的丰富经验。此外,为了平衡技术集之间的差异,我们花了很多时间把开发人员按照他们愿意使用的工具和技术做了调整。两个团队还解决了一些小的编队问题。这些时间不会被计算在最终的生产率数据中。
每个团队包含3名成员:
一名高级J2EE架构师。这个人掌握自己开发环境的技术细节。他的职责是开发,做架构,合理地分配任务,最终实现规范。
两名经验丰富的J2EE程序员。这些人都具备至少3年的J2EE应用程序开发经验。
3.6 项目计划和管理概况
为了准确地记录每个团队工作日志,我们分别和每个团队每周召开例行电话会议。在电话里我们对两个团队每周的经历作了详尽的记录。两个团队都必须回答下列问题:
*你的团队这周作了什么?
*从效率的观点看,这周好的方面有哪些?
*从效率的观点看,这周哪些方面存在问题?
这些记录的摘要会在这份案例研究的下一节作介绍。
在项目开始之前我们举行了一个项目开工仪式,仪式上每个团队都估算了他们多长时间能够完成项目。另外,每个团队每周都要提交上周的详细时间表。时间表包括估算时间和实际使用时间的对比。
4 研究结果
在这一部分我们将论述案例研究的结果。结果被分为如下几个部分:
在架构分析部分你将了解每个团队使用的架构和J2EE模式。我们在文档后面创建了一个专用设计模式术语表来简要地解释每种模式。对于有抱负的J2EE架构师来说这个术语表将是一份有趣的阅读材料。如果你不熟悉J2EE模式的话,你最好在阅读架构分析部分之前先阅读这个术语表。
在定性分析部分你将了解到每个团队对他们选择的开发方法的感性的思考。你将了解每个团队遇到的问题和他们是怎样克服问题的。在定量分析部分你将会看到每个团队最终的生产率数字。
4.1 架构分析
4.1.1 UML和代码生成
两个团队都创建了对象模型的UML图。而其实两个团队创建的的对象模型非常相似。每个团队都作了如下抽象:
*用户账号
*用户资料信息
*产品
*产品目录
*供应商
*购物车
*订单
*排列项
传统团队用了一种开源工具为他们的对象模型创建UML图。他们确实是为了设计和沟通的目的画的UML图,而不是为了从UML自动生成J2EE代码。不过,他们确实用了他们IDE的向导功能生成了JavaBean的accessor/mutator方法(也就是geter/seter方法),EJB组件,struts代码,异常处理代码和加速实现接口的桩代码(stub-code)。
MDA团队用他们的MDA工具不仅创建了平台无关模型还创建了平台相关模型。他们用MDA工具的UML代码生成功能自动生成了比传统开发团队多的代码。生成的代码有JSP,EJB组件,Struts代码,异常处理代码和接口,还有许多设计模式和构建应用程序时用到的框架代码。不仅仅是框架代码,MDA工具还在代码生成模式(code-generation patterns)的基础上利用UML对象模型生成了一个可以运行的应用程序。
4.1.2 Web层
两个团队在Web层都使用了servlet,Java Server Page,和JSP标记库(taglibs)的组合。两个团队都用了Apache Jakarta Struts作为他们Web层开发框架。Struts是一个流行的建造基于J2EE的Web应用的开源框架。它鼓励使用广为接受的Model-View-Controller(MVC)设计模式。两个团队都调整了生成的代码使其更符合MVC思维模式。
4.1.3 EJB层
从架构性的观点来看,两个团队的EJB层代码的具体不同之处在于他们选择的模式。
模式 传统团队 MDA团队
Session-entity wrapper Yes Yes
Primary Key generation in EJB component Yes Yes
Business delegate Yes Yes
Data Transfer Objects(DTOs) Yes Yes
Custom DTOs Yes Yes
DTO Factory Yes No
Service Locator Yes No
JDBC for Reading via Data Access Objects(DAOs) Yes No
Business interface Yes No
Model driven architecture No Yes
从上表可以看出,两个团队都用了很多J2EE设计模式。虽然这样做在开发PetStore这样的应用时显得大材小用,但是我们还是想使用在实际项目开发中用到的模式,这样就更能够测试出MDA生产率的真实水平。
另外还请注意,传统开发团队使用了比MDA团队更多的模式。当我们一开始做好这个比较表时就注意到了这一点。传统开发团队使用了额外的模式是否会使这次案例研究失效呢?毕竟,传统的团队使用更多的设计模式会让人认为他们的开发过程会自然地被拉长。
为了回答这个问题,我们仔细分析了被使用的每个模式。我们也会见了两个团队的成员。完成这次研究后,我们关于这一问题的一致意见是虽然传统团队使用了更多的模式,但是比较结果还是非常正确的。为了帮你理解为什么是这样,让我们看看每个传统团队使用了而MDA团队没有使用的模式吧:
The service locator 模式没有给传统团队添加额外工作。实际上这个模式还节省了他们的时间,因为它简化了EJB层的客户端代码编写,也包括EJB组件调用其它EJB组件的情况。由于是使用一个类中的静态方法实现的,所以它减少了必要的代码行数。所有对EJB的访问都是由这些方法完成的。
The JDBC for Reading via DAOs 确实需要传统团队花时间去实现;然而,如果假使他们不用这个模式的话,他们就不得不写实体Bean来替代这些数据访问对象(DAO)了。还有,MDA团队需要手工编写代码来排序数据,而这些工作传统团队可以通过JDBC for Reading模式完成。所以说,这种模式实质上没有给传统团队增加任何工作量。
The business interface pattern 没有给传统团队带来任何工作量。据他们讲,每个接口大概需要10分钟。因为要使用MDA推荐的平台无关模型创建业务对象模型,所以MDA团队也要创建业务接口,只不过层次更高而已。
The DTO Factory pattern花了传统团队一点实现和测试的时间。但是由于这种模式减少了应用程序中的代码量,所以实际上还是节省了他们的时间。
同样值得注意的是传统团队拥有世界顶级的J2EE模式专家(Owen Taylor,我们J2EE模式教程的作者)。这种专业的模式知识不是普通的IT开发组织所能拥有的。所以传统的团队使用模式比MDA团队多就可以理解了。正是因为传统的开发团队选择的模式没有拖延他们开发的时间,所以我们得出的结论是没有明显的迹象表明这次生产率比较是无效的。
4.1.4 安全
两个团队开发的应用程序大部分都是相近的。不过两个团队在安全方面却产生了差异。
传统团队使用了一个身份验证过滤器(authentication filter)来解决安全问题。这个过滤器察看当前请求的页面是否是受限制的,如果是的话就要看用户是否已经登录了(登录信息保存在HTTP会话里)。这个过滤器完全是这个团队自己写的。过滤器实现javax.servlet.Filter接口。
相比之下,MDA团队使用了MDA工具辅助开发安全系统。他们的MDA工具提供了一个安全框架可以使他们从不同的身份验证方法中选择,这些方法其中包括简单验证,基于摘要的,基于表单的,和编程实现的验证。该组选择了编程的方法。这一框架还提供了登录和退出的JSP页面,该组定制了这些页面把他们用在了PetStore中。
4.2 定性分析结果
在这部分,我们将评论两个团队感性的思考,这些是从他们每周提交的资料中总结出的。
4.2.1 传统团队
4.2.1.1 传统团队第一周
传统团队采用迭代式的原型法开发。在第一周里,他们搭建了一个简单的原型,这样就可以架构他们项目的设计模式基础。对于他们来说建立一个得心应手的开发环境是一件相当棘手的问题。在让StarTeam版本控制和他们的IDE有效结合的过程中就遇到了一些问题。在第二周他们才下决心用替代方法绕过这一问题。第一周他们还花了很多时间在架构对象模型上,比如确定包结构等和开发环境有关的问题。
从生产率的观点来看,第一周他们印象最深的就是IDE的能力。他们发现IDE和被选择的应用服务器集成得很好,而且也具有很好的代码生成能力。这都得益于每个团队成员都有以前使用这种IDE的经验。
这周他们生产率存在的问题和文件共享,沟通交流,执行代码复查,维护包结构的稳定性有关。
4.2.1.2 传统团队第二周
第二周,传统团队开始分配不同的开发角色。一名队员负责model(EJB)层,另一个队员负责View(web)层,第三个队员提供两个层之间的辅助类和接口。该队决定以用例的方式构建他们的系统,一次只关注一个用例。这一周他们在开发用户账户维护用例,例如
登录,退出,用户创建和用户偏好维护。
从生产率的观点来看,这周他们发现Struts框架发挥了作用。他们发现编写Struts代码的效率很高。另外他们还决定使用一种让web层和业务层解耦的策略。这种策略让实现"桩"的代码能够植入没有完全建好的代码中。他们通过属性文件和附录中的业务代理(business delegate)设计模式在"桩"和"真实"代码之间切换他们这周的生产率问题都是一些开发团队在开始会遇到的典型问题,例如坚持使用源代码控制。在IDE的使用上也遇到了困难。情况是,如果他们试图从IDE生成J2EE组件然后修改的话,这些修改过的组件就很难再逆向到IDE中
4.2.1.3 传统团队第三周
这周,传统团队继续开发他们的产品目录浏览和购物车等功能。
从生产率的观点来看,这周他们解决了如何使用版本控制协作开发的问题。他们还构建了队员用到的接口库,这样就减少了构建时(build-time)的依赖性。在开发的这一阶段,每个队员的效率都非常高,而且由于项目模块分解的非常合理,每个队员都有自己的工作领域。还有的就是他们的IDE在代码生成上也起了很大的作用。
他们这周的生产率的唯一问题就是对PetStore规范描述的需求的理解和执行了一些对购物车部分的重构。
4.2.1.4 传统团队第四周和第五周
在最后两周里,传统团队在对最后一个用例编码,测试和调试后完成了他们的应用程序。他们还合并了队员的代码,去掉了实现桩的代码。这周获得高效率的因素有这么几点。他们始终得益于选择的桩实现架构。只要他们把接口确定下来就基本不需要什么沟通了,所以编码的效率非常高。同时,因为他们的IDE在WSDL自动生成和SOAP服务部署方面的能力,他们的web服务实现构建得也非常快。
这周遇到的问题包括对代码的重构和重新分析,例如在数据访问层就存在一些缺陷。由于他们的应用分成好多层也导致了一些问题,因为当出现错误时除非仔细查看这些层否则就不清楚问题出在哪一层。他们还有其他一些无足轻重的问题和Struts和属性文件有关。
4.2.2 MDA团队
4.2.2.1 MDA团队第一周
第一周,MDA团队作的都是一些一般项目团队在项目开始时做的典型步骤。他们用MDA工具的UML建模能力创建了一个详细的对象模型。配制好了他们的源代码控制系统,然后就把项目任务分配给每个队员。他们还设置了一个项目目录结构并作了一些初始的开发工作。
从生产率的观点来看,好的方面就是他们发现不需要建造过多的组件,因为MDA工具具备生成这些代码的能力。实际上他们还发现工具不仅能够生成这些组件,还能生成框架代码把这些组件连接起来产生一个有机的应用程序。该团队估计应用程序的50%到90%都可以自动生成,包括web页面,Struts action,EJB实体bean,EJB会话bean,J2EE设计模式的框架代码和数据库表。
这周的关键问题是掌握MDA方法的核心思想。这种方法和他们以前用的传统方法不一样,他们需要抓紧时间来熟悉工具提供的许多层和结构。
4.2.2.2 MDA团队第二周
第二周,MDA团队开始投入到开发工作中。他们完成了网站的很多部分,包括UML对象模型,组件框架,站点导航系统,JSP模版(用Dreamweaver开发),主页,EJB购物车的大部分功能和用户账户管理的一小部分。
从生产率的观点来看,好的方面是他们能够从UML对象模型生成EJB会话/实体bean代码,web层代码,和一个DDL模型。创建测试数据集也同样非常简单。最后,由MDA工具生成的整体应用程序框架可以使他们快速地把组件组装起来。
这周遇到的困难和传统团队遇到的差不多。他们有一些开发环境上的困难,包括在一个协作的开发环境中习惯使用源代码控制系统。他们花了一点点时间就把工具配制好了。他们也知道着手使用MDA工具需要时间来学习,所以在这周里他们都在不停地学习以适应从传统的开发方法转变到MDA的思维模式上来。最后,他们意识到MDA的代码生成能力有点过于强大了,生成了一些他们不需要的代码。他们确实注意到有必要修改工具用于生成代码
的算法。在一个实际的项目中这样做可能会减少麻烦,但是这超出了这次案例研究的范围。
4.2.2.3 MDA团队第三周
第三周,MDA团队完成的系统用例比上周多了几个,包括购物车,订单处理,账户管理,登录模块。从效率的角度来看,这周有几件好事。由于MDA工具辅助生成了代码,他们非常容易就构建好了安全系统。他们使用JSP模版的想法也起了作用。把JSP的通用代码集中在JSP模版中,这些通用的代码就可以集中在一个地方更新了。
这周有一个开发人员开始体会MDA方法的好处,并且情不自禁地做出了如下结论:
MDA 的价值和OO 的价值相似,只要在设计阶段多下功夫,在实现阶段就能得到回报了。一旦你做了一两个应用程序之后,你就会真正开始从它受益。不过这周他们也遇到了一些困难。在Struts上遇到的一些细节问题一度造成他们工作停顿。他们还有一些会话
标识符和浏览器的cookies的问题。这周最后遇到的问题是关于MDA的。他们发现由于在认为应该生成的代码和实际生成的代码之间存在差距,有时会感到开发工作非常郁闷。有时他们的开发工具要么产生他们并不需要的代码要么产生过剩的代码,这些都无助于提高效率。他们认为这些问题都是由于他们在MDA和代码生成上的经验不足造成的,因为他们在预测将会产生出什么代码时毫无经验。他们相信随着使用MDA工具的经验的增加这些问题将迎刃而解,而且是用得越多,效率就越高。正是由于对MDA工具一时的不熟悉,导致他们的时间有点拖延。
4.2.2.4 MDA团队第四周
第四周,MDA团队完成了他们的开发、测试和调试任务。
从提高效率的角度来看,MDA代码生成,以及由MDA提供的Struts框架,身份验证框架都是值得肯定的。同时,模块集成过程也进展顺利。
这周遇到的问题是有时生成的代码变成了一种负担。他们要么彻底修改,要么丢弃不用。不过他们也认识到MDA工具生成的代码是基于模式的,这就给他们手写代码助了一臂之力。他们也有一些MDA工具的源代码合并问题。他们吸取的教训是当你使用一种象MDA工具一样的产品时,你必须随时掌握工作的进展,并且要注意如何使用好版本控制把他们编制到一起。
4.3 定量统计结果
每个团队最终使用的开发小时数统计结果:
团队 初始估算小时数 实际的小时数
传统团队 499 507.5
MDA团队 442 330
就像你看到的,在这次案例研究中MDA团队取得了绝对性的胜利。他们在预算的时间之内完成了任务。需要强调的是MD团队不是立刻就利用了这种效率上的优势,而是随着项目的展开效率的优势才逐渐显现出来。队员把这归咎于MDA工具,因为它对于绝大多数开发人员来说都是一种新的产品,所以需要一个适应的过程。实际上有一个队员认为作为他们用这种工具开发的第一个项目,如果不存在这个学习的过程的话他们应该比实际的情况还
要再快10-20%。
另一点也需要强调,在这个项目里我们没有执行"bug跟踪";不过我们作了前文提到的手动用例测试。有意思的一点是在对传统团队的测试过程中发现了一些bug,但是MDA团队却没有。我们相信这是由于使用MDA开发方式产生的代码的坚固性造成的。
5 结论
根据这次案例研究的结果,The Middleware公司被MDA团队使用模型驱动架构所获得的效率所折服。我们鼓励那些致力于提高开发效率,特别是那些涉及企业级应用和Web服务的组织,在项目中尝试使用基于MDA的软件开发工具。当然有必要给开发团队短期的MDA方法和开发工具入门时间,由于在开发的过程中,特别是以后的应用中才能收到效率的回报,所以付出的努力完全值得。
我们认为MDA还有其他的一些价值。比如,平台无关模型(PIM)具有相当长的预期使用期限。软件开发组织有必要创建一个这样比技术生命周期还长的业务对象模型。和使用不同的工具和技术的开发人员交流时,这将是一个非常重要的工具。
我们觉得MDA的另外一个优点就是可以让一个组织中具有渊博知识的架构师确保平均水平的开发人员能够协调一致地使用设计模式。用MDA工具自动生成实现模式的代码,然后按照架构师的意图作调整,架构师就可以做到这一点。这样,使用模式就很自然地变成了开发人员编码工作的一部分。
我们有一个队员是这样评价MDA的:"它让一名脑外科医生成为一名更好的脑外科医生,但是不会让一个看大门的人成为脑外科专家。"他的意思是MDA让一个有经验的架构师的能力得以充分发挥,能够更好地把握项目的方向。同时你还要你的职员了解J2EE模式和最佳实践,面向对象的开发,和一些架构方面的考虑。
最后,在代码和应用程序质量方面,一个很突出的观测结果就是在手工编写代码时发现的bug需要修改和复测,而修改和复测还将不断影响整体开发质量。MDA团队通过模版自动生成代码就不会有这些额外的步骤了。
有必要指出,这次案例研究中很多MDA的特性没有被评估到,比如应用程序的性能和可维护性。我们确实也作了一些必要的性能测试,用来考查两个应用的性能是否相近。但是为了得到全面客观的结果,我们觉得可以把这些测试放到今后的研究中。同样,我们想在可维护性方面进行比较也将是非常有意思的,你将看到相比一个用传统方法开发出的系统,改变MDA建造的系统的代码将是多么容易的事。毕竟,当你重构一个基于MDA的系统
只需修改原来的UML模型然后再重新生成代码即可。