Middleware 公司案例研究团队
RRD 生产率案例研究, Middleware公司
2005 年 1 月 由于受到更快创建J2EE应用程序的不断驱动,模型驱动开发越来越引起人们的兴趣。被人们称作
"架构化快速应用程序开发"(或者ARAD)的一类工具是模型驱动工具中的"新兴工具"
。这些工具能够进行更高层次的抽象,比传统开发具有更高的生产率并且需要更少的J2EE知识。在大量采用这种模型驱动开发的产品中,ARAD方法是IBM的Rational
Rapid Developer (RRD)。它为J2EE开发者提供了极高的生产率,节省了构建服务器端应用程序所花费的时间。
1 概要
由于受到更快创建J2EE应用程序的不断驱动,模型驱动开发越来越引起人们的兴趣。被人们称作 "架构化快速应用程序开发"(或者ARAD)的一类工具是模型驱动工具中的"新兴工具"
。这些工具能够进行更高层次的抽象,比传统开发具有更高的生产率并且需要更少的J2EE知识。在大量采用这种模型驱动开发的产品中,ARAD方法是IBM的Rational
Rapid Developer (RRD)。它为J2EE开发者提供了极高的生产率,节省了构建服务器端应用程序所花费的时间。
在本案例研究中,我们按要求对RRD生产率进行了测试。两个团队开发一个完全相同的应用程序――其中一个团队使用RRD,而另一个使用传统的以代码为中心的IDE。研究的结果相差悬殊:RRD团队的开发速度比传统团队快10.7倍。RRD团队花费47.5小时完成了工作,而传统IDE团队却使用了507.5个小时。另外,RRD团队在相对较短的时间内完成了一些常用的增强功能。
由于这份案例研究,Middleware公司推荐那些致力于增加生产率的开发机构考虑在他们的项目中采用RRD。
2 引言
本白皮书对比了两个开发团队构建一个相同应用程序的生产率,该应用程序由业内专家通过一个功能性规格说明书进行了严格指定。该规格说明书为The
Middleware Company Application Server Platform Baseline Specification(《Middleware公司应用服务器平台基线规格说明书》),它是一个常见的J2EE
PetStore应用程序的严格指定版本。其中的一个团队使用IBM的 Rational Rapid Developer (RRD),这是一个采用模型驱动方法来进行J2EE开发的工具。另一个团队使用传统的以代码为中心的开发方法。
我们首先概述一下模型驱动的开发及其优点。然后介绍一下RRD如何实现模型驱动开发,重点介绍RRD区别于以代码为中心的IDE的关键特性。然后考查一下我们的研究结果――两个团队所生成代码的结构和质量、开发者根本的开发过程,当然还有定量结果。最后,我们要更深入地解释为什么会出现如此悬殊的差别。
2.1 什么是模型驱动开发?
模型是应用程序或系统的某些部分的简单抽象表示。我们可以建模的对象可以像构成用户接口的类一样具体,也可以像整个网络的数据和功能分布一样广泛,或者是界于两者之间的任何事物。我们可以以任意的复杂程度构建模型
:从在白板上手绘的方框图,到使用建模工具生成的复杂的UML图。
尽管模型很早就出现在J2EE开发中,但奇怪的是,实际开发却经常脱离模型。模型作为一个指导或者蓝图,但是开发者仍然要手工编写所有的实现代码。随着应用程序的进展,
开发者经常发现坚持使用模型所带来的约束要远远大于其用途。维护模型就变成繁琐的工作而不会产生帮助。
模型驱动开发(Model-driven development ,MDD)是一种能够将模型与实现更紧密地联系在一起的范例。使用MDD,模型不仅能用来封装应用程序的设计,还可以用来生成实现代码。
MDD通常由以下4个步骤组成:
1. 创建一个类模型。这包括定义数据项和业务操作。
2. 从模型中生成Java代码。MDD工具可以为任意您所指定的J2EE结构(servlets、JSPs、EJBs、SOAP对象)生成代码。
3. 为定义的操作提供实现代码。MDD工具能够完成CRUD操作。但是诸如placeOrder()
或 validateCreditCard()这样的自定义操作需要开发人员编写自定义代码。(注意,可以将这一步骤提到第2步骤之前,这取决于工具种类和建模方法)
4. 为将应用程序部署到特定的平台上,将其进行打包处理。
2.1.1
什么是 ARAD?
尽管可以从模型中生成代码,基本的模型驱动工具仍然需要开发人员手工的编写大量的基础代码来完成应用程序。架构化的快速应用程序开发(ARAD)利用应用程序的高层结构(架构),使模型驱动开发获得进一步发展。从而,ARAD工具大幅度加速了开发过程。
ARAD 工具的几项特性实现了以下几项功能:
- 首先,它们将模型抽象提到了一个更高的层次上。顶层模型中的类仅表示一个域实体,从该实体如何在应用程序中使用进行了抽象。该实体的实现方式有多种,可以作为一个业务对象、一条消息、一项web服务、一个JSP,或者上述全部,但是这些选择不是根据基本模型做出的。
- 其次,它们生成了基础代码,包括诸如部署描述符这样的非Java工件,因此与基本的模型驱动开发工具相比,它们生成的代码在应用程序代码中占更高的比例。从而使开发人员能够将精力集中来定义应用程序组件。
- 最后,它们所生成的是基于最佳实践上的"架构化"代码。架构师或者开发人员能够在他们以前建立的架构中进行选择,也可以定制它们或者定义新的。
2.2 MDD能够提供哪些好处?
模型驱动开发据称提供了以下这些好处:
更快的开发时间。 代码生成为您节省了多次手工编写相同文件所需的"繁杂工作"。例如,使用传统的方法,一个完整的bean程序需要3个或4个Java类,和1个或多个XML文件。一个"聪明"的MDD工具能够自动生成它们中的绝大多数。
架构化优势。在域层次上进行建模能够促使您实际思考系统背后的架构及对象模型,而不是让您完全陷入代码编写中(许多开发人员仍然在编写代码方面忙得焦头烂额)。在前期的建模方面多下点功夫,将减少后面的架构缺陷,这一点已经人所共知。
经过改进的代码一致性和可维护性。绝大多数组织在保持它们项目中的代码一致性方面存在问题。一些开发人员使用被广泛接受的设计模式,而另外一些则不使用。使用一个MDD工具来生成具有一致性算法的代码,而不是手工编写,能够促使所有的开发人员都使用相同的基础设计模式,因为每一次代码都是以相同的方式生成的。从维护方面来说,这是一项巨大的优势。另外,如果开发人员使用相同的设计语言,那么他们就能够更容易相互理解对方的代码。
提高了在不同架构、中间件供应商和平台之间的可移植性。根据定义,模型从它们所生成的代码抽象为某一个层次。一个MDD工具可以经过配置,从而生成具有特定配置和属性的代码主体。例如:
- 模型中的数据实体可以生成实体bean,JDO类或者是带有JDBC的传统的普通Java对象
(POJOs)。
- 模型中的屏幕设计可以生成JSP,显式的servlet或者一个Swing GUI。
- 模型中的部署设置可以生成任何特定的应用程序服务器的描述符,这些服务器可以是WebLogic,
WebSphere, JBoss 或者其他。
另外,模型甚至可以不受J2EE本身的限制进行抽象,使您能够从相同的模型中生成J2EE、.NET
或者 CORBA代码。
本白皮书的重点在于分析加快开发速度方面的获益。没有涉及MDD其他方面的潜在优势。
2.3 Rational Rapid Developer
(RRD) 和 ARAD
Rational Rapid Developer是一个用于创建服务器端Java应用程序的ARAD工具。RRD涵盖了J2EE开发的重要方面:UI、业务逻辑、持久性、通信,以及遗留系统与web服务的集成。
2.3.1
建模和代码生成
使用RRD进行的开发从一个类模型开始。类模型包含具有属性和方法的实体。模型中的类之间彼此关联。通常,类模型与数据库模式类似,至少在开始时是这样;事实上,RRD可以很容易地从数据库模式生成一个类模型,反之亦然。
任何模型驱动方法的一个有趣的方面是该方法如何将开发者提供的实现逻辑集成到模型中。绝大多数模型不能够完全描述一个应用程序。例如,当您在类模型中定义一项操作时,MDD工具可以为对应的方法生成一个带有存根的Java类。但是除了标准的CRUD操作外,MDD工具不知道如何为方法体生成代码。您将不得不亲自提供方法的实现逻辑。
RRD 通过在类模型本身中包含方法代码来解决这一问题。换句话说,也就是当您为一个模型类定义方法时,您编写模型中的方法,而不是作为生成的Java类的一部分。RRD
将方法代码作为元数据存入模型中,然后将其合并到所生成的Java类中。
这种方法对于开发者来说产生了两个重要结果:
- 编写的方法是"隔离的"而不是作为完整的Java源文件的一部分。习惯于上下滚动源代码文件来检查同一个类的其他成员的开发人员在开始时,会发现这种方法具有一定的挑战性。
- 通常,没有必要接触生成的Java代码。事实上,从RRD的角度来看,生成的代码是"不相关的"。这听起来有些名不符实;JSP开发人员很少查看从它们的JSP中生成的Java
servlet。
2.3.2 使用类模型
一旦类模型构建完成,RRD应用程序的开发就会将工作中心放在构建那些与模型中的类互相作用的结构上。RRD可以提供很多这种结构,包括web网页、消息,或者通用组件。每种结构都有其各自的仅包含所需的类、属性和方法的ObjectSpace(它自己的子集或者类模型的视图)。例如,为了创建一个显示单个客户和相关订单的详细信息的web页面,我们需要在该页面的ObjectSpace包含Custome类和Order类,但要省略Product类和Vendor类。将其同数据库模式做一个类比:如果类模型是整个模式,那么ObjectSpace就是表和字段的一个子集,对于对特定的数据库用户是可见的。
将该类比进行扩展,比如数据库模式能够包括可以进行计算的字段和虚表,那么您也可以在ObjectSpace中定义变量和方法;它们仅仅属于J2EE的父结构。
这种方法的结果是生成了相当多的从类模型中派生的Java类,这些类是为每一个在ObjectSpace中使用它们的结构而生成的。例如,如果您构建了5个不同的web页面,每个页的ObjectSpace包含模型Customer类,那么RRD将会为每一个网页生成一个独立的Customer类。并且每一个生成的Java类仅仅包含那些在ObjectSpace中实际使用的Customer的属性和方法。
这种方法对于产生的Java代码有重要的影响。下文的很多地方对此进行了讨论。
2.3.3
构建站点模型和样式模型
如果应用程序包含一个web前端,那么您可以创建一个站点模型。这是一个像流程图一样的图,它表明了站点有哪些网页和用户如何浏览它们。您可以使用这种方法来对站点的所有网页进行初始定义,后面再慢慢完善它们。
该站点模型可以作为站点的故事板。然而它并不生成实际的网页的浏览代码,它只是对您已经编好的网页进行链接。
您还可以为GUI创建样式模型。这些模型与文本文档的样式表有相似之处。它们包括预先定义的网页的布局和网页控件,以及颜色和字体方案。样式模型确保站点的网页有统一的外观和感觉。通过预先考虑绝大多数格式化的选择,它们还加速了网页的开发。
2.3.4
创建Web 网页
RRD提供了一个创建网页和其他的屏幕结构的WYSIWYG设计工具。您可以通过该工具将诸如Visual
Basic这样的控件这置在设计区域内,然后在ObjectSpace中将控件绑定到对象中,从而建立一个网页。例如,在一个详细的Customer网页中的数据项字段可以映射为在ObjectSpace中的Customer对象属性。RRD生成的代码在对象和网页之间建立链接。当运行时加载网页时,该字段也相应被赋值。
RRD还简化了网页之间的链接过程。例如,如果客户的详细信息网页包含客户订单表,那么表中的每一行能够提供该订单详细页面的链接。RRD将会生成一个URL,用于包含订单ID的链接。
RRD用于网页设计的方法将开发人员从下面两个乏味的工作中解放出来:
- 编写显式的HTML 脚本或者 JSP 逻辑。
- 编写网页的框架代码(例如 Struts)。
2.3.5
添加应用逻辑
类和站点模型定义完毕后,下一步的工作是添加应用程序逻辑。采用您定义和实施的自定义方法的形式。对于各自的网页或者其他结构来说,这些方法可以属于模型类。
2.3.6
设置应用程序的架构
在这种方法的许多地方,您需要设置应用程序总体架构。这个过程包含以下几个步骤:
- 选择部署技术。您首先要选择技术平台(如J2EE 或者 Microsoft DNA/COM),然后选择应用程序服务器。
- 选择构造模式,也就是控制代码如何生成的高级模式。例如,您可以通过EJBs或者包含JDBC的POJOs来实现持久性。同样,您可以通过JSPs或者显式的servlets来实现web网页。
- 划分应用程序,以便进行部署。您可以将整个应用程序打包成一个简单的archive包,或者将它们分成许多archive包。
注意,这些步骤可以发生在开发进程中的任何位置。还应该注意,您可以在不影响那些包含应用程序的各种模型的情况下就能够改变这些选择。
3 案例研究介绍
本案例研究比较了开发一个J2EE应用程序的两种不同方法的生产率:模型驱动开发(即IBM的Rational Rapid Developer
所体现的ARAD方法)和传统的以代码为中心的方法。该研究的中心是开发同一个应用程序的两个竞争团队,该应用程序为:The Middleware
Company Application Server Platform Specification(Middleware公司应用程序服务器平台规范,下文简称规范)。
注意我们并没有为这项研究组建两支新的团队。取而代之的是,我们组建了一支团队使用RRD来开发这个规范。为了便于比较,我们使用了"传统"团队的结果和经验,这些都是来自于今年早些时候所进行的生产率方面的研究
。该团队使用了一个市场领先的、全功能的IDE,该IDE是一种典型的采用以代码为中心的方法的工具。我们不提及该IDE的名称,将主要的研究放在MDD
和 RRD的生产率方面,而不是进行一项"哪家供应商应该出局"的研究。
关于这个研究的建立和执行情况的一些其他细节:
- 为两个团队提供了web页面所需要的包含静态HTML的文件,所以他们可以将其合并到他们所创建的JSPs中。用这种方法,他们就能够将注意力集中到J2EE开发方面而无需编写HTML。使用传统方法的开发团队使用这些HTML文件,而RRD团队则忽略了它们。由于RRD页面设计特性的原因,RRD团队发现以spec.中的屏幕截图作为指南,从头开始设计这些页面的效率更高。
- 在他们完成这个规范后, 为RRD团队下达了一张简短的增强功能清单,记录了一些"典型的"应用程序演进需求。因为这些额外的需求并不是传统的团队的职责,因此RRD的这些工作作为一项旁证相对独立,不进行定量比较。
3.1 关于 规格说明书
两个团队为完成这项研究而使用的功能性规格说明书为 The Middleware Company Application Server
Platform Baseline Specification。它是一个面向企业应用程序的46页的规格说明书,详细地描述了需求方面的内容,从数据库图表到web的用户接口。使用该规格说明书将确保在这个研究中的参与者能够创建能够进行比较的应用程序。
Middleware公司在一个独立专家组的帮助下创建了这份规格说明书,专家组包括图书作者、开放源码方面的贡献者、工程CTO
和VP、来自美国的三个顶尖的 IT研究机构中的两家机构的代表,以及对Middleware公司前一个案例研究感感兴趣的评论家。专家组成员包括:
Assaf Arkin(Intalio公司首席架构师)、Clinton Begin(Open
Source JPetStore作家)、 Rob Castaneda (CustomWare Asia Pacific作家、CEO)、Salil
Deshpande (来自Middleware 公司)、William Edwards(来自Middleware 公司)、Marc-Antoine
Garrigue (OCTO、ENSTA讲师)、John Goodson(DataDirect公司副总裁)、Erik Hatcher(Java
Development with Ant的作者)、Rod Johnson(Expert 1-on-1: J2EE Design
& Development的作者)、Anne Thomas Manes(Bowlight公司分析师、CEO)、Vince
Massol (JUnit in Action的作者)、John Meyer( Giga Information Group
公司的J2EE/.NET 分析师、现供职于Forrester Research)、Tom Murphy( META Group
公司的J2EE/.NET 分析师)、Cameron Purdy( Tangosol 公司的CEO)、Roger Sessions(NET
导师、 ObjectWatch创始者)、Vivek Singhal(Engr,Persistence Software公司CTO兼副总裁)、
Bruce Tate(Bitter Java的作者)、Bruno Vincent(OCTO)、Andrew Watson(Object
Management Group公司副总裁兼技术总监)、Wayne Williams(Embarcadero Software公司CEO)、Joe
Zuffoletto(BEA WebLogic Server Bible的作者)。
您可以从下面这个网址下载这份规格说明书: http://www.middleware-company.com/casestudy.
3.2 应用程序的选择
众所周知, PetStore作为该规范的基础,是一个简单的基于web的J2EE 电子商务应用程序,具有以下功能:
- 用户管理和安全性。用户能够登陆系统并且管理他们的帐户。
- 产品目录。用户能够在网页上浏览宠物的目录(例如,鸟类、鱼类或爬行动物)。
- 购物车功能。用户能够将宠物增加到他们的购物车中并且使用常用的方法管理他们的购物车。
- 下订单功能。用户能够为他们购物车中的物品下订单。
- Web 服务。用户能够通过web服务来查询订单。我们扩展了PetStore来包含这个功能,因为web服务是我们感兴趣的新兴领域。
从技术方面讲, PetStore 包括如下内容:
- 一个瘦客户端 HTML UI 层。
- JSPs 用于服务器上生成 HTML。
- JDBC 基于SQL的数据访问。
- EJB 中间层组件。
- 无序数据库搜索。
- 数据库事务。
- 数据缓存。
- 用户/Web 会话管理。
- Web 服务。
- 基于表彰的身份验证。
应该注意到,一些人对这个"PetStore"褒贬不一,因为Sun Microsystem
公司从没打算将最初的PetStore样例应用程序作为案例研究的基础使用。毕竟,PetStore最初仅仅是一个J2EE的样例应用程序,而不是一个完全的规范。更进一步讲,最初的PetStore不是一个架构良好的应用程序。
我们相信通过下面的方法,我们克服了这些缺陷:
- 我们有一个PetStore的规范,而不仅仅是一个PetStore实现。
- 符合我们规范的"高级的"PetStore 实现,本质上与Sun
以前的实现不同。实际上,这个规范与Sun原先的PetStore的最大的共同点就是应用程序中包含了购买宠物的功能。
- 规范没有限定设计PetStore的特定架构性方法,这就使得两个团队可以选择他们认为对他们的应用程序合适的架构。
3.3 规则概览
该规范详细描述了构建应用程序的规则。例如,它描述了哪些数据能够进入缓存、数据库排他性规则、基于表单的身份验证需求,以及会话状态规则。它还非常详细地描述了使用应用程序所需要的经验。
本案例研究的规则旨在找出将二者进行比较的外部特征,并通过它们来比较J2EE代码的编写效率。简单的说:
- 规范中要求每个团队使用相同的数据库模式。
- 为每个团队提供相同的静态HTML和图片。传统团队在构建JSPs时使用了所提供的HTML;而RRD团队则没有使用,因为RRD团队从头设计网页更容易。不过他们使用了所提供的图片。
- 规范并没有要求J2EE代码的实现细节,包括J2EE实现模式的选择,这些决定权留给了团队。最重要的是两个团队所创建的最终应用程序能实现相同的功能。
- 每个团队都可以选择兼容J2EE的应用程序服务器,以免由于不熟悉硬件而影响生产率(同样,我们不提及具体使用了哪个应用程序服务器)。
- 每个团队选择他们自己使用的源码控制工具、日志等等。以下列出他们的选择:
3.4 测试过程概览
为了确保最终两个应用程序具有相同功能,我们为两者都进行了严格的测试。在一个29页的文档中进行了描述,每个应用程序的测试都包括37个测试场景,测试由人工进行。该测试衡量了应用程序是否达到了最初的规格说明书的要求。
测试场景本身是功能性测试,不执行代码的单元测试,而是为那些利用web接口同该应用程序进行交互的测试人员描述了一个过程。例如,其中的一个测试场景用来登陆系统以及编辑账户信息。我们不希望进行代码级的单元测试,因为两个团队的实现方式不同,关键是最终的应用程序具有相同功能,所以本案例研究的结果很有参考价值。这就是为什么测试要手工进行。
两个团队开发的应用程序都通过了测试。
3.5 团队概览
使用传统的,以代码为中心的开发方法的团队由3名成员组成:Middleware公司的一位资深的J2EE架构师(他作为团队负责人)和两个经验丰富的J2EE程序员。每位成员在开发服务器应用程序方面都有大量的J2EE开发经验。
RRD团队由两名成员组成,分别由IBM及Middleware公司推荐。IBM公司推荐的团队成员作为团队负责人,他是一位经验丰富的服务器端开发人员,来自Technology
Solution Partners LLC,这是一家有过多年RRD使用经验的基于Shelton及CT的服务提供商, 后者是一位经验丰富的J2EE开发人员,在架构和开发方面造诣颇深。研究本案例之前,他使用过很多开发工具,包括模型驱动开发工具,但是从没有使用过RRD。
尽管团队人数不同,我们将竭尽全力来确保这两个团队的技术实力和所采用的特定开发工具大体相当。在传统开发团队这一边,团队成员在所选择的IDE使用方面很有经验。然而,他们仍然花费时间来补充这方面和其他要使用的工具方面的知识。在RRD这一方面,为了加快速度,在开始项目之前,TMC成员接受了三天的1对1RRD培训。两个团队都没有做整体培训。
3.6 项目日程安排和项目管理方法概览
为了保持每一个团队开发日志的准确性,我们分别对每个团队召开定期电话会议。对于传统团队我们每周召开一次电话会议。对于RRD团队,由于开发的进程太快,项目临近开始时召开了一次,再次召开会议时已接近尾声。我们对这些电话会议的过程做了详细记录。这两个团队都将回答下列问题:
- 您们团队在进行什么工作?
- 哪些工作有利于提高生产率?
- 从生产率角度方面看遇到了哪些挑战?
在本白皮书的下一节中将对这些方面进行概要介绍。
4 研究结果
在本部分,我们将讨论这个案例研究的结果。我们将研究结果归纳为以下几个部分:
在架构分析部分,您将了解到每个开发团队使用的架构和J2EE模式
在定性结果部分,总结了每个团队在选择开发方法方面的指导思想――每个团队遇到的问题以及他们是如何解决的。
在定量结果部分,您将看到每个团队最终的生产率结果的数字。
在影响生产率的因素部分,给出了关于生产率不同的原因的详细剖析。
最后,额外的任务部分描述了RRD团队在完成应用程序增强功能方面的工作。
4.1 架构分析
4.1.1
UML 和代码生成
这两个团队都为他们的对象模型创建了UML图。事实上,他们创建了非常类似的对象模型。他们为下面的部分进行了抽象:
- User Accounts(用户账号)
- User Profile Information(用户配置信息)
- Products(产品)
- Product Categories(产品目录)
- Suppliers(提供者)
- Shopping Carts(购物车)
- Orders(订单)
- Line Items(系列物品)
这两个团队采用了不同的方式来创建模型和图。
传统的团队使用一个叫做Visual Thought的产品为他们的对象模型创建UML图。他们创建UML图只是单纯的为了设计和交流――并不从UML中自动的生成J2EE代码。但是,他们使用IDE的向导(wizards)来生成JavaBean
accessor/mutator方法、EJB组件、struts代码、异常处理代码,以及加速接口实现的存根代码。
RRD团队使用RRD从数据库中模式创建类模型,然后通过它显示的UML图直接在RRD中完善该模型。由于RRD的代码生成功能,他们比传统的那个团队自动生成了更多的代码。
4.1.2
代码概览
这两个团队开发的代码体在许多方面是相似的。例如,两个应用程序都使用了JSP 和 EJB。但是在其他的重要的方面是不同的。代码的生成方式显著地影响了最后结果。
4.1.2.1 传统的团队
对于web 层,传统的开发团队使用了servlets和JavaServer Pages(JSPs),以及
JSP 标签库(taglibs)三者的结合。他们使用Apache Jakarta Struts 作为 web 层内部导航栏框架。(Struts是一种流行的用于构建基于J2EE的web应用程序的开放源码框架。它鼓励使用被广泛接受的模型-视图-控制器(MVC)设计模式)
在业务层中,传统的开发团队在会话和实体中都使用了EJB。 会话 bean 表示业务逻辑,而实体
beans则处理持久性方面的问题。另外,该团队有意使用了多种标准的 J2EE设计模式:
- 会话外观
- EJB 组件中的关键字生成
- 业务委托
- 业务接口
- 数据传输对象 (DTOs)
- 定制的 DTOs
- DTO Factory
- Service 定位器
- 通过数据访问对象 (DAOs)进行读入的JDBC
4.1.2.2 RRD 团队
RRD 团队使用了不同的方法。 RRD 从 J2EE 平台和关于代码生成方式的低层选择进行了抽象。而您通常会首先选择目标平台,然后进行代码生成方式的高层选择。
RRD 团队选择了一个平台和一组结构模式用于开发,而另一组用于产品版本。
为了便于开发,团队开始选择了Apache Tomcat(RRD自带)作为目标平台。由于这个选择,RRD生成了servlet用于外观设计,生成了一个POJOs的MVC结构。用于业务逻辑和数据持久性。作出这样选择的原因是在开发中加快速度并减轻负担。
开发结束后,团队开始使用一个全功能的J2EE应用程序服务器。这个目标平台使他们选择JSP用于外观设计,选择无状态会话bean用于业务逻辑,以及实体bean用于数据持久性。使用新的设置,重新生成代码只花费了几分钟时间。
值得注意的是RRD如何为每一个页面复制特定的类。如果有5个页面需要用到模型中的Account类,每一个页面都会得到自己的Account.java,但该Account.java只是为满足该页面的需要而"量身订做"的。当您选择构建EJBs时,会为每一个页面生成各自的无状态会话
bean。这种架构意味着特定页面的类是"轻量级"的,因为每个类只包含它所服务的页面所需的逻辑。
至于设计模式,RRD创建的代码使用了一些,但数量远远小于另外一个团队。而且,在从J2EE平台进行抽象方面,RRD无需开发人员做这些决定。
4.1.3
安全性
在安全性方面,两个团队采取了截然不同的方法。
传统的团队使用了一个身份论证过滤器(authentication filter)。该过滤器检查当前请求的页面是否受到限制,如果受到限制,就检查用户是否登陆(登陆信息保存在HTTP
Session中),该团队从头编写了这个过滤器。该过滤器实现了Sun 提供的javax.servlet.Filter接口。
通过比较,RRD使用了一个更加分布式的方法。它使用了一个会话属性,该会话属性包含了登陆身份来表明是否已经登陆过了。但是每一个验证过的页面都包含了它自己的逻辑来检查该属性,并且如果有必要的话,就调用登陆程序。所有安全相关的逻辑都是人工编写的。
4.2 定性结果
在这一部分中,我们将检查一下两个团队的根本思想,直接根据他们的定期状态更新进行总结。
4.2.1
传统团队
4.2.1.1 传统团队――第一周
传统的团队采用了一种迭代原型开发过程。在第一周,他们构建了一个简单的原型,使得他们能够为项目的设计模式制订一个架构。对他们来说,建立一个舒适的开发环境是一个相当麻烦的过程,并且在版本控制和IDE进行高效协作方面遇到一些麻烦。他们通过划分工作区暂时回避这些问题,很多问题是在第二周解决的。在第一周,他们还花费了一些时间来为系统的对象模型设计架构及其他问题,并决定采用包结构作为架构。
从生产率方面来看,在第一周,他们对IDE的能力表现很满意。他们发现IDE能够很好地与应用程序服务器进行集成,并且拥有强大的代码生成能力。这要归功于团队中的每一位成员都具有丰富的IDE使用经验。
这一周在生产率方面遇到的挑战主要是:共享文件、交流问题、代码检查,以及维护一个具有一致性的包结构。
4.2.1.2传统团队――第二周
在第二周,传统的开发团队开始具体分工,各就各位。一位成员负责模型(EJB)层,另一位成员拥有视图(web)层,而第三个成员通过提供层之间的帮助类和接口来保持团队的工作效率。
该团队决定使用用例的方式来创建他们的系统,将注意力依次集中在每一个用例上。这一周主要的工作是用于用户账户维护的用例,例如,登陆、登出、用户创建,以及用户性能维护。
从生产率角度看,他们发现这一周收获就是利用了Struts框架。他们发现利用Struts编写代码非常高效。而且,他们决定采取这样一种策略:通过在尚未构建完成的代码中植入"存根"实现代码,来使Web层和业务层实现去耦(decoupling)。他们通过属性文件和附录中描述的业务委托设计模式,在"存根"代码和"真实"代码之间进行切换。
这一周的生产率方面遇到的挑战是一个开发团队通常遇到的第一个问题,例如源码控制的一致使用。在使用IDE方面,他们也遇到了一些挑战,是否从IDE中生成J2EE组件,以及是否随后修改它们,组件不能轻易的返回到IDE中。
4.2.1.3传统团队-第三周
这一周,传统团队继续在产品目录浏览方面的工作,同时增加了一些购物车功能。
从生产率角度来看,这一周他们感到满意的就是解决了版本控制协作问题。并且通过构建他们团队能够使用的接口库来减少构建时间依赖。在这个阶段,每个团队成员都非常高效并且该项目进行了很好的分工,使得每一个团队成员都能够有他们自己的开发领域。而且,他们的IDE在代码生成能力方面为他们提供了诸多价值。
这一周仅有的挑战是PetStore规范的一些澄清,以及一些小的、购物车所需的重构。
4.2.1.4传统团队-第四周和第五周
在最后的几周,传统的开发团队通过编写最后的用例,进行测试和调试来结束他们的应用程序开发。他们还将团队成员的代码集成在一起,放弃了他们原来使用的存根实现。
这两周中有几方面的收获。他们从所选择的存根实现架构中获得了持续的收益。在他们开发的接口方面需要很少的沟通,提高了协作效率。还有,他们的web服务实现的创建速度很快,因为他们的IDE为其提供了功能支持。
这两周遇到的挑战包括重构和重新分析一些代码,例如在数据访问层就有许多缺陷。应用程序有许多层,这使得出现问题时很难查明原因,因为在具体的层发生问题之前,很难搞清楚问题存在于哪一层。还有一些与Struts和属性文件相关的小问题。
4.2.2
RRD 团队
再讲一次, RRD团队给我们的印象有些"应接不暇",因为他们进行得如此之快。
4.2.2.1 RRD 团队――早期阶段
该团队启动得非常迅速。第一天他们就完成了大量的工作:
- 加载数据库。
- 建立应用程序环境,包括源码控制。
- 从数据库模式创建类模型。这涉及将模式导入来创建类,然后填入数据库中不存在的关系。
- 创建一个样式"仓库"来促进构建应用程序过程中的样式的一致性。
- 通过创建所有空白页面并将它们相互链接来创建"站点模型"(站点的故事板)。
- 创建登陆页面和逻辑。
- 创建购物车和逻辑。
几个特殊事项直接对生产率提高有贡献。第一,从数据库模式导入初始的类模型节省了大量的时间。所需的工作就是指定模式中的没有对应外键的类的关系。第二,通过构建站点模型,能够快速创建所有空白页面并且在页面之间建立了整体流,或用户导航栏。第三,事实证明,WYSIWYG页面设计比直接的JSP编辑更有效。将页面控件绑定到类模型中的数据对象,是将页面与应用程序逻辑进行链接的一种高效方法。
从TMC成员的角度看,影响生产率的一个问题是处理样式"仓库"。RRD的GUI样式处理相当复杂并且是多层的。它使您能够建立一个独立于应用程序的包含页面样式和公共控件的仓库。随后构建PetStore时可以使用这些样式和控件。另外,当您在页面中加入控件时,可以使用多种方法来覆盖其继承设置。
TMC成员发现默认的设置并不总是像预期的那样执行。例如,尽管他为组合框控件设置了颜色方案,但是当他在一个页面中使用这个控件时,却显示了不同的颜色。他不得不花费额外的时间重新格式化该控件。
另外,TMC成员最初考虑了RRD在开发人员和J2EE之间插入抽象的程度。这方面并没有妨碍生产率。
4.2.2.2 RRD 团队――后期阶段 随着项目的进展,页面的快速开发继续提高了生产率。
在最后的几天,有三个问题妨碍了生产率。第一个问题是关于州、国家等的下拉列表框。按照规范的要求,RRD的自带方法处理这类列表框存在很大问题。这些问题导致了一些笨拙的编程。更多细节请参见下文的4.4.2.1节。
第二个问题是关于在规范中描述的默认错误页面。RRD在使用JSP本身的错误捕获能力方面有一些障碍,这就迫使该团队显式地捕获应用程序中的错误并且将它们传递给错误页面。这种方法和纯粹的JSP编程比起来显得相当笨拙。更多细节请参见下文的4.4.3节。
最后,TMC成员发现在RRD中找到一种最好的组织代码的方法很困难。特别是当他想要编写一些全局功能函数时,将这些函数放在哪里并不是显而易见的。如果对RRD有经验,就不会出现这个问题了。
4.3 定量结果
这里是每个团队开发PetStore花费的最终开发时间:
正如您看到的,在这个案例研究中,从生产率角度看,RRD团队是明显的赢家。他们构建PetStore应用程序的速度远远快于传统团队,所花费的时间还不到他们的10%。
4.4影响生产率的因素
显而易见, 生产率的提高大部分要归功于RRD从模型中生成代码的能力。但是,如此悬殊的差异值得我们更深入地详细检查两者的不同。有许多重要的因素对于RRD的高生产率有影响,也有一些降低了生产率。尽管我们无法对每项因素都进行量化分析,但可以简要描述一下它们对结果的重要性。
4.4.1
WYSIWYG 网页设计
RRD的一大特色就是使开发人员完全不用编辑servlets 和 JSPs。而传统的团队使用了提供的HTML。尽管他们的IDE
提供了一个JSP编辑器,但是他们仍然需要直接编辑JSP语法。他们不得不将提供的HTML 转换为JSPs。即使使用模板和标签库,这也是一个非常琐碎并且浪费时间的工作。RRD的页面设计者,将Visual
Basic这样的控件链接到模型类中,经过验证这是构建网页更简捷高效的方法。
在网页调试过程中也得到了一些不同结果。在传统的JSP开发中,要测试JSP语法是否正确,必须运行该应用程序并且调用JSP。在RRD中,可以将您的网页设计直接转换为servlets
而不是 JSP。在转换过程中,创建过程会编译该servlet并且在您运行应用程序之前检查JSP的语法错误。该过程更快,RRD团队选择了这个方法。
在RRD和网页创建方面有两点要注意:
- RRD仍旧要求或者允许您在特定场合使用JSP逻辑。例如,您放进标签控件中的文本可以包括JSP表达式和字符串。然而,这种用法是孤立的并且在网页创建方面要花费一部分团队的时间。
- RRD允许您查看并编辑网页设计中生成的HTML/JSP 逻辑。 RRD 团队发现为达到所需的设计结果,有几个地方需要查看,或者甚至需要覆盖HTML。
4.4.2
将页面绑定到数据
RRD通过ObjectSpace将页面控件绑定到类模型中的对象,这种方法对于生产率的提高也产生了巨大作用。RRD团队无需对于Struts或者任何类似的低层框架进行编程。对于典型的数据网页,可以在网页中加入标签或者文本字段,并且将它们映射到ObjectSpace中的一些对象的属性。在一些特殊的情况下,某个网页或者独立的控件需要一些显式的预加载逻辑;RRD提供了存放这种逻辑的地方。
有两个因素一定程度上妨碍了生产率的提高。
4.4.2.1网页列表
第一个因素与页面中的列表框(例如,美国各州的下拉列表框)的使用有关。RRD将用户从列表框中的选择映射为一个整数,即使这个数据是以字符串形势存储的。例如,在美国各州的列表框中,当一个用户选择了Alabama时,RRD考虑列表中的"值"为1而不是"Alabama"。需要一些额外的编程,才能将该列表框绑定到ObjectSpace中Account对象的字符串属性。
注意:如果列表框中的数据位于数据库表中,那么就不会出现这个问题。但是该规范的模式不包含这样的表,并且RRD团队避免创建它们,因为,该规范不允许对模式进行改变。
4.4.2.2 在页面之间传递对象
第二个问题就是要通过HTTP会话将数据从一个网页传递到另外一个网页中。通常,源网页简单的将对象作为一个命名的属性放置在会话中,目标网页以相似的方式检索这个对象。
然而在RRD中,一个模型类为每一个使用它的网页转换为一个单独的Java类。例如,如果一个模型拥有一个ShoppingCart类,并且有三个网页在它们的ObjectSpace中使用了该类,那么每一个网页都会得到它自己的生成的ShoppingCart.java。这三个生成的类是不同的,因为每一个都处在一个特定页的Java包中。这就意味着网页不能通过HTTP会话来传递实际的ShoppingCart对象。
RRD的首选解决方案是将这些对象转换为XML,或将XML转换为对象,并且通过会话来传递XML字符串。RRD使得从一个模型类中创建一个DTD以及对象与XML之间的转换相对来说非常容易。尽管如此,这个过程仍然需要在使用它的网页中进行额外的编程。RRD使用了这项技术。
4.4.3
默认的错误页面
规范要求在默认的错误页面中捕获所有的应用程序异常情况。在规范文档的屏幕截图中,错误页面包含异常的栈跟踪,尽管规范让开发人员来确定网页的内容。
JSP API 使得实现规范中描述的错误页面很容易实现:
1. 在每一个源代码网页中使用页面指令来指向一个错误页面。
2. 以同样的方法在错误页面中使用页面指令对其进行标记。
3. 在错误页面中,通过预定义的变量exception来引用这个异常。
在对JSP API中网页设计进行抽象方面,RRD使过程复杂化并且晦涩难懂,耽误的RRD团队的时间。RRD使得为一个给定的源代码网页标出一个错误面面变得很容易。困难在于捕获和传递这个异常。该团队不得不将try
block中的方法体与对应的捕获(该捕获将异常加入会话中)进行打包。然后默认的错误页面必须能够发现和显示这个错误。
4.4.4
源代码控制
源代码控制可能使RRD团队具有一些优势。在传统团队中,团队领导者非常了解所选择的产品,并且在使用过程中培训并指导其他成员。但是该产品没有集成到IDE中。结果,源代码控制过程经常需要成员在IDE外部进行操作时要非常慎重。而且,该团队不得不指出IDE生成的文件中哪些需要在源代码控制工具中保持
,哪些可以忽略。
RRD团队在支持RRD的常用的源代码控制软件工具中选择了一个。除最初到源代码控制服务器的登录操作之外,团队成员可以在RRD中轻松地完成所有的源代码的控制操作。另外,RRD同时也知道哪些文件需要加入源代码控制。
PRD如何组织其工件这一问题,在一定程度上抵消了这种优势。RRD团队负责人对如何组织工件方面非常精通,
RRD的新手却要经历一个学习过程。这项工作的关键在于,对于给定的开发任务,选择哪些项进行签出操作。例如,整个类模型中的类和方法的定义都存储在一个单一的文件中,而每个方法体都存储在各自的文件中。这就意味着有一点很不合理,团队中两位成员可以同时编辑该模型中的同一个类的不同方法,但是不能定义模型中不同类的新方法。TMC团队成员不得不进行调整以适应这种不寻常的源代码文件的组织方法。
4.4.5
团队组织
最后,RRD可以仅因为团队规模更小而获得了更高的生产率。更少的团队成员意味着在分配任务是困难更少,源代码控制冲突和交流方面的问题更少。它还意味着执行协同任务(例如设计讨论)花费更少的人时(man-hours)。TMC团队成员感到,像这样的一个中等规模的应用程序,多增加一名与他技术相当的成员实际上可能会降低开发速度,而不是加速了开发。
4.5 额外的任务
在完成规范中要求的应用程序的开发后,RRD收到了要进行增强功能和维护的任务清单。这些任务通常是要求开发人员为当前开发的程序所进行的后续任务。
正如开始提到的那样,因为传统的团队没有执行这些任务,我们不能够在这些任务上比较这两个团队的生产率。RRD的这些额外任务仍然值得我们关注。
下面是他们所执行的额外任务:
- 帐户编辑页面国际化。为多个地区/语言建立一个框架。在所选定的地区的基础上,将网页翻译成该地区的语言。
- 为数据库增加一个新表并且使用它。增加一个客户意见表,客户意见与表项之间为N:1关系,更新类模型来匹配数据库模式。在表项详细页面上显客户意见清单。
- 应用程序划分。将应用程序划分为两个独立的部分进行归档:外观设计(WAR)和业务逻辑(JAR)。
在完成这些任务上花费的时间很短:
下面介绍一下这些任务的细节。
4.5.1
网页国际化
RRD的i8n功能相当完备。您可以从Excel、数据库或者其他的地方导入特定区域的资源包。网页上的独立标签控件和消息对于选中的包中的特定资源的是非常关键的。该过程相当直接;最麻烦的事情就是将大量的文本转换成外国语言。
该规范增加了一个使得任务稍微复杂的"插曲":用户可以选择首选语言。所以当用户登陆的时候需要选择地区。
为应用程序建立国际化,将一个页面上的信息翻译成西班牙语,将资源应用到该网页,并且修改登陆代码来选择一个地区,这些只花费了RRK团队一个小时多一点儿的时间,
4.5.2
新表的增加和使用
RRD团队使用SQL来创建并填充客户意见表,表项与客户意见之间可以是1:N关系。
该团队执行SQL,将新表导入到类模型中,建立到表项的关系,然后修改表项细节页,从而在其他项数据下面的独立的组合框中列出客户意见。该团队实现了类似于其他应用程序行为的客户意见组合框,当超过一定的长度是地,使用Previous和Next来显示前一页或下一页。
整个过程花费的时间少于1.5个小时。
4.5.3
应用程序划分
RRD包括"划分架构",使您能够对应用程序进行划分。他能够显示所构建的全部工件清单,同时还可以分别显示不同应用程序层(外观、业务逻辑、持久性)的各自清单。您可以将单个工件从第一个清单中移到一个其他清单中。然后为RRD下达指令来创建所必需的存档文件。该过程相对比较简单并且允许使用不同的部署技术和不同的架构来创建多个划分模型,例如,将开发分区作为一个文件局部部署到Tomcat中,产品分区部署到WebSphere,并且具有独立的文件用于外观和业务逻辑与持久性。
该团队将应用程序分成了两部分:外观和业务逻辑/持久性。花费了20分钟。
5 结论
根据这份案例研究的结果,使用Rational Rapid Developer能够获得的生产率的极大收获,这一点是勿容置疑的。Middleware公司对与二者的悬殊差异印象非常深刻。
那些希望提高开发人员生产率的组织,应该考虑在他们的项目中使用RRD方法。在具体实践中,我建议考虑下面的这些因素:
- RRD极力强调建模和架构.我们为Middleware公司考虑了建模和架构方面的好处,但是为传统的、以代码为中心的开发人员考虑,还需要进行一些变更。另外,还应该考虑如何使RRD及其模型与其他正在使用的基于模型的工具进行交互。RRD提供了类导入以及同IBM的UML的建模工具Rational
Rose 和 Rational XDE的同步,以及XMI导入。
- RRD从J2EE平台的抽象。再次强调,RRD将开发活动从基础代码完全转换到了建模和业务逻辑方面。相当多的底层平台方面的问题,例如包结构和代码模式的使用,不再需要开发人员的参与。对有经验的J2EE开发人员来说这可能是一项挑战,正如一些C++程序员发现在Java中不使用指针,并且直接进行内存管理是一项挑战一样。然而,这正是为什么缺乏J2EE经验的开发人员能够在RRD中很快变得高效,而无需理解平台的复杂性的原因。
- 开发人员的背景. RRD 团队的TMC成员感觉到RRD特别适合于那些从其他方面转到J2EE的开发人员,因为它回避了J2EE开发的复杂性,正如PowerBuilder
和 Visual Basic隐藏了面向对象的开发的复杂性一样。
- RRD处理现有应用程序的能力. 在这个案例研究中,两个团队从头开始构建一个新的应用程序。他们并没有评估在现存应用程序中应用该工具的简单性。维护工作大于开发工作的机构在考虑采用RRD时,应该考虑在现有程序中使用RRD。另外,RRD声称具有广泛的遗留系统集成功能,尽管本案例研究并没说证明这些功能。
请向这个邮箱casestudy@middleware-company.com发送电子邮件,与我们交流您的见解与经验。
6 启示
本案例研究是
IBM 委托的
Middleware公司与IBM过去曾经有过一些业务合作。
另外,Middleware公司是Veritas Software(www.veritas.com,纳斯达克上市代码:VRTS)公司的一家全资子公司,独立经营。Veritas与IBM在一些技术领域有许多业务合作关系,但在其他技术领域却是完全的竞争关系。
IBM委托Middleware公司来做这个案例研究,并且期望我们能够保持供应商中立的原则,以便得到一个公正的研究结果。Middleware公司作为该案例研究的后盾,并保证研究公正地进行。
6.1 为什么我们要进行这项研究? 我们的"议程"是什么?
为了澄清本案例研究不是偶然创建的,我们有必要回答诸如此类的问题。
首先,我们的议程不是这样的:不是用来证明哪一家公司、产品、技术或者方法比其他公司 "更好"。
诸如"更好"或"更快"这样的简单词语都是粗略的并且毫无用处的概括。
实际情况更复杂,特别是当涉及到关键的企业应用程序时。我们尽量开诚布公地讨论我们的结果的意义(或者缺少意义),并且竭尽全力指出一些不能被概括可不应该被概括的情况。
我们的议程是尽力为客户和公众提供有用的、可靠的并且有益的研究与咨询服务。
为了将来能够帮助我们的客户,我们坚信需要熟悉并精通一些平台、工具和技术。我们之所以进行像本案例一样的实验,是因为它们具有很大的学习价值,而且我们认为每家技术咨询机构都应该进行一些具有学习价值的实验,从而能够为他们的客户提供最大的价值。
如果我们更进一步,邀请技术供应商来赞助一些案例研究(提供专门技术和资金),并带动广大社区和知名专家,并且记录并公开这些案例研究,那么我们就能够:
- 降低这些研究的成本
- 进行更大规模的研究
- 进行更多的研究
- 确保在这些研究方面不做任何愚蠢的事情并产生错误的结果
- 确保从研究中得到的经验能够为整个社区所用(而不只是我们)
6.2 进行一项"赞助研究"的结果一定对赞助商有利吗?
不。
我们和赞助者的方案是我们要做出我们相信并且能够证明是正确的结果,但是允许他们选择不公布研究结果,如果赞助商认为公布结果会给他们带来损害。我们在写这份报告的时候拒绝受赞助商的影响。赞助费并不会影响该结果。我们在开始阶段就使得赞助者明白这些约束,并且敦促他们在授权我们做研究之前认真考虑这些约束。
参考资料
- 您可以参阅本文在 developerWorks 全球站点上的 英文原文。
|