UML软件工程组织 |
应用 Rational 工具简化基于 J2EE 的项目第 6 部分 : 早期开发 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Steven Franklin
软件设计师和过程专家 这部分文章的重点是关注于在早期开发中适当的推行一种开发方法和使用 Rational 的工具。在这里 Rational Rose 被用来支持逆向工程以保持设计和代码的同步。 Rational Purify 和 Rational Quantify 用来跟踪内存的使用和性能。 本文是演示了在分布式的、基于 J2EE 的项目中使用 Rational 工具的系列文章(如下面所列)的第 6 部分。
本文中所虚构我们是一家软件公司 Lookoff Technologies Incorporated,我们的客户 Audiophile Speaker Design, Inc. (ASDI),它雇用我们实现他们最初的 IT 需求。对于更详细的信息,参见 第 1 部分。 本文讨论了团队的进展进入了实现阶段,并且因此进入了 RUP 的构建阶段。我们挑选了在 ASDI 项目的第一阶段被使用的大部分技术。设计的情况相当的好,虽然在本系列的第五部分中被讨论的包的结构和设计在未来的一到两周内还将继续的演进。例如,包结构的部分被重新定义来反映预期的 Java 包命名习惯。
铺平道路
指导方针和标准 对于我们的 Java 代码,我们创建了一个基于AmbySoft Inc. Java 编码标准的编码标准文档。这些标准被证明在我们进行同级评审中是意义重大的。这些标准不仅可以帮助我们为客户产生更加一致的和高质量的交付系统,而且还允许我们的团队成员更加容易的在不同的子系统(和项目)之间进行调整。我们发现如果开发人员们对编码的形式和构建非常熟悉的话,他们将能够非常快的融入到统一的团队之中。通过避免使用模糊的命名习惯、不充分的注释和不好的编码风格,开发人员能够创建出使其他开发人员更加容易接手的代码。 培训 因为我们的话题是与整个公司相关的,因此我们鼓励其他的技术人员参与到这些培训会议中。我们发现有更多的技术人员参与将会引发更加有价值的思想上的交换。最其码,我们计划能够让 ASDI 项目中所有的工程师都参加的会议(不论是参与分析、设计、实现或者测试的工程师)。 团队结构的演变
团队结构的变化和变化背后的原因被总结如下:
这些职位被增加:
后来我们发现,我们的团队结构也许是太具有杀伤力了,因为我们的工具仅仅是为了实现在第一阶段中的概念的验证的。我们也许应该在没有太大伤害的前提下调整一下系统的构建和质量保证的正式过程,并且依然要满足我们的第一阶段的目标。最后,我们建立了高质量的概念的验证,而且比我们最初预想的为第二阶段的工作提供了更多的可重用性。 开发方法 在 ASDI 的项目中,提供独立的开发环境是容易的,甚至对于我们的远程办公也是如此。仅有的共享方面是 DB2 的数据库,但是我们能够为每一个开发人员建立独立的数据库计划(schema),这样就可以去除任何的潜在的问题。此外,我们为我们的工程团队设置每一个类被一个单一的开发人员所“拥有”。我们发现这非常好的减少了我们的合并与修改的工作。我们从来不相信以 CVS (Concurrent Versioning System)方式在一个源文件上实现并行开发的哲学,因为在一个方法上的改变将会带来在其他方法上的细微但又重大的影响。我们觉得最安全的方法是将每个类实现的责任交给单独的团队成员。 关于我们的特定开发环境,我们发现 Orion 应用服务器、Rational Suite DevelopmentStudio 、J2SE JDK 和 DB2 客户端软件能够很容易的符合 P-III 500 和 256 M 内存的机器。Orion 惊人的小的足迹和高效的设计是他能够在这样低的硬件配置的机器上运行的主要因素。 基本的开发周期在图 1 中被显示出来(它大量的借用了 RUP 的内容)。 每一个开发人员最初从基线设计说明开发工作。开发的的第一个迭代包括使用 Rational Rose 作为起始点生成代码的框架。一系列的迭代(包括时常发生的小的构建)都是从这里开始的。开发人员非正式的对早期的迭代进行单元测试,同时也与团队的领导协商任何与设计的背离。小的设计变化可以通过电子邮件进行沟通,然而重大的变化需要一对一的讨论以确保变化是适当的并且不会对系统的其他方面做成负面的影响。显然,任何对接口(甚至是公用方法)的变化要求特别细致的检查和冲突分析。设计要定期的通过逆向工程进行更新,合并任何的变化回到 Rose 模型中以维护系统的最新画面。 回顾一下,我们希望我们投入更多的工作在场景上。如果我们的场景已经演示了系统的大部分,我们就能够在 Rose 中使用报告来显示类之间的详细依靠了。这将使我们可以产生关于特定变化的影响的更具有根据的推测。而不是,我们必须编写脚本来根据被配置管理的代码进行文本的搜索以确定谁正依靠着给定类的特定的方法。 当遇到复杂的事情和问题时,他们将被交给团队的领导。通常团队领导或者亲自的协助解决问题,或者让开发人员解决问题,再或者使用来自其他团队或者公司的帮助解决问题。有时,我们会遇到技术上的需要与客户讨论的问题和后续的需求本身的更新问题。例如,我们的一些安全方面需求的遵循 JSSE (Java Secure Socket Extension) API 的变化。 一旦代码被充实起来,开发人员编译一系列的单元测试,集成与测试团队创建一系列的组件测试,他们被设计用来测试性能、功能和可靠性方面的需求。在完成了代码和单元测试之上,开发人员要为同级评审过程(后面被描述)组装一个评审包并等候反馈。评审过程有时会导致设计的修改,其他时候算只是简单的识别出一些 bug 或者需要增强的地方。 跟踪进展 任务报告以每周为基础被开发人员提交。这些报告能够指出最近一周的任务工作完成情况和在任务中的预算的花费情况,并且可以估计任务中剩余的工作量。任何阻碍任务进展的障碍也会在每周的总结中被报告。 小的里程碑甚至是更加关键的,因为他们有时揭示了重要的问题。团队领导经常要求小版本的构建、非正式的星期五下午的演示、代码预演或者甚至是当场的代码检查。如果我们发现一个团队或者团队成员不能在时间期限内实现一个适当产品的里程碑,这有时意味着存在需要帮助的问题。 确保系统的质量
我们发现 Rational 工具能够帮助我们满足这些要求中的很多。为了举例说明 Rational 工具能够在哪些地方帮助我们,这部分将重点集中在客户接口的 command gateway 部分。就像在本系列第五部分所注明的,这个网关是一个 B2B (business-to-business)接口,这个接口允许大公司可以查询 ASDI 的零件的可用性、提交订单、更新他们的客户信息和查询运输或者帐目状态。 更新设计:双向工程 command gateway 通过远程被开发(在总部),因为他们具有在 Java 、 XML 和 JSSE 方面的丰富的经验。我们在周五将最新的设计发给高级的开发人员,并且计划在接下来的星期通过电话会议来讨论设计。然而,开发人员那个星期五病了,并且没有收到设计;实际上她并不知道任何我们已经完成的进展的信息,因为我们的最初设计并不是详细的。在周末她在家中继续的通过她的膝上型电脑进行着项目的工作,却没有意识到她已经丧失了与 command gateway 设计的同步。 在接下来的电话会议中,高级的开发人员详细的谈论了她对设计的改进、她对新技术引进和她在整个开发中的大的超前。这使团队领导非常的惊讶,当然开发人员听到了关于设计上的更新也是非常惊讶的。我们协商同意忽略最新的设计和开发人员的工作以找到哪一种方法我们应该使用。 当我们选择好方法之后,开发人员的进步是显著的,并且比我们以前的工作更加深思熟虑。她使用了一个开放的产品 Castor,这个产品能够封装 XML 数据的映射到 Java 的对象,并且她合并了一些比我们提议的方案更加好的设计决定。因此,我们同意更新设计以反映她的良好的方法。 因为她开始于她的草稿代码,因此我们需要返回她的设计到我们的模型中。这是相当容易完成的:我们简单的提供给开发人员我们最新的对于 command
gateway 的 逆行工程的过程
这个值指向了核心的 J2SE 类的运行时库和我们用来映射 Java 对象和 XML 数据的 Castor 的 XML 绑定类。 然后我们定义项目的说明,在 Rational Rose 中使用 Tools > Java > Project Specification 选项(弹出如图 4 所示的对话框)。我们确认所有被发现的路径,并且我们指出了在 Rose 中我们的代码的根。 接下来,我们选择 Tools > Java > Reverse Engineer 选项,它弹出一个对话框(如图 3 所示)提示我们选择将要被分析的源文件。我们选择我们感兴趣的包
— 在首先的几次尝试当中,我们意识到我们在设置我们的 逆向工程的结果 逆向工程在分析类之间的关系上是相当有效的。当类的变量被声明为类的成员变量时,找到所有权关系是更加可靠的。有些关系被获取的并不正确(例如,在我们的 Java 代码中通过本地范围的实例变量创建的关系),因此一些继续的检查工作是必要的。 可以理解的是 Rose 没有为代码创建图。在上百个类中, Rose 没有办法知道如何进行逻辑的分组这些类来适当的表示系统的架构和设计。然而,所有类之间的关系已经被适当的生成了,产生设计和组件图是相对容易的。在图 8 中显示的是在逆向工程后修改的网关设计。 在图 6 中显示的设计上的主要变化是引入和 Castor 的 XML 绑定的接口。我们不必做我们自己的分析(使用 Xerces-J 或者
XML4J)来进行 XML 消息到对象的转换,因为 Castor 显然提供了这种映射的能力。 性能分析 为了加速我们的这个过程,我们决定使用 Rational Purify 和 Rational Quantify 来观察 Castor 的行为。这些工具允许我们精密的检查资源的需求和运行时
Castor 的行为。为了方便起见,而不干扰实现整个 JSSE 客户端和服务器端的代码,我们决定去掉 JSSE 的功能(在 图
6 中的 检查 Java 内存的使用 在 C 或者 C++ 项目中,我们已经强制在组件上运行 Purify 来预防进入产品代码的内存访问的违规。使用 Java ,象读空指针、内存泄漏和数组越界的问题已经不是什么问题了;然而,Purify 依然在分析 Castor 中为我们提供了非常有用的特性。 为了运行 Purify ,我们首先必须设置参数配置以使用正确的 JDK 。除了我们选中了" Pause JVM console after exit "选项之外,我们为我们的 JDK 版本使用缺省的设置,以便我们能够在 Purify 测试被完成时看到我们的应用的任何错误或者结束的结果(见图 7 )。 为了运行 Purify 测试,我们选择 File > Run 并且通过浏览 有趣的是,我们第一次就遇到了类格式的异常错误。在过去当我们在 JDK 1.1 和 JDK 1.3 之间迁移时我们看到过这些异常,在那里
我们运行了这个测试几个小时以确保它是可重复的和可预见的。没有问题被注意到,除了垃圾收集的问题。虽然内存使用从没蔓延,但是我们的应用在每妙秒中处理和映射 200 个命令时强制的执行了有意义的垃圾收集。在现在为止,我们没有看到性能的问题,因为在测试的任何一个点上 CPU 的负载从没变得紧张。 分析代码 Quantify 在外表和配置方面类似于 Purify ,并且 JVM 的设置以相同的方式被完成。Quantify 对于了解 Castor 是如何影响的 CPU 和时间是非常有用的,并且它可以帮助我们知道 Castor 的大量工作在哪里。图 10 显示了在分析我们的 command gateway 代码时 Quantify 环境的一个样例截图。
对于我们来说有一点变得清楚了,就是当 Castor 运行时 Xerces (Castor 的底层 XML 解释器)使用了相当数量的 CPU 。我们显然遇到了相同的问题,因为我们仍然必须要解释 XML 消息以提取内容。Quantify 使我们能够了解到在调用栈中对于每一个部分的执行的最大和最小的时间,被派生的时间消耗和其他有用的信息。最后,我们觉得在我们的系统中包含 Castor 使合适的,因为它展示它的健壮性和一些好的特性。 单元测试 开发人员经常定义他们自己的单元测试规范,因为这些测试是非常底层的白盒和黑盒测试,他们也是很详细的,可以让集成与测试团队理解。为了在单元测试规范中强制一致的详细程度,我们将他们包含在同级评审过程中。 同级评审
同级评审也通过技能和方法的交叉传授改进了整个团队的能力。开发人员通过了解其他每个人的想法建立起良好的设计模式和编码习惯的部分。代码的评审允许使用大量的时间对各种编码策略进行有价值的赞成和反对的讨论;因此,通常为了学习的目的我们会尽量让至少一个初级的开发人员参与评审。 我们的编码标准不仅仅是简单的针对风格的问题,而且也涉及到了编码习惯、编码实践和性能问题。标准在三个午餐小时被呈现给了团队,连同的还有针对评审过程的指导方针。 评审过程的步骤如下:
最初我们存在着对这个评审过程会花去过多时间的担心,但是我们发现它这个过程是极有价值的,它提供了:
总结 计划未来 在接下来的几周中将是产生内部和外部的早期演示的工作。为了外部的演示我们将很快的将用户界面屏幕集成到一起。这对我们来说也是非常好的机会来得到额外的需求反馈。 主要风险 贯穿整个项目远程开发对于我们来说都是一个挑战。虽然我们以前也做过远程开发,但是我们还没有解决如何集成跨越分离的地理位置的团队工作结果的问题。我们了解到 Rational 的工具不能完全的消除远程开发的问题,但是他们至少能够减轻远程开发的痛苦。例如,我们还不能防止高级开发人员在 command gateway 设计方面的分歧,但是逆向工程能够通过最少的工作帮助我们评估和集成她的变化。 为了符合我们严格最终期限,开发必须以高效的步伐继续前进。自从我们提供给客户软件的架构文档,已经有一段时间了,客户渴望看到一些进展。尽快的提供集成的演示是重要的。
|
版权所有:UML软件工程组织 |