这个由多篇文章组成的系列文章讲述了如何在很紧的时间和预算的情况下通过应用 Rational 统一过程(RUP)以及 Rational 的其他工具来开发一个软件项目的。 文章的第 1 部分包含了高层次的计划和需求的引出。Raional 的开发工具套件支持 双向工程(round-trip engineering,RTE)、分布式的和协作的开发、高度迭代的开发周期和更多的一些特性。 这个由多篇文章组成的系列的第 1 部分将向大家展示 Rational 工具的作用,并显示你能够通过使用 Rational 的工具来简化分布式的 J2EE(Java 2 Platform, Enterprise Edition)项目。我们将看一个将单的虚构的项目,并以高层次的计划和需求的引出作为开发,并将过渡到 Rational 统一过程(Rational Unified Process,RUP)的各个阶段。
为了简单起见,我们不想完成 RUP 中所有必要的迭代,而是只显示在项目各个阶段被用到的工具的特性。我们将跟随着我们的小的样例项目,完成它的第一个主要的构建,如下:
第 1 部分快照 |
第 1 部分中的工具和技术:
|
样例项目介绍
这 篇文章中的虚拟假设是我们是一家软件公司,名字为 Lookoff Technologies Incorporated,我们的公司主要的业务是在 IT 系统,包括集成、支持和开发。我们的总部在多伦多,并且在遍布加拿大有一些小的办事处。因为我们的分析和开发团队距离我们大量的跨国客户非常近,这个公司 的结构就允许我们以一种非常好的方式集中我们的专家(典型的后端开发(back-end development)和项目管理)。
我们假设另外一个虚拟的公司,Audiophile Speaker Design, Inc. (ASDI),这个公司位于 New Brunswick 的附近。 ASDI 开始只是一家从事扬声器制造和设计的小公司,主要开发针对个人用户的一些定制的扬声器方案。随着 ASDI 公司的声望的增加,他们开发出更多主流的扬声器产品线,并向加拿大和北美国家的用户和电子商店供应产品。
ASDI 的技术设施不能满足他们的成长需要。他们已经难以管理定单,计划生产材料,跟踪部分需求和管理运输。更主要的是,ASDI 的客户抱怨他们缺乏浏览可用性和交付过程的能力。
ASDI 公司意识到了从纸张和电子表格到自动化的资产管理系统的转变是伴随风险的,ASDI 决定将他们的所有 IT 需求交给 Lookoff 一家来作。他们选择我们的主要原因是我们的良好声誉和距离他们的公司很近(便于支持)。
注意:虽然样例项目是虚构的,但是它是基于我的个人经验、对其他项目的观察和我通过一些优秀的书籍(例如被列在文章结尾的 "参考资料")获取的知识。
|
引出高层次需求
象许多小的非 IT 公司一样,ASDI 意识到了他们的问题,但是他们并不十分清楚他们的需求究竟是什么样子。他们原有的工作状态(statement of work,SOW)仅仅有两页纸长,并且是契约的、功能的和编程的需求的混合。我们和他们坐下来讨论他们的每个需求点;这里最大兴趣的是契约的和编程的问题,讨论如下:
契约问题
客户(ASDI) 希望我们签署一份完全固定总价(firm fixed price,FFP)合同,合同价值一百一十万加元(CDN),按照合同规定软件系统应在10个月之内交付。对于我们来说没有一个清楚的需求远景,签署这 个合同是不可能的。这将给我们带来过多的风险,并且也许对客户来说是不公平的,并且我们能够确定他们的技术需求将被满足吗。我们开始了第一个会议,目的是 讨论迭代和和增量的软件开发优于顺序(“瀑布式”)开发的力量。
我们对客户强调的 RUP 的关键特性包括:
客户还是很关心软件交付的期限的缺乏。通过一些讨论,我们成功的显示了客户从项目的开始到结束都应该对项目的进展有足够的了解。他们也想项目的预算可以分阶段支付,并且要求我们在执行项目时履行一些义务。因此项目计划被划分为两给阶段:
对 于阶段 1,客户要求250K CDN 的上限,我们觉得这个预算对于我们创建第一个原型系统的演示版本是很充裕的。我们创建了如图 1 的甘特图,我们在四个月是标记这个点应该产生演示版本,并且与客户一起审阅以确保至少与第 1 阶段的时间表粗略的保持同步。(之后我们与他们更加紧密的一起检查了这个时间进度表)
图 1: 阶段 1 甘特图 |
( 点击放大) |
图一中的图是用 Microsoft Visio 创建的,但是你可以很容易的使用 Microsoft Project 或者 一些类似的软件工具来计划你的项目。这个图表对我们的主要目的是对时间进对和里程碑达成一致,并且建立工作分解结构(work breakdown structure,WBS)的层次图,工作分解结构中的每一项我们都可以跟踪、估计和执行。
编程问题
ASDI 是一家通过了 ISO 认证的公司,并且他们非常信仰厚重的文档、连续的里程碑和广泛的质量控制。他们不是一家非常技术型的公司,他们在过程上有自己的想法。我们在与他们合作的 作大挑战之一就是找到一个过程和可是使他们满意的可交付工作产物的集合,同时又不会使我们的团队感到多工作有防碍。他们进行了几次会议,并很强调要有大量 的彻底详尽的文档。而且,他们的里程碑是有顺序性的,而且他们的思想是每一个任务必须在下一个任务开始前结束。 他们对过程的理解使我们在最可能的方法中应用 RUP 制造了更大的挑战。
虽然 ASDI 同意了我们使用迭代和增量的开发(基于 RUP)方法,但是他们对这种方法似乎不感兴趣。他们希望得到下面的东西:
我们简单的将这些里程碑插到了我们的过程当中(如 图 1 所示).
ASDI 也计划雇用一个 IT 经理与我们联络,同时也负责维护和管理完成的项目。我们需要 ASDI 的这样一个角色的人加入到项目中,这个人对于项目来说应该是一个技术上的权威。不幸的是, 这个 IT 经理(对公司来说是新兴的事物)缺乏客户运作的知识,就像我们的团队中的一样。
|
总结
在 最开始与客户的一系列的会议中,我们取得了一些非常好的进展。ASDI 的对于交付产物和时间进对期望是有些灵活性的,并且允许我们使用基于 RUP 的方法进行开发。我们对项目达成了一个大致的时间进度结构,并且与客户建立了良好的关系。通过与客户的讨论,我们识别除了一些风险,之后这些风险被我们用 来划分任务的优先级和项目管理。
计划未来
我们应该进行的最高优先级的事情之一的是与客户一起从客户的工作现状(SOW)开始建立项目的远景。我们已经获得了客户需求的大概的理解,但是我们还需要分析出需要我们作的具体的工作。
我们也必须细化我们的时间进度表,并尽快的开始我们探测好的起步阶段。在阶段 1 期间,要确保一个方案是有成本效益的和满足客户需求的,我们就必须找出如何能够满足客户需求。客户已经提到过,在决定是否将项目进行到第 2 阶段的主要因素是最终系统的维护和系统架构软件/硬件的成本。
总而言之,我们在前几周应该做的事情包括:
主要风险
项目进行的开始几周对于建立有效的客户关系和使项目保持在正确适当的技术方向上是非常关键的。我们没有太多的时间来寻找需要的技术并将这些技术集成到我们的团队中,因为客户期望的项目进度是非常快的。
我们认为我们必须建立一个问题的数据库,我们能够以一种集中查找数据库的方式提出行动条目、问题和风险。通过将这些信息发布到网上,这样就可以使不论是集中办公还是远程的开发团队都可以监视项目信息。如果有必要的话甚至远距离的工作者都可以跟踪和更新项目的风险。
第 2 部分快照 |
第 2 部分展示的工具和技术:
将被创建或者更新的产物:
|
从开始进行计划或者计划失败
在一个软件项目中,获得一个良好的开始是十分关键的。你不仅会希望你的早期劳动确定整个项目的基调,而且你也希望快速的识别出系统中的高风险和挑战的部分。大概一半以上的项目的命运在项目的第一个月就已经注定了,决定的因素包括:
Rational 统一过程(RUP)通过改进团队的效率和指导提升团队的成熟性可以尽量的减少导致项目失败的因素。良好的数据可以影响项目的管理者对项目的管理,更好的工 具可以支持工程团队,更好的过程能够帮助软件产品以一种可预见的方式发展。本系列的第 2 部分将把重点放在我们能应用的一些早期策略上以获得一些在我们的样例项目中摇摆不定的事情。
请注意项目管理包括一些目前在 RUP 中没有包含的活动。我强烈推荐这本书 《快速开发:驯服疯狂的软件时间进度》(Rapid Development: Taming Wild Software Schedules) 它可以作为在开发项目中减少风险因素的进一步的参考资料。
|
细化第 1 阶段时间进度
我们希望尽快启动软件工程,但是首先我们必须在一系列的日程安排问题上得到来自于客户的同意。我们拿来了 我们已经创建的第 1 阶段的时间进度 (在4个月的时间点以一个演示结束)并和客户更加紧密的审查时间进度。客户提出了以下的问题,所有的问题都是正当的并且一些讨论:
这就是我们看到的客户的主要的关心点,并且我们对每一项作出了回答:
综上所述,我们并不觉得我们时间进度计划是过分自信的,并且我们有信心在客户的成本期望之内完成任务。关于我们能够满足时间进度的能力来自于我们的团队结 构,在项目团队中我们与 ASDI 一起对项目进行审查。如表1所示,我们计划了包括一些兼职角色的人员。例如,我们有单独的一个 QA 人员在我们的项目中,这个人同时也在其她项目中扮演角色;在我们的项目中显示她作为一个20%的角色,这就以为着在我们的项目中她一周工作一天:
Table 1:团队结构
|
总 的来看,我们计划需要450个人天的工作量来创建这四个月之久的系统演示。在项目的进展过程中,我们将知道是否我们需要增加时间或者提前完成,我们也将通 知 ASDI 项目的情况。在展示系统演示的时候,我们也要对深入的设计审查做好充分的准备,并且能过向客户展示对项目第 2 阶段的估计。如果 ASDI 对我们在第 1 阶段的概念检验(POC)的工作表示满意,他们将与我们启动项目的第 2 阶段的工作来开发产品化的系统。
虽然我们还在创建了ASDI 的第 1 阶段的演示,但 ASDI 非常高兴的看到了我们所作的工作将是进一步开发产品化系统的良好输入。至少他们已经接近可需求的审查、屏幕的模式、OTS 评估、架构审查、两个实际的版本和一个系统演示。
|
管理风险
从 一开始就跟踪风险是极其重要的。在之前的项目中,我们使用 Microsoft Excel 来管理风险,这次我们决定使用 Rational ClearQuest 以简化风险的输入、管理和报告。 ClearQuest 不是一个便宜的工具,而且它对风险管理不是独一无二的成本有效的工具。然而,它同时还可以集中的管理我们的集成和测试方面的问题。此外,我们计划在 Lookoff 的其他项目中共同承担这个成本。
使用 ClearQuest Designer 可以非常方便的设计新的数据结构和表单。比如,创建一个风险录入表单就类似与已经在 ClearQuest Designer 中显示的缺陷表单,我们可以根据缺陷跟踪计划(DefectTracking schema)来新的计划(schema),也可以删除一些不必要的条目和重命名其他的条目,类似的更新相应的表单,删除或者重命名必要的提示和域。
这里是你如何能够自己进行试验:假设你已经安装了 ClearQuest 并具有管理员的权限,你应该可以很容易的找到 ClearQuest Designer 应用程序。从文件菜单中,选择 创建计划(New Schema ),并且选择一个已存在的你想修改的计划(Schema)。我们选择修改缺陷跟踪计划(DefectTracking schema)。一旦你给你的新计划(schema)一个名字,你将被提示创建一个与这个计划(schema)相关联的数据库。除非你制定一个特殊的方 法,否则你将以 Microsoft Access 数据库的形式创建这个数据库。当被要求将这个新建的数据库与一个计划(Schema)关联时,选择你刚刚创建并命名的计划(Schema)。然后你可以检 查编辑和修改的表单和数据类型以符合你的要求。比如,你可以展开记录类型和目录树的表单节点来查看存在的 Defect_Base_Submit 表单。这些表单可以被重命名,一些域可以被删除、添加等等。更多创建和修改 ClearQuest 表单的信息,请参考 ClearQuest 文档。
我可以很快的在我们的桌面将我们项目的风险输入到 ClearQuest 中。整个团队的所有成员都可以访问风险数据库,并且可以输入他们观察到的风险。虽然只有项目经理(PM)和项目工程师(PE)应该具有权限 关闭风险,但是给团队的每一个成员 提出风险的权限是没什么不对的。项目经理首先会希望查看对于客户可见的风险,因为其中的某些风险也许不是相关联的或者是可以很快被解决的。例如,图1显示了一个被用来输入我们讨论过的项目早期遇到的风险的表单。
图 1: ClearQuest 风险输入表单 |
( 点击放大) |
对于项目的开始我发现并输入和一共17个风险。这并不是一个非常大的数字,其中的一些风险(比如有挑战的时间进度计划)直到项目的最后时期都会存在。
图2显示了我们所查询的项目风险的一个部分的列表的 ClearQuest 界面。风险被列在最上方,并且严格的按照顺序排列。通过点击列表中的风险项可以得到更加详细的单个风险的信息。
Figure 2: ClearQuest 风险报告 |
( 点击放大) |
|
跟踪进展
管理需要工具来跟踪项目的进展。在项目的早期阶段,我们不能依赖任何象缺陷、变更请求和测试结果来衡量项目的成功。相反,我们必须根据工作分解结构(WBS)项和我们的进展来估计实际完成的比例。
好的工作分解结构(WBS) 对于跟踪项目进展是十分重要的。 第 1 部分中的甘特图 描述了我们第 1 阶段的工作任务包 。 为了使我们可以精练出有用的矩阵,这些工作任务包必须被清晰的定义并也适当的规划每个工作任务包的大小。我们典型的为这些工作任务包分配10到40天的工作工作量。
此 外,ClearQuest 也可以帮助我们跟踪那些系统中可变的部分—在这些可变的部分中,变更请求却是极其的偏高。在一些之前的项目中,我们发现在细化阶段出现的过多的变更请求通 常是下列方面中的一项或者多项的征兆:不够充分的分析、难相处的客户、脆弱的工程团队、不良的过程执行或者复杂的再工程。如果在系统的某些方面出现了一点 这些症状,就需要管理人员和组长对这些部分有额外的注意。
|
管理客户期望
有 时减少与客户开会和接触开起来是很容易的;然而,实际上是你的项目团队成员中最重要的成员之一,并且客户应该被从始至终的包括在整个项目中。这不仅仅可以 产生更好的分析和改进每个迭代所获得的结果,而且可以通过让客户看到进化中的产品和理解面临的挑战更好的管理客户的期望。尤其是当客户对技术不是非常精通 时,他们对最终产品的期望肯能会很大程度的超出现实的成本、时间进度和可行性。
我们怀疑真正的项目优先级和动机并没有反映客户的工作现状,我们还需要理解客户关心的主要优先级和期望。为了实现之一 点,我们起草了一份概要的远景文档来帮助谅解更多的客户期望。(由于时间的限制,我们将业务远景和项目远景合并成了一个文档。)不论是工作现状(SOW) 还是远景文档都要与客户一起进行多次的修订。
远景文档是基于在几个由 RUP 安装包提供的 Microsoft Word 模板其中的一个创建的。我们将这些模板安装在 Word 指定的地方(通过 工具 > 选项 > 文件位置)。如图3所示,我们为每个模板生成了预览(通过打开每个 .dot
模板文件,选择文件 > 属性 > 总结,检查 “保存预览画面” ,保存文件)并对模板的标题重命名 *.dot
文件以使他们更容易浏览。
图 3: 浏览 RUP Microsoft Word 模板 |
( 点击放大) |
|
管理需求
需 求对于系统来说不是微不足道的。同样,因为 ASDI 有很少的 IT 基础设施,因此系统需求向详细的软件需求的转换就需要充足的时间和劳动的付出。Rational RequisitePro 可以非常好的帮助我们完成这个任务,它允许我们在整个项目中管理我们的需求和跟踪项目范围的变化。
客户已经开始的工作现状(SOW)可以作为我们的系统需求基线。在许多的情况下,我们按照 RUP 中描述的从业务建模和需求分析开始。这应该包括业务用例的集合、补充的系统规范和业务对象模型。但是对于我们来说从客户的工作现状开始来满足他们的期望并 建立在他们的工作之上是十分重要的。我们将按照的工作现状生成了一个叫作 软件需求说明书 (SRS) 的 RUP 产物,并且把它作为需求的基础集合,根据它我们可以跟踪我们后来的分析和建模产物。
RequisitePro 的能力可以非常容易的帮助我们从客户的工作状态(SOW)插入需求。我们创建需求的规则要与我们“子弹”的样式相配,或者与任何或所有的关键字 "must"、 "will" 和 "should" 相配。其他可以帮助我们建立需求层次的诀窍包括在相同的级别上获取需求块,在需求块创建标签下对适当的父需求设置缺省值,然后让创建工具完成接下来的工 作。(起先我们使用需求块创建时没有设置父需求,所以我们必须返回到每一个需求并对每一个需求设置父需求 — 对于成百上千的需求来说这是单调乏味的工作。)
图4显示了来自于客户服务子系统需求的一页(一共大约40页)。就象你看到的一样,RequisitePro 的界面被紧密的集成到了 Word 应用程序中,因此你可以同时使用 Microsoft Word 和 RequisitePro 的特性。
图 4: Rational RequisitePro 界面 |
( 点击放大) |
我 们与客户紧密的沟通什么样的信息是被需要的,但是我们让他们在需求文档上作了大量的工作。这被证明是一个非常有效的方式;我们能够向他们的团队传授过程的 技能,而他们能够给我们的团队他们学科的专家意见。我们趋向于非常细节的投入到一些领域中,而在其他的一些领域只是在非常高的层面上。在一些情况下这是非 常合理的,但是在另一些情况下他们却对系统的一个特定的领域过分的狂热。通过对文档的审查,我们可以指导 ASDI 写出适当并足够详细的需求集合。因为我们正在处理的是 Word 文档,因此规格上的互操作是容易的,当我们对这个文档感到满意时,我们就可以在文档上运行 RequisitePro 。
同样在这个时候我们关注系统的 非功能 需求,这就意味着这些需求不会被系统的功能规格说明描述。这些非功能需求包括关注人的因素的可用性需求(比如学习和使用的舒适性)和可靠性需求等等。
|
总结
在 项目的这个点上,我们运作着一个很小的团队。制定计划和获得资源是我们首要的任务。直到我们知道了我们应该朝什么方向努力并知道如何可以实现目标,我们的 团队才会越来越有斗志。对于我们来说首先最重要的是我们必须完成客户的工作状态(SRS),它规定了项目的基本系统和软件需求。
计划未来
我 们希望尽快的组成工程团队,但是我们接下来的任务需要一个高级的分析师以使 RUP 的初始阶段更有进展。首先,被显示在我们的工作状态(SOW)中的需求本质上是一系列被分解的规格说明,这些规格说明不能引导清晰的工作分解,或者甚至不 能会产生许多架构的线索。我们一直认为以平白的文字表示的需求不会带来以统一建模语言(UML)表达的需求带来同样的好处,因此我们计划将我们的需求转化 成用例(在 Rational Rose 中使用 UML)。
同样,我们需要一种正式的方式来管理客户的变更请求、客户所关心的地方和客户的反馈。虽然之前我们没有使用 ClearQuest 的 Web 界面,但是它看起来像是一个完美的工具使开发团队和客户保持同步。建立 ClearQuest Web 对我们来说是下一周或第二周最高优先级的事情。
主要风险
我 们的风险没有明显的变化:我们必须继续把精力放在建立有效的客户关系和快速的使项目沿着正确的方向前进。我么们现在有一个问题数据库,因此我们可以关闭这 个风险了;然而,直到我们建立了 ClearQuest 的 Web 界面,客户才可以对项目的风险和他们可以支持我们的领域看得更加清楚。(后来当我们关闭这个风险时,我们不能提供时间或者基础设施来建立 ClearQuest,但是一个大的项目将很明确的会从 ClearQuest 中受益。)
客户很高兴我们的进展如期完成,一部分是因为我们的工作产物对他们来说不是感觉不相关的。当我们继续的移到 RUP 的产物时我们必须通过大量的指导来维护客户的舒适感觉并温和的进入新的概念:用例、业务对象等等。
我们觉得我们的时间进度是切合实际的并且设计是良好的除了有非常小的意外。这就意味着资源必须尽快的到位,并且审查返回必须是及时的。我们也必须从一开始就关注高级别的风险,因为我们不能让他们在晚些时候遛进项目的第 1 阶段。
本文中所虚构我们是一家软件公司 Lookoff Technologies Incorporated,我们的客户 Audiophile Speaker Design, Inc. (ASDI),它雇用我们实现他们最初的 IT 需求。对于更详细的信息,参见 第 1 部分。
这 个第 3 部分文章重点的介绍了在 Rational Rose 中完成的早期建模活动。首先我们来对 ASDI 现有的(“as is”)系统进行建模,通过业务用例和业务对象可以显示当前事情是如何工作的。我们将从这个反映现有系统的模型创建出符合 ASDI 新的需求的系统模型,并且将这个系统模型作为建立软件的基础。
伴随着这本文有 2 个 演讲稿(来 自于 Rational 用户大会 2000) 这里讨论了以下主题: Yves Holvoet 的 “维护分析模型与多个设计模型的同步” 和 Robert Bretall 的 “结构化你的 Rational Rose 模型”。后一个演讲稿附带一个 Rose 模型。
第 3 部分快照 |
第 3 部分所使用的工具和技术:
被创建的或者被更新的工作产物:
|
捕获“目前的”系统
有太多新的和被改进了的 IT 系统在已有系统被了解之前被启动。甚至是当已有系统还缺乏 IT 组件的时候,有必要在可选的和改进的方案被建议之前对当前的业务活动情况进行分析。然而人们总是跳过或者草草的完成这一步,但是这做会导致以下的问题:
创 建一个业务模型以捕获“目前的”系统的情况可以是非常快速的任务并能够产生有用的分析线索,这些线索将简化对“将来的”系统的定义。在创建这个模型中能够 对我们有帮助的一件事情是工作状态(SOW)。虽然 SOW 主要用来描述“将来的”系统的需求,但是它也提供了ASDI 的当前业务流程的有用的背景信息。
在 Rational 统一过程(RUP)初始阶段部分存在一系列的用于业务建模的方法(也是就在我们项目的第 1 阶段)。与 ASDI 一起创建一个 IT 系统,我们需要一个“目前的”模型以捕获文件的流转和他们的当前系统的交互活动。我们在 Rational Rose 中创建了下列 RUP 工作产物作为业务建模工作的部分:
注意在以前的一些项目中,我们跳过了业务建模的步骤,因为我们是建立一个全新的系统,或者是因为我们已经非常好的了解了已有的业务模型。但是因为我们对 ASDI 的业务是陌生的,因此我们觉得这一步是十分重要的。
我们也考虑到开发一个 业务术语表(使用 RUP 提供的工作产物模板),但是我们发现我们的术语中的大多数是相当标准和明确的,而且这些术语在我们的业务对象模型中被充分的捕获了。更加复杂或者严格的项目将会从创建业务术语表中获益以确保在所有产物中的一致性。
当 我们使用 Rational Rose 创建我们的模型时,我们感到仅仅简单的创建图是不够的。我们发现仅仅通过图的方式表达模型对图的创建者是容易理解的,但对图的阅读者来说却是很难读懂的, 因此我们为每一个图附加了文档(通过在图上点击并在文档窗口输入文本)。我们也为图中的每一项提供了文档 — 用例、业务对象、用户或者其他项 — 用一到两行的文字来描述每一项的目的。
创建模型
我们从一个开始点来创建我们的新模型文件( ASDI.mdl
),我们使用符合 RUP 中定义的结构的 Rose 模板(见图 1)。因为我们在 RUP 中完成大量的工作,这将使我们工作的很好。RUP 的模型模板是可以在启动 Rose 时看到的,我们可以通过向导来访问的几个模板之一,或者你也可以在 Rose 应用程序的 Frameworks
目录中找到他们。
图 1: RUP 模型模板 |
我们对模板的结构做了一些改动以符合我们的需要和选择。例如,我们直接做了一下的修改:
接下来我们必须添加一个计划(schema)区域到模型中以使数据库架构师可以跟踪数据建模的工作。
管理模型
将 Rose 模型按照不同团队成员的责任分摊到包中通常是需要花费一定的功夫的。包的结构应该被创建的使在团队成员之间共享职责相对的简单一些,这可以通过划分系统成为不同的部分来实现:分析(比如,贯穿用例和业务对象),体系架构和设计。
我们的团队虽然不是很大,但我们还是要考虑到在模型之上的协作问题。我有几个 Rational Rose 的浮动的许可证,这足够我们所有的人同时访问模型,但是我们也需要使我们能够 并发的访问模型的某一部分。因此我们使用 Rose 的 “单元控制” 的特性以对模型进行适当的分解。
在我们的团队的组织结构中的角色(如在 第 2 部分被描述的)这些角色所拥有的对模型各部分的输入和更新的指责被显示在表 1 中。因此,团队中的其他成员,比如初级的开发人员和项目工程师将只拥有对模型进行访问的权限以完成他们的开发工作。
角色 | 输入/更新职责 |
组长/高级分析人员 | 打包管理 用例模型(业务和系统) 业务对象模型 体系架构 设计 |
高级开发人员 | 体系架构 设计 |
数据库架构师 | 体系架构 计划(Schema)设计 |
表 1: 模型输入/更新职责 |
我们对模型进行了分解,如图 2 中显示的 Rose 图。此时这个模型的结构服务于我们需要,因为我们有 3 个人直接的维护这个模型。将来,当团队和项目逐渐扩大时,这个模型结构可以被容易的分解为更多的 *.cat
文件。
图 2: 模型分解 |
关于分解 Rose 模型的额外信息可以在 Robert Bretall 的演讲稿中找到。这里只指出来自于它的模型结构讨论中的几个有价值的事情:
*.cat
文件中。) 使用 Rational Rose 分解模型成为分离的 *.cat
文件是很容易的。如图 3 所示,我们简单的右键点击我们想在单独的文件中控制的包;然后在上下文菜单中选择 Units > Control Use-Case Model ,这使我们可以控制这个包和这个包中的所有子子项。稍后在项目中,我们将重组一些 *.cat
文件成为几个更小的被控制的包以进一步的发布建模的工作产物。
图 3: 在 Rose 中创建分离的 *.cat 文件 |
建模用户和接口
一个 角色(actor)是与系统交互的外界的人或者事物;这既可以是使用系统的人,也可以是其他的接口类型。建模系统的用户和接口以及他们之间的依赖是非常有用的;它不仅仅可以给你一个系统的完整实体,而且也可以提供给你对于将来的安全性和角色建模工作的良好信息。
图 4 显示了我们如何在 Rose 中将角色容入我们的业务模型当中 — 尤其是,在一个与客户服务相关的用例图中,这个用例图摘自我们的业务用例模型。两个特殊的原型类被使用:业务角色和业务用例。 Rose 可以基于原型分配自定义的图标,并且我们选择这个方法为用例和角色分配外表略有不同的图标 — 加了一条斜线 — 因为我们觉得区别用于构建软件的系统模型与业务模型是重要的。
图 4: 客户服务的用例模型摘录 |
( 点击放大) |
当 我们将业务用例模型充实起来时,对于业务对象模型来说将会出现一系列好的候选对象。虽然创建一个“目前的”系统的业务模型看起来要花费大量的工作(主要的 工作量是生成图),但是我们觉得它是值得的。在我们过去的“目前的”模型中,已经包含了大量的在实验室工作簿中的注释和正式的技术注释。为了得到已有业务 流程的更加清晰和完整的视图,应该在花费一些时间在 Rose 中捕获这个信息。
理解系统交互
有 时人们会将重点都放到了系统的某个单独的部分上,但实际上系统各部分之间的交互也是非常重要的。充分的考虑整个系统部分的交互将使系统各部分之间集成的共 性和可能性更加明显。这是为什么我们后来使用交互图的原因之一(显示系统各部分间的交互)以验证我们的设计;这对在分析和设计中识别流程和固有的缺口是非 常关键的。
在项目的早期我们关注的交互:
我 们花费了一些时间在 Rose 中捕获我们对当前业务组织和过程的理解,结果是生成了对于我们理解现有系统非常有用的业务对象模型。在对象模型中的图(在图 5 中显示的是其中的一个)类似于标准的类图、除了他们使用了特殊的原型类:业务实体、业务控制和业务角色。业务实体表示被动的领域对象比如发票或者报告,而 业务控制是执行功能的对象,可以表示报警或者机械的作用。(业务角色在之前已经被讨论了。)
图 5: 业务对象模型摘录 |
我 们在业务用例建模之后很快开始业务对象建模。业务用例的说明文字确定了一系列合适的业务对象。如果是跨越多个用例的对象,比如“购买请求”和“产品”、“ 产品队列”和“运输队列”是被识别的业务领域的关键对象。有时如果我们意识到它是不合适的或者已经被其他对象覆盖到了,我们将删除这个业务对象。通过这种 方法,可以快速的在任务(用例)和 事物(业务对象)中筛选与 ASDI 业务相关的业务对象。
在某些情况下,业务对象模型将演化成系统类。这对于实体对象来说基本上是正确的,实体对象通常被映射为容器类或者是数据库表。在其他一些情况下,业务对象模型简单的作为一 个为理解客户领域的引用的结合点来使用。我们确认客户已经完全理解了图形化的符号和每个图的内容,因为他们的检查和批准是关键的。
总 而言之,我们花费了大量的时间在业务建模的工作上。这并不一定是一流的或者是完全的,但是对于我们来说应该是能够对当前的业务流程有一个足够的认识。在项 目的第一个或者两个月后,我们将很少的提及业务模型,但是我们觉得它是值得花费时间的,因为它是形成“未来的”系统的系统模型的一个必要的步骤。当一个新 成员加入到我们的团队时,我们可以通过浏览业务模型来帮助他们来理解新的领域;然而,一旦对它熟悉了,业务模型将很少再被查看,除非是阐明术语。
|
将 SOW 转换成用例
计划“将来的”系统,我们需要将已经用文字形式表示的 SOW 需求(在 第 2 部分中 被讨论的)转换成为经过深思熟虑的用例。换句话说,通过对“目前的”系统的业务用例的创建(就像早些时候所讨论的),我们准备为“将来的”系统细化这些用 例。这将不是一个快速的步骤,但是它经历超过两周的时间。(在 RUP 的术语中,这个转换反映了一个从初始阶段到细化阶段的逐步转化过程。)我们在业务建模上所作的工作,获得了当前系统的经验并将它的功能划分进了业务用例, 这对我非常有帮助。( RUP 的文档显示了从业务用例模型到业务对象模型和系统用例模型的演进;我们发现这是非常正确和有帮助的。)
我们并不担心映射 SOW 需求到“目前的”系统业务用例的原因是 SOW 需求中的许多在当前的系统中是不存在的。我们早期所创建的业务模型只不过是一个临时的产物,它用于我们确保我们的团队理解 ASDI 的当前系统。
用例对文字说明
一系列的工作簿和工作产物(包括那些后面被列的 “参考资料”)解释了用例建模和理解需求的好处。我们发现许多被提及的好处是真实的,虽然定义用例的内容不是琐碎的任务。与良好的文字说明相比,如果用例没有被良好的设计,对于你来说他们当然没有用的。
这里是一些开始创建用例时的误解:
结果,我们决定用例建模标准和指南需要被组长定义。这些包括下面的指南:
当决定什么应该包括在我们的用例中时,我们应该遵从在文章中指出的指南 "Fine Tuning Rose to Complement Your Process":
从“目前的”到“将来的”演进
当 我们从“目前的”转移到“将来的”时,我们的许多业务角色被演化成了系统中真实的用户和接口,虽然有意义的重构是必要的。这是自然的,因为当重新定义其他 角色时新的 IT 方案统一了原有的一些角色。一些业务实体作为抽象的概念消失了,而其他的一些通过计划(schema)或者详细的设计被映射成了类。
在图 6 到 图 9 中显示了我们早期工作产生的对于“将来的”系统的用例模型的一部分。通过图形、协作图和时序图以及进一步的详细分析的帮助,它将随着时间推移而成熟。
图 6: 早期的角色模型 |
图 7: 核心的客户服务用例 |
图 8: 客户定单用例 |
图 9: 系统管理用例 |
就 像 RUP 的描述,“用例建模的最重要的目的是与客户或者最终用户沟通系统的行为。”然而,增加复杂性可以导致我们的客户也许感觉不舒服的风险,我们发现当我们充实 用例时,在用例中引入更高级的包含和扩展关系是很有价值的。在详细的检查我们的用例模型时,被包含和扩展的用例频繁的出现。我们发现甚至在我们理解了系统 的(包括用户)外界接口视图,通过包含和扩展用例来分组功能产生在重要的计划、架构和测试中的好处。然而,在我们看到客户对检查这些高级的关系没有信心 时,我们有时会将被包括和扩展的用例从检查的包中拿掉。
|
总结
我 们现在已经有了一个描述了 ASDI 业务中已有过程和实体的画面,并且在对将被构建系统的任务和角色的系统建模上有一个良好的开始。虽然还有一些在团队内的关于跳过业务建模工作的讨论,但是 我们觉得我们的工作将收到回报。其他的好处是,它使客户容易的以一种舒服的和相对非技术的级别进入用例。
不同项目之间的用例建模有着显著的不同;用例的定义、用例的关系、详细的程度等等都是经常被争论的。最后我们发现当我们向客户展示我们的用例模型时,一致的并频繁的检查是成功的关键。
计划未来
我们需要得到技术上的强劲进展。客户正向我们索取比我们现在可以提供的更多的有关用户界面、代码原型和工具选择的信息。我们必须开始提供屏幕的模拟并开始考虑适当技术的选择;现在重要的是开始使用更加实际的、技术的产物和购买工具(尤其是如果我们需要更多的培训)。
虽 然我们还没有开始进入体系架构阶段,但是我们知道系统必须是基于 Web 的并且是跨平台的,同时从原型到企业级方案都要是可扩展的。我们已经学习了 J2EE ,并且 ASDI 雇用的 IT 经理也首选这个技术平台。因此,我们觉得开始探索 J2EE 的成本和能力是明智的。我们的团队在这个领域不需要太多的培训,这是另外一个因素。数据的存储应该被更多的考虑,然而,因为 IT 经理极力的推崇面向对象的数据库(OODB)方案。因为我们对关系型数据库更加在行,这对我们来说是一个艰难的路程,但是我们还是同意了考察 OODB 的方案。
我们非正式的与我们的客户审查了我们的所有工作产物,但是是时候进行正式的检查了。在接下来的几周中,我们将建立 我们的 Rational SoDA 模板以便我们提供我们的第一个正式的交付:详细的软件需求。我们同意这个文档应该包括用例和非功能需求(可靠性、可用性等等)。
我们的用例开始稳定了,开始指明在对 SOW 合适的可跟踪的地点。我们需要用 Rational RequisitePro 来确保维护 SOW 与我们的用例之间的映射。
我们接下来的方向,应该是:
主要风险
我们仍然觉得时间是非常紧的,并且存在着时间进度或者预算的一些出入 — 并且我们的风险列表还在增长,甚至我们还没有开始任何的认真的技术探索。其中有以下新的风险:
本文中所虚构我们是一家软件公司 Lookoff Technologies Incorporated,我们的客户 Audiophile Speaker Design, Inc. (ASDI),它雇用我们实现他们最初的 IT 需求。对于更详细的信息,参见 第 1 部分。
这个第 4 部分文章的重点在于 ASDI 项目的细化阶段,尤其是在用例分析方面(细化我们的用例以对工作状态(SOW)添加可跟踪性,并且标准化和生成用例文档)并选择合适的工具和技术。
第 4 部分快照 |
在第 4 部分演示的工具和技术:
产生或者被更新的产物:
|
细化并文档化用例
图 1 显示了在 ASDI 项目的第 1 阶段(RUP 的初始和细化阶段)中的用例的演化。就像我们在 第 3 部分讨 论的,我们在初始阶段创建了业务用例,然后在细化阶段的初期将业务用例转换成体现了“目前的”系统的用例。现在我们是在细化阶段的最激烈的时刻,我们正准 备细化我们的用例,为系统完成向详细需求的转换。这个演进是自然形成的,因为直到断定了是否我们开始定义的用例是正确的,我们才可以为用例进行更为详细的 信息添加。一旦详细的系统需求被完成,我们将它作为一个正式的交付物被 ASDI 审查通过。
图 1: 第 1 阶段用例的演进 |
( 点击放大) |
标准化用例文档
在我们与 ASDI 对用例进行非正式的检查的会议中我们对用例进行了注释。用例图和包也被我们的高级团队成员定期的检查了,一个“健全的” 检查将带来以下的结果:
我们现在的重点是记录我们已经了解到的东西。我们与 ASDI 在用例文档的形式上达成了一致,并且我们非常高兴他们愿意接受在 Rose 模型 中对每一个用例直接添加文档的方式。这对于我们来说,事情变得更加简单了,因为这意味着更低的对文档美观的期望。
在 多个团队成员共同工作的情况下,我们发现我们需要标准化与每个用例相关联的文档。因此,我们起草一份用例的文档模板,并应用于 Rose 模型的每个用例中。在图 2 中显示的内容是被粘贴到每个用例作为模板的文档窗口。注意我们在这个模板中使用术语 “variation” 作为对 RUP 可选流概念的速记标记。
图 2: 用例文档模板 |
在项目的后来,我们意识到在模型( *.mdl和 *.cat) 文件中有大量 ASCII 形式的文档,使模型的加载慢了下来。感谢我们的快速的电脑,这个副作用还可以被容忍,但是在后来的项目中我们使用了更加正式的方法来维护用例的内容,通过 一个自定义接口的方式。(就像在文章 "Fine Tuning Rose to Complement Your Process" 所讨论的那样)另一个可选的方法是使用 Rose 附带单独的 Microsoft Word 文档到用例的特性(通过右键点击用例并从上下文菜单中选择 New > File )。
用例的可跟踪性
ASDI 原来的期望是 SOW 将最终成为一个大的文字形式的文档。我们通过与他们的不断的讨论,最终他们意识到这种方法的缺点,并作出了让步的姿态。他们现在明白了使用用例的好处并很 快的掌握了相关的概念,并理解了使用用例将给他们一种不需要对模型进行预排的非常强大并适当的反馈的方式。无论如何,一个好的时间和精力的分配已经进入了 SOW ,可以理解 ASDI 希望我们能够确保不会遗漏任何在 SOW 中被捕获的东西。
为了提供这个保证,我们使用了 Rational 的工具来建立在 SOW 需求和我们的相当稳定的用例之间的可跟踪性。首先我们通过 RequisitePro 将 Rose 模型与被管理的需求文档关联起来,通过选择 Tools > Rational RequisitePro > Associate Model to Project 并选择 SOW 。然后我们相应的映射每一个用例到主 SOW 需求,通过右键点击用例并在上下文菜单中选择 Requirement Properties > New 。如图 3 所示,我们展示了一个 SOW 需求列表,并从中选择适当的需求。
图 3: 关联需求与用例 |
( 点击放大) |
我 们已经在模型中建立起了这些关联,我们可以跟踪需求到用例,相反也可以。双向的可跟踪性是十分重要的,因此我们既可以发现遗漏的需求也可以发现新添加的需 求。遗漏某一需求是不可接受的,跟踪需求到用例可以使我们很容易的发现我们的任何遗漏。添加需求而没有清晰的调整将导致项目范围的蔓延并对项目的时间计划 和预算有着负面的影响。为了防止这一切,我们应该跟踪所有的用例到每一个存在的 SOW 需求或者变更请求。
不像跟踪需求 到用例,反方向的跟踪经常被忽略,但是我们可以很容易的在 Rose 中完成这一点。为了浏览与一个用例相关联的 SOW 需求,我们简单的在 Rose 模型中右键点击用例,并选择从上下文菜单中选择 View RequisitePro Association 。这会弹出一个窗口指示哪一个 SOW 需求是被选择的用例跟踪的,如图 4 所示。如果用例没有被映射到一个 SOW 需求,底部的两个域将显示 “NONE” 。我们也可以通过 Rational SoDA 产生更加复杂的跟踪报告。
图 4: 被 Rose 报告的对于一个用例的 SOW 需求 |
( 点击放大) |
注 意在这个方法中使用一个捷径是重要的。通过我们使用的方法,我们可以仅仅可以每次关联一个用例到一个需求,反之亦然;然而,一个用例实际上是可以跟踪回到 几个需求的,同样一个需求可能分布到多个用例中。我们不必苦恼映射多对多的关系。我们直接将用例关联到 SOW 中的需求,但是更好的方法是引入一个被 RequisitePro 管理的用例规格文档,它包含很多用例需求的文字描述并可以实现多对多的映射。(详细的描述可以在 Rational 白皮书 "Use Case Management with Rational Rose and Rational RequisitePro"中被找到。)我们现在觉得用例规格文档是我们不应该跳过的重要步骤。
用例文档的检查周期
我 们与 ASDI 都明白文档频繁的检查周期会导致无止境的循环下去。结束任何文档都是困难的,因为每一次阅读文档时检查人员经常会产生一些新的想法。在迭代的方法中,相同 的 “何时结束的” 的挑战也会出现在软件的文档和其他任务中。为了满足 ASDI 对关于结束的关心,我们描述了我们对用例文档的检查周期将是什么样的,我们努力的借用了 RUP 中所描述的概念(见图 5)。
图 5: 文档检查周期图 |
( 点击放大) |
就 像你所看到的,我们的每一个文档都经过了一系列的迭代。对于我们来说找到一个工具来支持它是重要的,我们在 Rational SoDA 中发现这样一个工具,它允许我们生成 Rose 模型以外的文档。虽然对文档直接做修改是诱人的,但是这将带来文档与模型不同步的风险。如果你将在一个或其他的文档中投入精力,更好的方法是在模型中投入 精力。除了你开发的软件用户手册以外,模型几乎是可以在软件被交付后还可以继续被引用和维护的产物。
通过使用 SoDA ,产生报告是简单的。为客户的检查生成用例文档,我们从 Rose 的 报告菜单中选择 SoDA Report ,这将出现一个报告模板的列表,如图 6 所示。从中我们选择 a RUP use-case model survey 模板。
图 6: SoDA 报告选择 |
( 点击放大) |
每 一个模板提供了一个缺省的报告(作为 Microsoft Word 文档)伴随一个空的部分和相应的内容表格(TOC)。图 7 显示了我们选择报告的 TOC 。我们通过与 ASDI 检查 TOC 开始,并且我们查看了我们的用例以决定是否需要在报告中根据我们的需要进行合适的裁剪。
图 7: SoDA use-case survey 报告(TOC) |
( 点击放大) |
你 可能想知道在写任何实际的内容之前,为什么我们担心与 ASDI 一起检查 TOC 。我们发现这是一个重要的步骤。有时 ASDI 给我们一个 DID (数据项描述),它对正式的交付物提供一个 TOC ,但是我们发现在开始充实内容之前根据 TOC 从 ASDI (或者内部的团队检查人员)得到信息是有用的。有时我们在每一个部分填写显示我们将如何细化的标题,但是在首次的 TOC 检查时几乎没有任何的段落内容。
后续的文章部分将讨论 Rational SoDA 和 模板定制的更加详细的信息。
细化:不只是用例
为了使生活更加有难度, ASDI 期望我们在继续随后的任务之前创建用例文档。我们必须提醒他们用例文档直到软件被交付才会被 “完成” ,除非他们不想让我们在需求变化或者新需求出现时更新用例。我们说服了他们,他们不会对 完成的里程碑甚至是 自信的里程碑感兴趣。然而,他们希望放一个检查标记到下一个要做的 “详细的用例文档”项,因为它是十分成熟的,我们同意这个观点。
真正的挑战是说服 ASDI 所有需要的活动应该是并行的发生,而不是所有的里程碑都是按照顺序被交付的。我们把它作为在项目早期的一个常规的关注点,它仍然没有被完全的解决。为了让他符合用例分析的一些活动,我们提出了这两个观点:
我们非常高兴 ASDI 同意模拟和原型作为分析阶段的有用的部分。这使我们可以在用例分析被完成前进入到架构的和工具的选择问题中。
|
选择工具和技术
工 具和技术选择从来就不是微不足道的任务,虽然它常常被忽略。团队经常根据启动成本、“小工具因素”、好奇心或者对工具和技术的忠心来作出选择,相反,他们 应该考虑生产成本、可靠性、可得到的培训、团队技能和特性标准。在评估过程中添加一些正式手续可以确保工具的选择使基于项目需要的而不是个人主观的意见。
正式的工具评估
一个在 RUP 中很少关注的地方是团队挑选现货(off-the-shelf)— 也称作商业现货供应 (COTS) — 工具的过程。可以了解这个过程领域知识的一个地方是卡内基-梅隆软件工程学院(SEI),那里有 COTS-Based Systems Initiative关注于 COTS 产品的选择和采纳的策略。特别有趣的是 SEI 的 product feature checklist;虽然它更关注于选择软件系统的组件和框架,但是其中的很多策略也可以被用于选择软件开发工具、Web 服务、数据库等等。
工具选择标准
ASDI 向我们展示了这些他们觉得将影响我们的工具选择的标准:
应用服务器的选择
我们拥有 J2EE 应用服务器的经验,因此我们非常幸运 ASDI 选择基于 Java 方案。不过在我们还是快速的评估了象 Perl/CGI 和 PHP 这样的入门级的 Web 方案之后的计算技术(主要是 Microsoft .NET/DNA)。
我们一致发现 Orion Application Server是友好的并是最成本有效的开发环境。在那里 Orion 唯一评分低的方面是 供应商的稳定性和支持。提供 Orion 产品的公司是非常小的并且不具备象 BEA 的 WebLogic或者 IBM 的 WebSphere的 能力和信誉。然而在与 ASDI 的检查人员讨论后,我们互相同意 Orion 的 J2EE 标准遵从的好处足以抵消这些风险。如果第二阶段开发需要,仔细的开发将可以确保我们拥有轻便的可以移植到其他应用服务器方案的代码。因此我们选择了 Orion — 这意味这启动成本为零,因为 Orion 是免费的。
Web 服务器选择
Orion 带有高速的内建的 Web 服务器,因此当 Orion 被选定后 Web 服务器的选择过程也就有了结论。它主要的竞争对手是 Apache。然而,在 Orion 网站上显示 Orion 已经在某些测试方面达到并超过了 Apache 。
数据库选择
使 用哪一个数据库的选择不是显而易见的。数据库通常不会执行高负载,但是它需要有丰富的特性支持。比如,复杂的数据关系要求有完全的引用完整性限制。同时, 系统必须可以 24 小时不间断运行,因此我们希望它具有热备功能、复制、其他的可用性和容错特性。我们是否会用到所有的特性将在以后被决定。
我们觉得 PostgreSQL仅 仅是一个有资格的开放源码的候选者。它有很好的 ANSI SQL 支持和引用完整性,并且只要并发用户的增长不太大它可以保持良好的性能。然而,数据存储需要更多的来自于一个供应商的 committed 支持。此外,我们觉得 PostgreSQL 在线支持(比如用户社区讨论)对我们来说是不够的。 MySQL实际上是更加流行的开放源码的数据库,但是它缺少太多的特性(比如,外键支持)。
然后我们转到主流的数据库: DB2, Oracle, and Microsoft SQL。 我们在 Oracle 上有着丰富的经验,但是新的处理器单元价格模式对于我们的这个应用来说是过于昂贵了。Oracle 的每 MHz 每 CPU 的基本负荷,意味着 ASDI 将为系统忍受高的生产环境成本,除非他们愿意将 Oracle 安装在一台 P-133 的机器上。Microsoft SQL 被淘汰了,因为它是基于私有平台的。如果创建一个基于 DNA 的方案,Microsoft SQL 自然是首选的,但是对于 J2EE 来说很少被选择的。
最后,我们选择了 DB2 ,我们的调查表明 DB2 对 SQL 有着非常优秀的支持、强大的容错特性、公道的价格模式和正在增长的和被培训的在线用户集合。 IBM 的 JDBC 驱动是高性能的,而且他们的个人版可以被免费的用于开发团队中。不幸的是,我们缺乏 DB2 的技能,这就意味着一些培训在原型活动期间被需要。
你也许正想知道对于 ASDI 首选的 OODB 的选择发生了什么。在通过原型和探索产品后,我们很快个到了结论,使用 OODB 得到的好处不足以抵消它带来的风险。
集成开发环境(IDE)选择
在这一点上,我们不想使用任何高端的 IDE 产品,有几个原因:
相反,我们混合使用了以下工具:
很自然,这些工具可通过使用 Rational 工具来弥补在测试、调优和代码覆盖上的缺乏。
|
总结
在 这个阶段我们看到了用例的演进(通过可跟踪性和文档化)并且通过 ASDI 参与的用例的检查,我们快速的发现我们是自由主题方式的专家。这通常是软件开发项目中的最大挑战之一,因此早期的并有效地建立这种关系才是真正的胜利。我 们与 ASDI 的关心通常是很好的。他们很快的理解并同意了基于 RUP 的开发过程而没有花费我们太多的精力。这是令人惊讶的,被他们给的首选的瀑布型的开发最终取得了这个和约。很多被 RUP 鼓励的迭代和增量开发的方法被良好的进行了调整,并且 ASDI 也看到可好处。
我们幸运的是工具的选择相当的简单,并在 项目的早期被完成。Rational 的一些工具被用来节省我们的时间。在之前的项目中我们使用 Excel 来管理需求,但是我们发现 Rational RequisitePro 是一流的并是完整的方案。此外, Rational SoDA 报告可以大大的降低我们的文档生成的成本。因为这个项目是我们第一次使用 SoDA,我们非常高兴 ASDI 对标准的 SoDA 模板表示满意。
计划未来
到 现在为止,我们把焦点放到了需求相关的产物上,并且花费了相对来说不多的时间来评估技术并创建原型以支持工具的选择。现在对我们来说重要的是通过创建更有 挑战的原型来揭示系统更加复杂的领域,并开始在实际的开发中使用工具。我们是否会用到 XML ?如果会用到,我们应该使用什么样的解释器?我们需要什么样的安全机制?我们应该使用 Enterprise JavaBeans 吗?象这些问题我们将很快有答案。
换句话说,是时候从分析转移到架构和设计了 — 尽可能快而不是晚,因为大多数的技术风险将在接下来的几周显现出来。我们有一个很好的功能基线包含一系列定义良好的用例。对于我们来说避免分析麻痹大意和维护前进的动力是重要的。
主要风险
没 有新的风险被识别出来;实际上我们的风险列表比以前更短了。因为 ASDI 同意对于这个项目 OODB 是不合适的,我们因此不再有技术上的风险要管理。他们也放松了对我们的交付产物的正规形式和他们预想的结构,并且他们毫无保留的批准了我们的基于 RUP 框架的文档。
在我们关心的剩余时间和工作量的问题上,当我们增加了对所需能够的理解和对技术熟悉后,我们觉得预算更加符合项目情况了。更进一步的技术探索勿庸置疑的将揭开新的挑战。
本文中所虚构我们是一家软件公司 Lookoff Technologies Incorporated,我们的客户 Audiophile Speaker Design, Inc. (ASDI),它雇用我们实现他们最初的 IT 需求。对于更详细的信息,参见 第 1 部分。
这个系列的第 5 部分首先检查了一下项目的时间进度,然后当我们进入了架构、设计、数据建模和创建原型时,我们已经在下一个阶段进行细化阶段中了。
第 5 部分快照 |
在第 5 部分演示的工具和技术:
产生或者被更新的产物:
|
项目的时间进度
在开始进行详细的架构和设计工作之前,让我们来检查一下 ASDI 项目的整体进度。就像你可以 第 1 部分回 想起来的,这个由多个部分组成的系列文章覆盖了项目的第 1 个阶段:以一系列需求、一个参考架构和代码(理想的可重用的)为结果的概念的验证。到目前为止,我们大概使用了整个第 1 阶段预算的三分之一,但我们已经接近了项目时间进度的一半了。这是在我们的预料之中的,因为我们有意的让进度稍微慢一点。分析和计划活动总是以较慢的步伐 移动,团队应该在项目开始时逐步的将他们建立起来。
因为第 1 阶段要求一个相关的结构化的和正式的概念的证据,我们将它作为一个小的项目处理,通过在演进的产品上进行测试和 QA(同级审查)来完成它。RUP 有一些用于开发概念证据的机制,基本在分析和设计工作流的执行架构的合成的活动中。我们正在进一步的将概念的证据转化成可用的 beta 版产品。我们能够将更多的功能、风险的降低和产品的成熟放到这个阶段中,我们越多的将技能和知识用到系统的产品版本中,我们的客户就越高兴。
这个接下来的一系列的任务将比之前的活动更加具有技术性。我们正很好的向架构。设计、数据建模和原型前进。在 第 4 部分中我们讨论了一些原型和评估如何进行我们的工具选择;现在我们的原型的关注点在测试我们设想的需求、系统说明和设计上。
|
过渡到架构和设计
架构和设计活动是在 ASDI 项目中最令人愉快和具有创造力的任务。我们为我们将系统计划的高效、安全和简单优雅而自豪。技术方案的远景在多次令人兴奋的会面、自由讨论和技术探索中最终形产生了。
简单的讲,架构意在捕获技术上灵活的方案,这个方案可以覆盖上个月我们定义出来的系统需求。不论是向前看(对于设计)还是向后看(对于需求),架构团队都将承受巨大的压力。 Rational Rose 的集成开发环境通过让我们能够做以下的事情简化了这个挑战:
注意,因为我们在过去的项目中创建的系统与目前这个系统类似,因此如果我们引用一些参考架构,我们的架构将会从中受益。然而,我们不能在已存在的包或者设计模式中找到任何可重用的机会,因此我们只是引用了已存在系统中可能会在将来用到的思想和类。
从用例到设计类的转化
从用例到设计类的转化过程是缓慢的,需要进行多次的迭代。这牵扯到分析人员和设计人员,因为我们有很少的既可以舒服的与客户讨论业务领域又可以使用特定的工具进行分析、细化设计产物的人员。
这个活动的目标
有时将需求直接的转换 成代码是诱人的。实际上,我们在以前的项目中就是这样做的(因为我们有非常详细的需求说明),我们在我们对项目的理解上非常自信。这样就产生了一个错误。 需求被遗漏,范围很难被跟踪,并且大量的工作和返工是无用的。使用设计模型来连接在需求和代码之间的鸿沟是重要的;设计模型可以在开发和测试之前很久捕获 错误和有问题的假设。
在从用例向设计类转化的过程中,我们希望能够实现:
实现稳定的设计
从用例和分析类到设计和设计类的转化是不可避免的模糊的。在我们能够拥有我们感到满意的设计之前,我们需要做大量的工作。图 1 显示了我们以我们的方法定义一个稳定的设计的主要活动。
图 1: 从用例模型到设计模型的转化 |
前面的文章部分讨论了多数的在图 1 中作为”架构“准备的活动和产物(特别是 SOW 需求、用例、业务对象模型和分析类)。此外,这些其他的活动对设计工作也是重要的:
这些将在接下来的部分连同如何处理新的和改变的需求一起被讨论。
|
打包和子系统结构
在开始考虑设计类之前,整个团队要对一个良好的包结构达成一致同意。不管我们最后的决定是什么,它都应该成为设计过程中的指导方针,所有团队成员都要遵守这个指导方针。
包结构的选择
我们一直在争论是按照子系统(图 2)来划分包还是按照架构的层次来划分(图 3)。表 1 列出了每种方法的有点和缺点。
图 2: 按照子系统定义包 |
图 3 : 按照架构的层次进行包的划分 |
方法 | 优点 | 缺点 |
按照子系统定义包 |
|
|
按照架构层次划分包 |
|
|
表 1: 打包方法的比较 |
最终我们使用了第一种方法,按照子系统来划分设计模型。我们觉得系统是足够小的,我们可以保持好子系统之间的一致性。
子系统结构设计
我们的顶层的包结构的一个最初草稿就象图 4 。你可以从顶层的包中看到被识别的子系统(因此,原型 <
图 4: 顶层包的结构 |
在我们将这个早期的草稿变成最终稳定的包结构之前,我们进行了大量的讨论。下面是我们关注的一些问题:
作 为一个例子,我们将着重关注在 command gateway 子系统上。虽然系统的很多地方都是以一个内部的和外部的 Web 接口为中心的,我们还是计划提供一个安全的、基于 XML 的命令网关(command gateway),这个命令网关允许 ASDI 的系统与它的大客户之间的形成一个 B2B(business-to-business)的接口。这个特性允许这些客户能够从他们已有的系统对 ASDI 查询、提交和更新信息。这是非常重要的,因为一些公司的需求是不能通过 Web 接口访问,相反他们需要的来自与公司的代号的批量的或者是幕后的提交。
在每一个包中,我们最初的类图都来自于我们的用例、业务对象模型、注释和访谈。图5 显示了 command gateway 子系统从早期的思想到详细的设计的演进过程。
图 5: command gateway 的初始设计 |
在这个第一轮的设计中,我们简单的识别出 command gateway 子系统的主要部分,在这个层次上存在着必须被关注的问题:
在后续的设计中(图 6 ),我们识别出了在系统中的更多依赖关系,并开始识别看起来象实现类的东西。我们仍然在争论高级别的概念,因此我们对文档和类的签名并不感兴趣(方法和属性)。文档和类的签名应该在我们觉得设计开始稳定时被填充进去。
图 6: command gateway 的中期设计 |
( 点击放大) |
就像图 7 显示的那样,我们后来细化了一些我们识别出的依赖关系、适当的方法和属性(被隐藏在图中以节省空间),并且添加了一些技术的细节。例如,通过建立原型我们识别出将 JSSE (Java Secure Socket Extension) 作为在客户和服务器之间的 SSL 连接的方案。JSSE 被直接集成到了 JDK 1.4 中,当对 JDK 1.4 以前的版本它只是一个附加的部分。
图 7: 成熟的 command gateway 设计 |
( 点击放大) |
这个设计还不是最终的。虽然设计已经通过众多的场景图被测试过了,但是在接下来的数周和数月的编码中将发现设计中不正确的地方或者或者遗漏的细节。
|
管理需求的变更
当 我们进行架构和设计时,我们识别出了添加新的需求或者对已有系统需求进行细化的需要。忽略一些小的变更是诱人的,但是我们看到需要相当多的预算来完成变 更。在预算上的小的缺口将增加需要的时间,并给客户一个不好的先例。我们发现跟踪所有的添加和变更将有助于我们用检查保持期望,并迫使我们问,“在将来我 们真的需要这个吗?” 这是一个我们通常忽略的关键点:如果一个需求不是足够重要进入系统,那么这个需求就不值得去实现。
有时,需求的引入会对已有的进化和预算带来负面的影响。这就要求我们坐下来和客户讨论选择 — 但是首先,我们应该在我们内部进行讨论,以便我们能可信的向客户提出备选方案,而不是简单的“即兴表演”。选择通常包括以下的方面:
对 用例进行变更不是问题,因为我们对用例进行了严格的版本控制,并可以直接的在模型中更新他们。此外,Rational RequisitePro 的使用将编程集成回到 SOW 中也是容易的。然而,追溯我们所希望的,我们已经花费时间建立了 Rational ClearQuest 来管理需求的变更。有时变更是被内部识别出来的,但是更多的情况是有外部的请求产生的。我们的变更管理过程是非常笨拙的,包括每月的会议、硬拷贝的文件等 等。更加无缝的变更请求过程几乎会为控制范围的增长、产生更好的系统和更高的和约价值带来的更多的机会。
|
数据建模
当 我们开始进行上面所描述的设计工作的同时,我们也开始建模数据了。在以前的项目中,我们使用 Rational Rose 进行设计,并发现在持久类和暂时类之间的分割有点笨拙:一旦我们识别出了一个用于持久存储的类,我们便设置它的持久属性并开始用其他的工具对他建模。在 ASDI 项目中,我们使用了集成在 Rational Rose Enterprise 中的 data modeler 进行数据建模,并且发现过度更加的成熟。
实际上,我们最初在使用老方法上范了一个错误 — 将持久对象放到他们自己的文件夹中,并遗忘了他们 — 但是,我们自己发觉了他们并使用 Rose 将这些对象转换成了数据模型。将所有收集到的持久类放入一个包中,我们可以通过鼠标右键点击包,并转换他们成为数据模型(通过从上下文菜单选择 Data Modeler > Transform to Data Model )。
数据建模器在 Rose 模型中创建了一个数据库计划。我们后来将这些计划从它的逻辑表示转化成了一个物理的 DB2 安装,并给工程团队访问表和测试数据。
|
原型
作为架构和设计的基础,良好的分析是重要的,但是原型也是非常有价值的。很多的主意在纸上看起来很好,但我们的假设只有原型才能提供的证据。
工程团队非常喜欢原型活动。典型的对这些活动的时间计划是非常自信的,目标是模糊的,技术是新的,并且 QA 轻松的,因此原型通常是很有趣的 — 金钱的大量浪费。我们发现如果原型没有清晰的、可测量的目标,它很快就会沦落到“我能做什么...”的境地,而不是降低风险的任务。
我们通常尽力与 RUP 的演进产品理论保持一致,RUP 可以指导我们将我们所有的原型演化成最终的产品。事实上,我们对快速的探索保留了术语“原型”。为了从原型中释放出最大的价值,我们经常忽略代码的标准、 同级检查和类似的过程。原型的一些方面(类的说明、设计模式或者编码习惯)也许可以被重用,但是我们在重用这一点上给团队非常小的压力。相反,我们的原型 的结果通常被总结成为技术注释或者成为可以被活来项目参考的样例应用。
马上,一个工作包必须被起草。对它的开发人员来说这个包能够概括特定原型的目标。我们为每个原型分配了预算和时间计划,这里包括了任务完成之前的中期检查。
我们不总是通过直接的编码来创建原型的。有时我们通过在写任何代码之前进行学习来执行工具的评估。当评估数据库时,比如,我们基于我们的经验、供应商提供的信息和第三方的检查从类表中去掉一些候选工具。
我们发现几种很好的构建原型和工具选择的方法:
良好运用原型的关键在于决定原型的实现的程度。很少有原型能够在推荐中被设计成为给人 100% 的信心。相反,原型必须演示足够的结果以减少风险到可以忍受的级别。
表 2 列出了一些我们在这个项目中采用的特定原型活动。
原型活动 | 结果 |
研究(覆盖特性、成本和性能) | Orion Application Server 的选择(更多信息,看 第 4 部分) |
OOBD 的评估(覆盖特性和市场份额),以满足客户的偏爱 | 决定放弃使用 OODB(更多信息,看 第 4 部分) |
研究关系型数据库(覆盖特性、成本和性能) | 选择 DB2 (更多信息,看 第 4 部分) |
JSSE 评估 (覆盖复杂性、稳定性和安全性) | 在 B2B 方案中包括 JSSE |
用户界面模拟(测试可用性、工作流和“外表感观”) | 对于“外表感观,用户界面指南和标准的开发” |
在 Rational Rose Enterprise 进行数据建模(使用 Rose 的 data modeler) | 熟悉使用 Rose data modeler;生成创建表、触发器等等用于早期原型的数据库教本 |
创建 B2B 接口的 XML 搜索及原型(prototype) | 一致同意良好格式的 XML 比信任第三方的解释器带来的利益或者对丰富标记的 XML 更重要 |
EJB 与 JSP 和 servlets 的对比 | 决定在 第 1 阶段使用 JSP 和 servlet |
表 2: 原型活动 |
|
总结
我们对系统的架构和设计已经相当的成熟;我们的原型取得了巨大的成功,并且我们将很快开始实现的工作。这意味着跟踪项目的过程要比保持项目远景在规定的方向上和仔细的计划每一个迭代和增量更加的重要。
到现在为止,我们已经试验并选出了所有主要的技术和第三方的工具,并且我们非常满意工具提供商能够做他们的工作。我们通过被计划的原型做了这个决定,并且不只是希望或者相信银弹。原型也帮助我们的工程团队,给我们我们具有完成工作的知识和需要的技能。
计划未来
在不久的将来,我们将进入系统的实现中。我们计划实现以下目标:
在做任何实现之前,我们必须在多个方面对项目的阶段做准备,包括更新我们团队的结构以满足我们的新需要,文档化代码和设计协定和交流有效的开发方法(包括单元测试和同级检查)。工程团队将需要完全的理解双向工程、调试、分析和其他更多的东西。
主要风险
JSSE 原型指出 JSSE 是一个比我们最初预期的更加复杂的 API 。尤其是,安全方面对项目范围的蔓延产生了巨大的机会,因此我们必须与 ASDI 密切的工作以准确的理解他们需要什么样的安全。来自于需求的工作不会涉及到密钥长度、加密机制和其他底层的细节。
最后,我们在 EJB 之上选择和 JSP 和 servlet ,我们知道我们架构可能需要在第 2 阶段进行一些返工。我们愿意将它作为那个阶段的风险保留,因为我们完全的提交了这个技术选择。
本文中所虚构我们是一家软件公司 Lookoff Technologies Incorporated,我们的客户 Audiophile Speaker Design, Inc. (ASDI),它雇用我们实现他们最初的 IT 需求。对于更详细的信息,参见 第 1 部分。
本文讨论了团队的进展进入了实现阶段,并且因此进入了 RUP 的构建阶段。我们挑选了在 ASDI 项目的第一阶段被使用的大部分技术。设计的情况相当的好,虽然在本系列的 第 5 部分中被讨论的包的结构和设计在未来的一到两周内还将继续的演进。例如,包结构的部分被重新定义来反映预期的 Java 包命名习惯。
第 6 部分快照 |
在第 6 部分演示的工具和技术:
被创建或者更新的产物:
|
铺平道路
在能够进行开发之前,我们必须在管理和团队领导的层面上完成下面的事情:
指导方针和标准
RUP 强调在一个产品被构建时同级评审的重要性;我们将在后面了解更多的细节。团队必须对同级评审的标准达成一致意见,以避免走向两个极端:松散的评审将带来非常微小的价值,或者过度严格的评审将产生大量的注释行,比如"这个被实现了,但这里我是如何实现的"的注释。
对于我们的 Java 代码,我们创建了一个基于 AmbySoft Inc. Java 编码标准的 编码标准文档。这些标准被证明在我们进行同级评审中是意义重大的。这些标准不仅可以帮助我们为客户产生更加一致的和高质量的交付系统,而且还允许我们的团 队成员更加容易的在不同的子系统(和项目)之间进行调整。我们发现如果开发人员们对编码的形式和构建非常熟悉的话,他们将能够非常快的融入到统一的团队之 中。通过避免使用模糊的命名习惯、不充分的注释和不好的编码风格,开发人员能够创建出使其他开发人员更加容易接手的代码。
培训
通 常的情况下,工程师们都在尽力的学习被需要的技术以在业务上保持竞争力;然而,一些项目也会引入一些需要团队培训的新技术。我们在 ASDI 项目中并没有处于这种情况下,因为这个项目中使用的架构和技术都是我们所熟悉的。我们在这个项目中的培训是关于 Rational 工具的使用、UML 、Java 编码标准和 J2EE 设计模式的。虽然我们在这些领域有着非常好的知识背景,但是这些知识多数是在团队领导的头脑里。因此,培训由非正式的午餐时间和被团队领导发起的下午会议 组成。我们发现这些维持在一个小时到半天的会议是非常成本高效的(但前提是,你必须要有具有充足知识和良好沟通能力的团队成员)。
因为我们的话题是与整个公司相关的,因此我们鼓励其他的技术人员参与到这些培训会议中。我们发现有更多的技术人员参与将会引发更加有价值的思想上的交换。最其码,我们计划能够让 ASDI 项目中所有的工程师都参加的会议(不论是参与分析、设计、实现或者测试的工程师)。
团队结构的演变
团队的结构从在系统的分析期间演变到了为满足实现期间的不同需要的结构。如表 1 所示,大量时间上的约定发生了变化,并且有五个新的职位被加了进来。
|
角色 | 分析期间 | 实现期间 |
项目管理 | 项目经理 | 50% | 25% |
财会支持 | 15% | 25% | |
质量保证 | 10% | 25% | |
项目工程 | 项目工程师 | 50% | 25% |
团队领导/高级分析人员 | 100% | 75% | |
工程支持,除了配置管理(CM) | 20% | 10% | |
工程支持: 配置管理 | 20% | 40% | |
支持和评审团队 | 10% | 5% | |
高级开发人员 | 100% | 100% | |
初级开发人员 | 100% | 100% | |
数据库架构师 | 25% | 25% | |
高级开发人员(远程) | — | 100% | |
中级开发人员(远程) | — | 100% | |
初级开发人员(远程) | — | 100% | |
集成和测试(I&T)领导 | — | 50% | |
I&T 初级成员 | — | 100% |
表 1:团队结构的演进 |
团队结构的变化和变化背后的原因被总结如下:
这些职位被增加:
后 来我们发现,我们的团队结构也许是太具有杀伤力了,因为我们的工具仅仅是为了实现在第一阶段中的概念的验证的。我们也许应该在没有太大伤害的前提下调整一 下系统的构建和质量保证的正式过程,并且依然要满足我们的第一阶段的目标。最后,我们建立了高质量的概念的验证,而且比我们最初预想的为第二阶段的工作提 供了更多的可重用性。
开发方法
一 些之前的项目要求我们在共享的开发环境下工作,并且这经常是痛苦的源头。工作在公共代码之上的开发人员经常会打断开发过程中其他的软件部分的工作。我们有 时因为架构上的或者许可证上的限制被要求在一个共享的环境下工作,但是我们还是希望在每一个开发人员的机器上拥有一个独立的环境。我们计划以一种正规的基 础将开发人员的组件集成到一起。
在 ASDI 的项目中,提供独立的开发环境是容易的,甚至对于我们的远程办公也是如此。仅有的共享方面是 DB2 的数据库,但是我们能够为每一个开发人员建立独立的数据库计划(schema),这样就可以去除任何的潜在的问题。此外,我们为我们的工程团队设置每一个 类被一个单一的开发人员所“拥有”。我们发现这非常好的减少了我们的合并与修改的工作。我们从来不相信以 CVS (Concurrent Versioning System)方式在一个源文件上实现并行开发的哲学,因为在一个方法上的改变将会带来在其他方法上的细微但又重大的影响。我们觉得最安全的方法是将每个 类实现的责任交给单独的团队成员。
关于我们的特定开发环境,我们发现 Orion 应用服务器、Rational Suite DevelopmentStudio 、J2SE JDK 和 DB2 客户端软件能够很容易的符合 P-III 500 和 256 M 内存的机器。Orion 惊人的小的足迹和高效的设计是他能够在这样低的硬件配置的机器上运行的主要因素。
基本的开发周期在图 1 中被显示出来(它大量的借用了 RUP 的内容)。
图 1:开发周期 |
每 一个开发人员最初从基线设计说明开发工作。开发的的第一个迭代包括使用 Rational Rose 作为起始点生成代码的框架。一系列的迭代(包括时常发生的小的构建)都是从这里开始的。开发人员非正式的对早期的迭代进行单元测试,同时也与团队的领导协 商任何与设计的背离。小的设计变化可以通过电子邮件进行沟通,然而重大的变化需要一对一的讨论以确保变化是适当的并且不会对系统的其他方面做成负面的影 响。显然,任何对接口(甚至是公用方法)的变化要求特别细致的检查和冲突分析。设计要定期的通过逆向工程进行更新,合并任何的变化回到 Rose 模型中以维护系统的最新画面。
回顾一下,我们希望我们投入更多的工作在场景上。如果我们的场景已经演示了系统的大部分,我 们就能够在 Rose 中使用报告来显示类之间的详细依靠了。这将使我们可以产生关于特定变化的影响的更具有根据的推测。而不是,我们必须编写脚本来根据被配置管理的代码进行文 本的搜索以确定谁正依靠着给定类的特定的方法。
当遇到复杂的事情和问题时,他们将被交给团队的领导。通常团队领导或者亲自 的协助解决问题,或者让开发人员解决问题,再或者使用来自其他团队或者公司的帮助解决问题。有时,我们会遇到技术上的需要与客户讨论的问题和后续的需求本 身的更新问题。例如,我们的一些安全方面需求的遵循 JSSE (Java Secure Socket Extension) API 的变化。
一旦代码被充实起来,开 发人员编译一系列的单元测试,集成与测试团队创建一系列的组件测试,他们被设计用来测试性能、功能和可靠性方面的需求。在完成了代码和单元测试之上,开发 人员要为同级评审过程(后面被描述)组装一个评审包并等候反馈。评审过程有时会导致设计的修改,其他时候算只是简单的识别出一些 bug 或者需要增强的地方。
跟踪进展
因为我们只是刚刚开始实现的工作,因此我们不准备使用来自于 Rational ClearQuest 的缺陷统计功能作为测量我们的进展部分。相反,我们依靠两个主要的信息来源:任务报告和小的里程碑。
任务报告以每周为基础被开发人员提交。这些报告能够指出最近一周的任务工作完成情况和在任务中的预算的花费情况,并且可以估计任务中剩余的工作量。任何阻碍任务进展的障碍也会在每周的总结中被报告。
小的里程碑甚至是更加关键的,因为他们有时揭示了重要的问题。团队领导经常要求小版本的构建、非正式的星期五下午的演示、代码预演或者甚至是当场的代码检查。如果我们发现一个团队或者团队成员不能在时间期限内实现一个适当产品的里程碑,这有时意味着存在需要帮助的问题。
|
确保系统的质量
软件工程的目标是在给定的时间和预算内产出高质量的软件。质量的精确定义从团队到团队,从项目到项目会有所不同。对于工程团队来说质量相关的目标包括:
我 们发现 Rational 工具能够帮助我们满足这些要求中的很多。为了举例说明 Rational 工具能够在哪些地方帮助我们,这部分将重点集中在客户接口的 command gateway 部分。就像在本系列第 5 部分所注明的,这个网关是一个 B2B (business-to-business)接口,这个接口允许大公司可以查询 ASDI 的零件的可用性、提交订单、更新他们的客户信息和查询运输或者帐目状态。
更新设计:双向工程
command gateway 的设计经历了一系列的迭代,已经成为了被显示在本系列的第 5 部分 成熟的设计; 然而,一种情形引发了远程的高级开发人员得到与设计的同步。她在她自己负责的部分提出一些优秀的想法,并且我们能够通过双向工程合并他们 — 也就是说,通过逆向工程她的改变合并到我们的 Rose 模型中。这种简单的设计与最新代码变化的同步对于维护我们系统的质量是十分重要的,因为我们的大多数事情都是围绕着设计模型进行的。
command gateway 通过远程被开发(在总部),因为他们具有在 Java 、 XML 和 JSSE 方面的丰富的经验。我们在周五将最新的设计发给高级的开发人员,并且计划在接下来的星期通过电话会议来讨论设计。然而,开发人员那个星期五病了,并且没有 收到设计;实际上她并不知道任何我们已经完成的进展的信息,因为我们的 最初设计并不是详细的。在周末她在家中继续的通过她的膝上型电脑进行着项目的工作,却没有意识到她已经丧失了与 command gateway 设计的同步。
在接下来的电话会议中,高级的开发人员详细的谈论了她对设计的改进、她对新技术引进和她在整个开发中的大的超前。这使团队领导非常的惊讶,当然开发人员听到了关于设计上的更新也是非常惊讶的。我们协商同意忽略最新的设计和开发人员的工作以找到哪一种方法我们应该使用。
当我们选择好方法之后,开发人员的进步是显著的,并且比我们以前的工作更加深思熟虑。她使用了一个开放的产品 Castor,这个产品能够封装 XML 数据的映射到 Java 的对象,并且她合并了一些比我们提议的方案更加好的设计决定。因此,我们同意更新设计以反映她的良好的方法。
因为她开始于她的草稿代码,因此我们需要返回她的设计到我们的模型中。这是相当容易完成的:我们简单的提供给开发人员我们最新的对于 command gateway 的 *.cat
文件,并且逆向工程她的代码成为模型。在项目的稍后部分,相似的情形逆向工程将会带来巨大的帮助。
逆行工程的过程
当我们进行逆向工程时的第一个步骤是在 Windows 中设置 CLASSPATH
环境变量。这个环境变量的位置依赖于 Windows 的版本,但是典型的情况下你可以通过系统的控制面板找到它。(在 Windows 2000 中,查看面板的高级标签。)如果 CLASSPATH
环境变量没有被适当的设置,Rational Rose 在评测代码与外部的引用类之间的关联时遇到麻烦,通常会导致类分析的失败。在我们的例子中,我们必须设置这个变量为
D:/jdk1.3.1/jre/lib/rt.jar;j:/usr/local/lib/xerces/xerces.jar; |
这个值指向了核心的 J2SE 类的运行时库和我们用来映射 Java 对象和 XML 数据的 Castor 的 XML 绑定类。
然 后我们定义项目的说明,在 Rational Rose 中使用 Tools > Java > Project Specification 选项(弹出如图 4 所示的对话框)。我们确认所有被发现的路径,并且我们指出了在 Rose 中我们的代码的根。
图 2:在 Rose 中定义项目的说明 |
接下来,我们选择 Tools > Java > Reverse Engineer 选项,它弹出一个对话框(如图 3 所示)提示我们选择将要被分析的源文件。我们选择我们感兴趣的包 — asdi
类,来引入高级开发人员的所有代码 — 然后点击 Add Recursive 按钮。然后我们选择所有被列出的文件并点击 Reverse 来逆向工程他们。
图 3:在 Rose 中进行逆向工程 |
在首先的几次尝试当中,我们意识到我们在设置我们的 CLASSPATH
环境变量时范了错误,导致在日值文件中出现了一些错误信息。(重要的是不要忽略这些错误,他们有时指出文件的解析完全的失败了)。
逆向工程的结果
一旦逆向工程被成功的完成,我们就能够在我们的模型的逻辑视图和组件视图中发现被命名为 asdi
的包(见图 4 和 5)。
图 4:逆向工程产生的类(逻辑视图) |
图 5:逆向工程产生的组件(组件视图) |
逆向工程在分析类之间的关系上是相当有效的。当类的变量被声明为类的成员变量时,找到所有权关系是更加可靠的。有些关系被获取的并不正确(例如,在我们的 Java 代码中通过本地范围的实例变量创建的关系),因此一些继续的检查工作是必要的。
可以理解的是 Rose 没有为代码创建图。在上百个类中, Rose 没有办法知道如何进行逻辑的分组这些类来适当的表示系统的架构和设计。然而,所有类之间的关系已经被适当的生成了,产生设计和组件图是相对容易的。在图 8 中显示的是在逆向工程后修改的网关设计。
图 6:修改了的(逆向工程了的)网关设计 |
在图 6 中显示的设计上的主要变化是引入和 Castor 的 XML 绑定的接口。我们不必做我们自己的分析(使用 Xerces-J 或者 XML4J)来进行 XML 消息到对象的转换,因为 Castor 显然提供了这种映射的能力。 Talker
类封装了 JSSE 的功能,并且 java.util.Vector
子类提供了进入消息的简单管理。Vectors 通过 add(...)
和 remove(0)
的调用使先进先出(FIFO)的查询更加容易。一般情况下我们选择 Vector
之上的 ArrayList
,但是因为查询必须是在线程之间共享的,我们同意使事情保持简单。( Vector
是同步的,但是 ArrayList
不是,它要求 Collections.synchronizedList()
被使用)
性能分析
一 个与新的 command gateway 方法相关的风险是不确定的关于 Castor 的序列化 API 的性能问题。使用经过长期测试的 XML 解释器,我们知道他们的内存使用和性能在负载条件达到高峰时是足够的。我们需要评估 Castor 产品以确保它能够符合我们的系统性能的要求。
为了加速我们的这个过程,我们决定使用 Rational Purify 和 Rational Quantify 来观察 Castor 的行为。这些工具允许我们精密的检查资源的需求和运行时 Castor 的行为。为了方便起见,而不干扰实现整个 JSSE 客户端和服务器端的代码,我们决定去掉 JSSE 的功能(在 图 6中的 Talker
类)来提供虚构的 XML 消息。
检查 Java 内存的使用
我 们想要了解被 Castor 引擎需要的资源的水平。使用这个开放源码的产品对于我们的项目是稍微有一点冒险,因此我们需要确保它是仿弹的并且不是严重吞噬资源的。我们设计了一些通宵 运行的单元测试来找出任何内存的泄漏或者稳定性的问题。Rational Purify 当前具有 Java 内存分析的功能,因此我们决定用它试一下。
在 C 或者 C++ 项目中,我们已经强制在组件上运行 Purify 来预防进入产品代码的内存访问的违规。使用 Java ,象读空指针、内存泄漏和数组越界的问题已经不是什么问题了;然而,Purify 依然在分析 Castor 中为我们提供了非常有用的特性。
为 了运行 Purify ,我们首先必须设置参数配置以使用正确的 JDK 。除了我们选中了" Pause JVM console after exit "选项之外,我们为我们的 JDK 版本使用缺省的设置,以便我们能够在 Purify 测试被完成时看到我们的应用的任何错误或者结束的结果(见图 7 )。
图 7:为 Rational Purify 配置 JVM |
为了运行 Purify 测试,我们选择 File > Run 并且通过浏览 Main.class
文件设置程序名为 Main.class
。这设置了如图 8 所示的缺省选项。我们所做的唯一改变(因为切断的显示,所以在这个图中看不到)是更新命令行参数来运行 asdi.exchange.command.Main
,因此 Purify 的缺省设置是没有包范围的 Main
。
图 8:运行一个 Purify 的 Java 测试 |
有趣的是,我们第一次就遇到了类格式的异常错误。在过去当我们在 JDK 1.1 和 JDK 1.3 之间迁移时我们看到过这些异常,在那里 *.class
验证规则发生了变化。由于一些原因我们有一次遇到了这个问题,但是仅仅是在 Purify 中遇到了这个问题。如果我们使用 J2SE 的 javac.exe
代替 jikes.exe
(IBM 的高速编译器)来编译 *.class
文件,问题就消失了。 Rational Purify 的分析结果在图 9 中被显示。
图 9:对于 command gateway 的 Purify 输出 |
( 点击放大) |
我 们运行了这个测试几个小时以确保它是可重复的和可预见的。没有问题被注意到,除了垃圾收集的问题。虽然内存使用从没蔓延,但是我们的应用在每妙秒中处理和 映射 200 个命令时强制的执行了有意义的垃圾收集。在现在为止,我们没有看到性能的问题,因为在测试的任何一个点上 CPU 的负载从没变得紧张。
分析代码
Rational Quantify 一直是我们在 C 或者 C++ 项目中喜爱的工具。我们通常使用它来跟踪性能的问题确保没有哪断代码浪费了 CPU 或者实时周期。
Quantify 在外表和配置方面类似于 Purify ,并且 JVM 的设置以相同的方式被完成。Quantify 对于了解 Castor 是如何影响的 CPU 和时间是非常有用的,并且它可以帮助我们知道 Castor 的大量工作在哪里。图 10 显示了在分析我们的 command gateway 代码时 Quantify 环境的一个样例截图。
图 10:对于 command gateway 代码的 Quantify 输出 |
( 点击放大) |
对 于我们来说有一点变得清楚了,就是当 Castor 运行时 Xerces (Castor 的底层 XML 解释器)使用了相当数量的 CPU 。我们显然遇到了相同的问题,因为我们仍然必须要解释 XML 消息以提取内容。Quantify 使我们能够了解到在调用栈中对于每一个部分的执行的最大和最小的时间,被派生的时间消耗和其他有用的信息。最后,我们觉得在我们的系统中包含 Castor 使合适的,因为它展示它的健壮性和一些好的特性。
单元测试
单 元测试是我们的开发工作中的至关重要的部分。多数的开发人员只是进行一下形式上的单元测试,甚至不被要求单元测试;然而,我们发现通过正式的单元测试过程 来确保一致的精确和质量是具有巨大价值的。开发人员通常将重点放在他们测试中的错误条件上,然而单元测试应该测试软件的几个方面。一些资源提供了对于团队 来说在定义角色和单元测试规范的样子的有用的信息被列在本文后面的 "参考资料"。
开发人员经常定义他们自己的单元测试规范,因为这些测试是非常底层的白盒和黑盒测试,他们也是很详细的,可以让集成与测试团队理解。为了在单元测试规范中强制一致的详细程度,我们将他们包含在同级评审过程中。
同级评审
我 们建立了同级评审来帮助我们在应用系统的 bug 影响生产环境的系统之前识别出他们,并且我们观察到一些事情非常有趣:在评审过程中很少的 bug 被识别出来。最初这看起来显示了一种在代码评审价值的缺乏,因此项目工程师们并不是非常认真的检查每一件事情。这里是他们所发现的:
同 级评审也通过技能和方法的交叉传授改进了整个团队的能力。开发人员通过了解其他每个人的想法建立起良好的设计模式和编码习惯的部分。代码的评审允许使用大 量的时间对各种编码策略进行有价值的赞成和反对的讨论;因此,通常为了学习的目的我们会尽量让至少一个初级的开发人员参与评审。
我们的编码标准不仅仅是简单的针对风格的问题,而且也涉及到了编码习惯、编码实践和性能问题。标准在三个午餐小时被呈现给了团队,连同的还有针对评审过程的指导方针。
评审过程的步骤如下:
最初我们存在着对这个评审过程会花去过多时间的担心,但是我们发现它这个过程是极有价值的,它提供了:
|
总结
我 们已经通过指导方针铺好了路,调整了团队的结构和经过深思熟虑的开发方法,我们发现开发(包括对设计的细化)正很好的向前进展着。工程团队开始了解了 Rational Suite DevelopmentStudio 工具的威力。对于这些工具的学习曲线是不寻常的,但是通过这段时间我们已经能够很舒服的使用他们了。特别要指出的是,我们通过使用 Rational Rose 的双向工程、Rational Purify 的检查 Java 内存使用和 Rational Quantify 的代码分析的能力获得了很大的利益。使用这些工具,连同建立单元测试和同级评审,我们很好的达到了 ASDI 系统的质量目标。
计划未来
我 们越快的使我们的团队习惯小版本的构建,将对我们的项目越有好处。我们预期为子系统建立每星期五的构建周期,并也建立每第二个星期五进行子系统的集成。为 这些小版本的构建组成团队是有价值的,并且对于团队来说也是非常好的通过让大家看到事情被合并成为一个整体来鼓舞士气的方法。
在接下来的几周中将是产生内部和外部的早期演示的工作。为了外部的演示我们将很快的将用户界面屏幕集成到一起。这对我们来说也是非常好的机会来得到额外的需求反馈。
主要风险
甚至是在开发的早期阶段,远程开发的挑战就一直敲打着我们,并且我们知道当我们开始集成我们的组件和子系统时这个挑战将会变得更加的辣手。早期的”实践构建“需要很快的开始以便我们能够平滑的实现集成的过程和解决早期的问题。
贯 穿整个项目远程开发对于我们来说都是一个挑战。虽然我们以前也做过远程开发,但是我们还没有解决如何集成跨越分离的地理位置的团队工作结果的问题。我们了 解到 Rational 的工具不能完全的消除远程开发的问题,但是他们至少能够减轻远程开发的痛苦。例如,我们还不能防止高级开发人员在 command gateway 设计方面的分歧,但是逆向工程能够通过最少的工作帮助我们评估和集成她的变化。
为了符合我们严格最终期限,开发必须以高效的步伐继续前进。自从我们提供给客户软件的架构文档,已经有一段时间了,客户渴望看到一些进展。尽快的提供集成的演示是重要的。
本文中所虚构我们是一家软件公司 Lookoff Technologies Incorporated,我们的客户 Audiophile Speaker Design, Inc. (ASDI),它雇用我们实现他们最初的 IT 需求。对于更详细的信息,参见 第 1 部分。
这个系列文章的第 7 部分主要关注在我们继续开发的构建和演示上。这些话题在 Rational 统一过程(RUP)中只是很简略的被提到,因为这个话题对特定项目的本质有着非常大的依赖。你将如何并在什么时候集成和演示你的系统依靠于你的客户、项目规模和项目风险。
第 7 部分快照 |
在第 7 部分演示的工具和技术:
被创建或者更新的产物:
|
在细化和构建阶段的演示
演 示发生在 ASDI 项目的几个点上,尤其是在 RUP 的细化和构建阶段。然而,构建却是迭代过程、集成被分别开发的组件和作为小的里程碑为跟踪开发过程服务的常规部分,演示更趋向于特殊的目标。在我们的项目 中,这些目标依赖于项目进展到什么地方而不同,并且这些目标依次的确定了演示的精确性和他的观众。演示可以是基于构建的,也可以不是(例如,他们可以是被 模拟的用户界面),演示可以是针对公司内部的,也可以是针对于外部用户的。
演示的目标
在细化阶段,演示具有下列的目标:
在构建阶段中,演示有这样一些目标:
另外,早期的演示为后面被集成与测试人员进行的正式的构建提供了实践上的指导,正式的构建包括测试所有的需求和完整的构建文档等等。
内部演示 VS. 外部演示
内部团队的演示很自然要比外部演示的次数和花费的精力要少。无论何时我们向客户显示软件,我们都希望在向客户演示时避免任何的故障,但是这在内部演示检查时并不是十分重要的。
内 部演示通常在一周中比较晚的时候被执行,也许是周五下午的晚些时候的团队片刻休息的时间。在演示的过程中工作在一个特定子系统或者线程的一个或者多个开发 人员可以讨论他们的进展、显示他们的工作进度和讨论任何他们遇到的问题,我们能够在演示中收集到这些信息。讨论必然伴随着有关方案、好的想法和被其他团队 成员发现的一致性问题的产生。这些演示要求很少的准备 — 也许只是不加修饰的构建版本并且快速的执行构建版本的使用过程以确定系统是可以被接受的。演示很少会非常顺利,但是我们并不把这种现象看作成问题,因为我 们知道对他们进行精化将意味着额外的准备和测试的工作。
外部演示具有一个被增加的正式的标准。因为我们希望维持客户的信心,并且不浪费他们的时间,我们遵循了这样一些指导方针:
这些防范措施看起来似乎有些过分,但是我们发现一个准备不充分的客户演示将产生很少的价值,并且是浪费时间和项目预算的。
构建和演示计划
表 1 列出了在 ASDI 项目的细化与构建阶段我们为构建和演示制定的大致计划:
RUP 阶段 | 构建或者演示的种类 | 频率 | 时间选择 |
细化阶段 | 工具评估原型 | 一次 | OTS 产品评估交付之前 |
用户界面模拟 | 每个 GUI 用例两次 | 在用例分析活动早期和细化阶段后期 | |
架构原型 | 一次,满足性能的要求 | 在软件架构文档(SAD)交付之前 | |
构建阶段 | 用户界面外观 | 两次,分别在两周执行 | 构建阶段的早期 |
设计原型 | 一次 | SAD 交付的几周后 | |
组件演示 | 每周 | 开始于构建阶段早期 | |
子系统构建 | 每周 | 进入构建阶段的 1 到 2 周 | |
子系统演示和局部系统的构建 | 半个月 | 进入构建阶段的 3 到 4 周 | |
完整系统构建和系统演示 | 每月 | 进入构建阶段的 4 到 6 周 |
表 1:构建和演示计划 |
|
演示方法
有很多方法能够执行演示。这些方法看起来是相当明显的活动,但是有一些能够增加演示价值的新颖的方法。
联合应用开发(JAD)
联 合应用开发(JAD)基本上包括为了非常集中和激烈的自由讨论活动,将所有的项目涉众集中在在一个演示场所中,典型的包括一些演示的种类。我们在我们的项 目中尝试了几次 JAD 方法,但是我们发现这个方法执行起来是困难的,并且产生了一些混合的结果。我们所检查的多个参考(有两个参考被列在文章结束部分的 "参考资料"中)都强调了 JAD 仲裁者的重要性,JAD 仲裁者应具备很高的技能和远见,我们觉得我们在这个方面能够做的更好。
在 我们的项目中, JAD 意味着将 ASDI 的问题领域专家、 ASDI 的 IT 领导、我们的高级工程师和来自于双方的项目经理集中到一起。我们关注我们在需求和用户界面设计方面的讨论(虽然不是在同一时间)。在 JAD 会议之前,我们已经提供了一个议程安排,从议程安排中仲裁者将引导会议进行。会议中进行很多的讨论,并且一个高级的图被画在了白板上。(我们使用了一个数 码的白板,我们可以在这个数码白板上保存和打印被画出的图,这是非常节省时间的。)我们也让一个工程团队的成员花费一些时间来记录任何支持图的注释。
我们在项目的两个阶段尝试使用了 JAD 方法:在早期的细化阶段针对角色(actor)和用例(use case)需求;和在后期的细化阶段针对用户应用程序的工作流程和设计(主要是用户界面设计)。这里我们将转向到我们的例子的后者。
在 这个第二次的 JAD 会议上,我们项目中在 JSP 和 HTML 方面做擅长的开发人员展示了基于用例分析和注释的早期用户界面模拟。我们在每个屏幕界面上花费和 15 分钟的时间,与全体参加会议的人员针对特定的用户界面外貌和整体的界面感观、被展示的功能和贯穿系统的导航进行集体的谈论。当有任何建议时,我们在现场对 这些建议进行了探讨。我们将所以的讨论结果结合到了一起,并在过程中学到这些教训:
显示和解说
我 们发现简单的显示和解说的演示方法是最有效的并且最容易管理的方法。不像在现实的 JAD 会议中处理问题那样,使用被大约一周左右的周期分开的小的演示可以给我们时间来考虑关于请求的影响,并且我们可以提出针对于被识别出的问题的解决方案。如 果经过批准我们能够有额外的 JAD 的培训,我们也许能够将几个显示和解说的演示压缩到一个或者两个 JAD 会议中;在同一场所中保持每一个人进行有效的协作可以节省我们计划中的大量时间。
客户实际操作的机会
随着构建阶段的进展,我们的系统到达了客户能够开始对其进行操作的时候了。如 表 1 所 示,系统演示开始了四到六周时,我们就进入了构建阶段。在这些演示期间,我们允许 ASDI 直接的使用系统。这不仅给了他们更多的参与到项目中的感觉,而且我们也从他们那里得到了关于系统的反馈,如果不让他们使用系统,我们将无法得到这些反馈。 当系统逐渐成熟起来时, ASDI 花费了更多的时间在系统上,并且他们为我们提供了免费的测试工作和在产品开发早期修改一些问题的机会。然而,伴随着允许客户自由的访问一个不成熟的系统也 会存在一定的风险:
当 ASDI 操作系统的早期版本时,我们必须不断的提醒他们,我们仅仅是在创建第一阶段的概念验证,并且那些“外表漂亮”的非关键特性将会被延迟到后续的项目工作中完 成。然而,我们确保了他们所有的建议都被记录了下来,因为他们的许多想法都是非常好的,并且值得我们在接下来的工作中再次的考虑。通常,ASDI 理解我们为他们提供实际操作系统的机会的意图和限制,因此上面所提到的风险对于我们来说不是什么问题。
系统的正面 VS. 系统的早期版本
开发团队花费了一些时间来辩论对于早期的演示创建系统正面相比于使用一个演进的产品的优点。典型的,正面是一个掩藏了系统背后场景的产品,它被尽可能快速并且低成本的实现。另一方面,使用演进的产品需要投入更多的设计和实现的工作到早期的版本中。
实际上,在 ASDI 项目的第一阶段中,为了演示图形化的用户界面,在分析用户工作流程的过程中我们尝试使用了这两种方法。表 2 比较了两种方法的结果。
演示外表 | 正面 | 系统早期版本 |
被使用的开发工具 | Microsoft FrontPage | JSP/Text 编辑器 |
在第一个演示之前准备时间 | 3 天 | 1.5 周 |
向客户传达工作流程/GUI 的能力 | 好 | 好 |
转移类似的外表到最终产品的能力 | 一般 | 好 |
针对请求和建议的回复更改演示的速度 | 非常快 | 慢到中等速度 |
在演示后的重用机会 | 不好 | 一般 |
培训时间 | 短期培训 | 短期培训(因为团队在在 JSP 上经过了培训) |
与后端的 servlet 和数据库集成的容易程度 | 不好到一般 |
表 2:使用正面演示 UI VS. 使用早期代码版本演示 UI |
我 们在项目的初始阶段和细化阶段的早期为演示使用了正面。虽然经常会有一些零散的演示,但是我们觉得投入是值得的。我们使用了 FrontPage ,因为我们没有与 Java servlet 和数据库集成的困难,因为我们还没有任何需要连接的数据库计划或者组件。因为我们在项目中使用了 FrontPage ,FrontPage 2002 的数据库集成能力已经得到了改进,如果我们在将来的项目中需要,我们甚至可以使用它来从数据库计划中显示测试数据。
一旦设 计开始稳定,我们就进入到了一个使用 JSP 和 servlet 的迭代的编码周期。在项目的早期部分(在初始和细化期间)编写零散的 Java 代码是价值很小的,因为在那个时候除了 Java 我们甚至不能确定我们将要使用 JSP 和 servlet 。使用 FrontPage 是更快更容易的,并且我们不用担心任何隐含的技术选择。
|
早期并且经常的构建
在 项目的构建阶段的早期开始产生系统的构建版本能够更加快速的消除问题,并且频繁的产生构建版本能够帮助保持项目中每一个成员的同步。在 ASDI 项目中在过多和过少的构建版本之间找到一个平衡点是重要的。选择频繁的构建就必须考虑到项目复杂性、休假计划、团队技能、客户可用性(对于外部演示)和组 件和子系统之间的依赖的问题。
子系统的构建
我 们的子系统集成了被分别开发的组件,并且有时导致生成系统的演示。我们并没有坚持要求所有的子系统的构建版本都具有演示;而是团队领导会实行一个内部的构 建版本 — 通常每个构建版本的计划时间是每周一次 — 恰好确保了各部分代码能够集合在一起。这同步了工作在子系统中的每一个人,因为例如,他们所有的人都必须为构建版本使用相同的数据库计划。当团队领导选择 演示被集成的子系统时,这个演示会在周末的团队会议上被展示,通过观看他们负责的系统部分是如何被改进的,给团队一种成就觉。
团队领导在建立这些演示上是高效的。整个团队都知道在星期五的上午开始修改他们的代码以为集成工作做准 备。典型的,生成构建版本是在中午过后,如果在集成过程中出现了任何问题,允许在一个或者两个小时时间修改和讨论。在确保所有的最近被更新的代码都已经被 检入(check in)后,团队领导将从源代码存储库库中提出所有的代码。
我们的配置管理工具是我们这个项目的一块绊脚 石。我们没有选择 Rational ClearCase 作为我们的配置管理方法,而是使用了免费的 CVS (Concurrent Versioning System) 工具提供的能力。配置管理是软件管理的重要组成部分,并且在项目之后,我们希望我们能够投入更多的时间在我们的配置管理工具的选择、集成和使用的指导上。 我们没有使用一个集成的方案就意味着:
我们决定如果我们赢得了项目的第二阶段的和约,我们将评估 ClearCase 作为我们使用的另一个 Rational 工具集中的工具。
系统的构建
一些或许所有的最近开发的子系统被集成成为一个系统构建版本,就像子系统构建一样,系统的构建有相同的好处和目标,除了:
工 程团队在没有集成与测试团队的帮助下完成了首先两个完整系统的试验版本。这些最初的构建工作是痛苦的:我们在配置管理上有很多问题;一些子系统接口级别的 细节已经丢失了;并且一些子系统稍微的落后于计划。在第二个试验版本中集成与测试团队作为观察者的身份加入了进来,并且开始了下一个系统构建的集成工作。 这有利于向集成与测试团队平滑的转移职责和知识,同时也不会在首先两个构建版本中浪费时间。
对于工程团队和后期的集成与测 试团队来说,对在每一个构建版本中应该包括什么有一个清晰的概念是十分重要的;否则,构建工作将会很慢的执行,并且会以浪费团队的时间结束。实际上,我们 很好的理解了迭代构建的过程和每一个集成工作的目标,并且我们能够成本高效的执行构建的工作。
|
总结
我们的构建和内部演示工作通常进行的非常平稳;然而,远程个构建需要来自于项目工程师的额外注意。对于远程开发的子系统的计划经常不能按时完成,因为远程的开发团队不能访问和核心工程团队一样的资源。
我们的客户演示是非常成功的。我们非常自信我们在构建阶段的早期拥有一个清晰的客户需求的描述,并且客户对我们构建的产品也有一个清晰的概念。在最终的产品交付期间,存在很少的错误期望和惊讶。
计划未来
现 在系统的构建开始进行了,我们很快的将步入测试工作。我们计划使用 Rational 的测试工具帮助我们完成测试工作。我们需要确保所有 ASDI 项目的功能都被适当的执行过,并且在一定的负载下测试我们 Web 应用的性能。这些活动也增加了集成与测试团队对系统的熟悉,并且开始学习使用测试工具。
主要风险
我 们的构建和演示没有增加任何的新的风险;实际上,发现并修改早期的问题帮助减少了风险。我们继续的感觉到在时间进度上的压力,然而,我们知道构建必须以快 速的步伐进行。在起草我们的功能测试说明中我们已经落后于计划了。 RUP 建议在项目的更早的时候开始这些工作,我们现在承受了巨大的压力,因为我们已经延迟了个活动。
本文中所虚构我们是一家软件公司 Lookoff Technologies Incorporated,我们的客户 Audiophile Speaker Design, Inc. (ASDI),它雇用我们实现他们最初的 IT 需求。对于更详细的信息,参见 第 1 部分。
本文是这个系列文章的第 8 部分,本文中对最初在这个系列的 第 6 部分介 绍的测试方面的主题进行了详细的讨论。在第 6 部分的文章中,我们看到了在早期的开发当中我们开始使用 Rational Purify 和 Rational Quantify 检查内存的使用情况和性能的瓶颈。同时也讨论了我们在早期的单元测试工作的很多细节。本文将描述这些工作的进展,并回顾我们使用 Rational 测试工具的自动化测试的能力来减少测试的成本,主要是 Rational PureCoverage 和 Rational Robot 的使用情况。在项目的这个阶段,我们主要关注在功能测试(包括 GUI 测试)上,虽然我们也从事了一些早期的负载测试。
注意,这里使用的 Rational 统一过程(RUP)术语反映了测试的两个不同的维度:“单元测试”是在将要被测试的软件的开发阶段进行的 — 在这个时候测试是针对最小的可测试的软件单元的 — 而“功能测试”和“负载测试”是针对特定测试目标的,不管是在被测试软件的哪个开发阶段。本文中所讨论的关于单元测试的大多数内容也可以应用在我们后面的 开发阶段的测试工作中(例如,在集成测试期间合并不同的组件或者子系统)。
第 8 部分快照 |
在第 8 部分演示的工具和技术:
被创建或者更新的产物:
|
单元测试
在 开发的进展过程中,我们发现我们的单元测试工作超过了我们的开发工作,因为我们正在构建的应用具有非常复杂的用户交互。单元测试总是要求大量的工作,并且 我们也许没有足够的预算和时间来执行大量的单元测试工作。我们发现我们的 GUI 测试,包括单调的手工测试的过程,尤其减慢了我们的速度。
虽然 ASDI 项目的第 1 阶段只是一个概念上的验证,但是我们也具有艰苦的时间忍耐在系统中显而易见的 bug 。在拥有坚固、可靠的软件和频繁的集成、快速的演示之间找到一个平衡是非常不容易的。我们定义了第 1 阶段项目的范围,这样我们就必须进行不止一次的技术上的演示;客户期望演示是一个可以使用的系统的 beta 版本。
这里,我们将看一下我们的单元测试工作的范围,我们可以选择(或者不)使用自动化的能力,并且我们使用 Rational PureCoverage 来确定我们测试的彻底性。
测试的范围
单元测试的范围 — 什么、多少次和什么时候测试 — 是几个可变量的基础,包括:
在 代码测试的次数方面,在之前的项目中我们没有打算在我们的软件中进行 100% 代码覆盖率的测试。完全的覆盖是非常昂贵的并且很难达到,因为我们必须要手工的检查我们的代码以确定哪一行代码没有被测试覆盖到。对单元测试的小的变化将 要求我们重新检查代码以确保完全的覆盖率被维护。然而,我们得感谢 Rational PureCoverage ,在 ASDI 项目中我们能够容易得实现了接近 100% 的代码覆盖率(由于项目预算和范围的原因,少量的未测试的残留是被允许的)。PureCoverage 很大程度的简化了检查代码覆盖率的任务,这使识别哪一部分的代码已经或者还没有被测试变得非常简单。
就像我们在这个系列的 第 6 部分提到的那样,我们的单元测试工作几乎与核心的软件开发本身开始的一样早。我们多数的开发人员在他们拥有一个能够被测试的软件单元不久就开始编写单元测试。他们喜欢当代码在他们的头脑中产生时测试软件的内部构件。
单 元测试的执行总是先于系统的构建;将明显能够通过单元测试来消除的简单缺陷引入到一个构建版本中是让人不可接受的。单元测试总是在代码被分发检查之前被执 行。此外,开发人员以规范的基础运行他们的单元测试以确保他们的定期变化不会破坏软件。我们的方法不像一些软件方法那样激进 — 比如 极限编程(XP),在 XP 中单元测试的开发通常是先于代码的开发的 — 但是我们将单元测试当作是一个重要的软件开发的早期步骤。
自动化的能力
这 里当然也有一些如何进行测试的问题,特别是什么样的测试应该被自动化的范围。编写“后台”(非 GUI )代码的开发人员是幸运的,他们能够编写自动化的测试,包括 Java 驱动程序、代码存根和脚本。然而,就像我们早些时候提到的,GUI 开发人员的测试是更加困难的。
对于我们的非 GUI 测试,我们观察了与每一个类相关联的单元测试的习惯;我们编写驱动代码访问类,并报告成功或者是失败。我们尝试使用能够为我们自动生成、管理和运行测试的 测试框架,比如被 XP 所推荐的那些工具,但是他们将产生混杂的结果。虽然理论是很好的,但是这些框架(包括,比如 JUnit)对于我们的项目 目的来说来是不够成熟的。不过,我们的开发人员非常自信如果他们有时间熟悉和对这些工具进行改进,这些测试框架对我们的单元测试是非常有价值的。我们也许 在将来的项目中更多的使用这些测试框架。在我们的 ASDI 项目中,采用 XP 的方法也许是太冒险了;相反,我们更加愿意接受 XP 在控制和风险降低方法方面的概念和思想。你能够在 the XProgramming.com 网站上找到大量有关 XP 思想的内容。
我 们没有使用 Rational 的测试工具来测试非 GUI 的代码,因为我们觉得他们不能达到一个足够底层的级别。对于自动化测试我们的 GUI 驱动的代码,Rational 的测试工具真的表现的非常出色。用户界面测试是非常手工和交互的,并且要求大量的内容确认; Rational 的测试工具以一种一致的并快速的方式使我们反复的进行这些测试变得更加的简单容易。
代码覆盖率
通 过使用 Rational PureCoverage ,在我们的单元测试执行期间,我们能够大幅的降低我们花在确定代码覆盖率上的时间 — 也就是说,哪些方法或者代码行被执行或者被遗漏 。这个工具能够使我们观测我们提供的代码覆盖测试,然后决定是改进测试还是通过手工检查的方法来测试代码。
PureCoverage 除了可以支持 C 或者 C++ 的应用程序以外,还可以支持 Java 程序,并且可以通过与 Quantify 相同的方式来配置和运行(在这个系列的 第 6 部分被讨论过)。这个工具能够使我们浏览我们的单元测试;以两种方法进行代码覆盖测试:使用 Coverage Browser 或者指定文件的 Coverage Fileview 方式。
使用 Coverage Browser 的方式(图 1 ),我们能够看到在单元测试中被包括的每一个文件(和目录)的代码覆盖测试的统计学的总结。这些统计表包括了所有方法的调用次数,方法被访问或者遗漏的次数,还包括被访问或者遗漏的代码行的数量。
图 1:Coverage Browser |
( 点击放大) |
我们能够双击一个在总结中的方法来进入 Coverage Fileview ,仅仅显示在那个方法中哪些代码行被访问或者被遗漏。就像被显示在图 2 中的例子,被遗漏的代码行被用红色突出出来(被访问的代码行用蓝色标识)。
图 2:Coverage Fileview |
( 点击放大) |
|
功能测试
功 能测试根据被定义在用例中的需求来验证软件是否正确的工作。为了确保我们测试了所有的需求,我们在设计和组织我们的功能测试时使用 Rational Robot 和 Rational TestManager 。(一个关于使用 Robot 的功能测试策略的讨论能够在 Robot 的用户指南中被找到。)Robot 能够使测试脚本更加容易的被录制,然后为自动化测试回放。使用 Robot 能够创建两种类型的测试脚本:
我们尽可能早的开始创建我们的功能测试集合,因为这些测试对工程团队来 说是非常有价值的工具。我们在代码被分发检查之前适当的拥有测试脚本的目标有时是很难实现的,可能是因为代码的一些部分和一些组件要比其他的代码和组件花 费更多的时间来完成,或者是因为集成和测试(I&T)团队太慢以至不能及时的完成测试脚本。在一种情况下,当用户界面仍然在变化时,测试脚本已经 被完成了;虽然一些返工是必要的,但是变化的出现是相当容易集成的。
一旦我们拥有了一个强有力的功能测试集合,重新测试系 统将是非常容易的。这样当你需要在后来的迭代中重新测试系统小的改变时得到很大的回报,并且可以确保变化不会影响其他的代码部分。我们映射我们的功能测试 脚本到用例上,以便我们可以立即知道当被关联到被给定的用例的需求被修改时哪一个测试应该被运行。
|
GUI 测试
当非 GUI 代码的开发人员非常高效的进行他们的单元测试工作时,JSP/servlet 的开发人员将很难的保证时间的进度。刺痛他们的是测试 GUI 域的过程,这个过程包括反复的执行下面的步骤:
一些 GUI 测试尤其令人讨厌,包括相同的入口,在几个域中填写冗长的值。可以使用剪切和粘贴,但是对于团队来说一遍一遍的重复这些测试仍然是非常琐碎的工作。有些页面有 50 个不同的测试必须被执行,每个测试都包括很多的步骤。
虽 然我们最初不倾向使用 Rational 的测试工具,但是我们觉得我们在 GUI 上的困难是我们深入研究 Rational 测试工具的很好的理由。我们决定使用 Rational Robot 来自动化我们 GUI 的大部分测试。我们通过以下的方式调整了这些测试:
这个方法工作的非常好。它不仅仅在集成与测试团队没有太多的事情做的开发过程的早期阶段给他们在更多的工作,而且也给他们一个机会通过揭示单元测试说明来了解整个软件系统。此外,我们为 GUI 测试使用 Robot 的经验也为阿我们对其他的功能测试脚本进行了准备。
当 Rational Robot 启动时,它需要一个已存在项目(使用 Rational Administrator 创建的)的选择,测试脚本将与这个项目进行关联。在我们的例子中,项目的定位必须是在网络上可访问的,以便我们能够在整个团队中共享项目的数据库。我们在 Administrator 中创建了 ASDI 项目,如图 3 所示,并且当 Robot 提示我们选择一个项目时,我们选择了这个项目。
图 3:使用 Rational Administrator 创建一个项目 |
一个验证测试的例子
作为一个 GUI 测试的非常简单的例子,我们需要确证对于我们的 partSearch.jsp
页面来说客户端的验证是行为正确的,这个页面执行了 JavaScript 的代码来验证他们域。每个 ASDI 的条件,部分数字被输入到整个页面中,比如,必须是比 0 要大的整型数字;如果一个用户输入一个无效的数字,JavaScript 代码就会报告一个错误,并且不会送坏的数据到服务器。我们在 FormChek.js
文件中编写了我们自己的验证代码。适当的使用这个代码,一个负数的输入会弹出如图 4 所示的窗口。
图 4:适当的 partSearch.jsp 页面验证 |
创建测试脚本
我们在 Robot 中创建了一个测试脚本来测试数字域的验证是否示适当的。首先 Robot 提示我们为脚本提供一个名字(图 5)。
图 5:录制一个新的 GUI 脚本 |
在点击 OK 这后,我们被提供了一个录制控制器(图 6),然后当 Robot 录制我们的动作时,我们使用我们的基于窗口的应用。在这个例子中,我们启动了 Internet Explorer 5 ,在 partSearch.jsp
页面进行浏览,输入一个坏的数字 (-123456),点击 页面上的 Submit 按钮。
图 6:Robot 录制控制器 |
Robot 将我们的动作记录在一个 GUI 脚本中(图 7 )。这是一个非常简单的例子;我们实际的测试会包括更加复杂的测试脚本。我们不用创建成百上千个独立的脚本,而是尽量为每一个屏幕界面设计一个大的脚本。 在 Robot 的文章中有进行测试设计的非常详细的信息,我们能够从 Robot 文档中所推荐的内容中得到大量的借鉴。
图 7:简单的 Robot GUI 脚本 |
( 点击放大) |
通过使用易读的并且可以容易的进行编辑的脚本,我们就不必为只是有很小差异的测试重复的录制测试脚本了。有时我们可以不用重新运行测试就直接编辑测试脚本,或者我们只是重新录制一个测试的一小部分,然后将它粘贴到已存在的脚本中。
运行测试
为 了再一次运行测试,我们简单的在 Robot 的录制控制器上(或者选择 File 菜单上的 Playback )点击 “play” 按钮。脚本就像我们最初执行测试一样回放我们的测试操作,并且当脚本运行完成时,Rational TestManager 被启动来总结我们的测试结果。对于上面那个简单的例子,TestManager 在图 8 中显示的结果表明,测试脚本运行的结果是测试被通过。
图 8:TestManager 报告 Robot 的测试通过 |
( 点击放大) |
假 设我们想测试代码的错误处理能力,比如坏的数字不再被捕获 — 也就是说,没有出现一个指明错误的窗口,我们的应用就会将整个数据传送到 servlet 来执行查询。当我们通过回放脚本重新运行这个 GUI 测试时,Robot 将会捕获这个问题,并且将结果写到报告中(图 9 ),包括显示出这个测试是失败的。
图 9:TestManager 报告 Robot 测试的失败 |
( 点击放大) |
|
总结
当 我们开始 ASDI 项目时,我们期望使用 Rational 的分析和设计工具而不是 Rational 的测试工具。到项目第一阶段的这个时期,我们非常惊讶并且也很高兴的看到我们通过使用 Rational 的测试工具自动化并且改进了我们的测试过程。这些工具都有一个坚实的学习曲线,但是一旦我们掌握我们每个工具的使用方法,我们的集成与测试团队的生产力将 大大的提高。在一些情况下,个体开发人员使用象 Rational Purify 、Quantify 和 PureCoverage 这样的工具为他们的单元测试工作提供补充。其他的工具,比如 Rational Robot ,则需要集成与测试团队具有更高的技能并投入更大的注意力。
计划未来
团 队仍然必须在系统级别上承担集成和测试的任务。多数的单元测试工作被分包给了开发人员,但是我们还需要更加全面和正式的测试子系统和整个系统。这就意味着 我们需要正式的构建版本、最终的构建文档和在集成与测试上的重要关注。特定目的的负载测试只是我们测试工作中的一小部分,但是它在整个系统的测试中却是非 常重要的。幸运的是,我们的测试集合已经完成了 95% ,并且我们还稍稍的比计划的时间提前了一点,因此我们能够有一些额外的精力来关注系统的测试以确保高质量的第一阶段的系统交付。
主要风险
我们的风险列表在此刻已经非常的短了。客户在演进系统上的合作并不太令人惊讶,我们的技术风险已经非常少了,非常感谢工程团队带来的良好的进展。
现在我们必须对我们的代码开发进行最后的 加工、执行系统的测试、识别系统中的任何缺陷并按计划交付阶段一的系统给客户。当团队接近主要阶段的尾声时,及时的将所有的细节包装起来通常时很难的。如 果我们想避免超出计划,我们就需要系统有少量的缺陷,并且能够快速的矫正在测试中发现的任何问题。
本文中所虚构我们是一家软件公司 Lookoff Technologies Incorporated,我们的客户 Audiophile Speaker Design, Inc. (ASDI),它雇用我们实现他们最初的 IT 需求。对于更详细的信息,参见 第 1 部分。
到 目前为止,我们已经接近了 ASDI 项目第一阶段的尾声了。ASDI 已经获得了我们提供的一系列的系统演示,并且他们对产品感到十分的满意。(实际上,我们有一些担心,因为项目的第一阶段已经是如此可用的系统,我们担心 ASDI 会推迟或者取消接下来的第二阶段的项目。) 客户感到满意的最终因素是我们进行了充分符合需求的系统测试和验收测试。
第 9 部分快照 |
在第 9 部分演示的工具和技术:
被创建或者更新的产物:
|
包装开发
在 这个时候,我们的编码工作已经显著的减少了。我们在修改和精化产品的阶段,团队的工作主要是针对一些小的更改。当集成与测试(I&T)团队发现软 件的缺陷时,他们在基于缺陷缺陷跟踪的数据库模式之上的 Rational ClearQuest 数据库中填写并对缺陷进行优先级划分。这些缺陷报告被工程团队复查。团队领导和项目工程师通常决定缺陷的优先级并维护一个描述对于被给定的构建版本哪一个 人将对其进行修复的计划。
构建的频率
执 行完整的系统构建版本的频率 — 在一个清洁的环境中从头开始构建系统 — 使我们大大的接近了第一阶段项目的尾声。最初计划每个月进行一次构建,但这些构建有时被每周进行一次。这对于大的项目或者缺少高技能的开发人员的团队来 说,建立一个清洁的构建环境的日常开支、从源代码库中得到软件,构建系统和测试系统的行为是不太可行。然而,感谢我们所使用工具的紧密集成、我们良好的文 档建立过程和我们使用了 Rational 的测试工具快速的完成了我们的测试执行,我们才能够将系统的构建增加到每周一次的频率。
自动化的脚本尤其使进行这么频繁的构建变得切实可行。至少我们运行了脚本来测试被我们已经解决了的缺陷所 影响的系统部分。我们通常可以更进一步,为系统的大多数或者全部运行脚本。我们非常幸运我们能够通过自动化的测试脚本来测试系统的模块;Rational 的测试工具能够非常好的符合我们使用的技术,然而,有一些其他技术的结合可能会给测试脚本的使用带来挑战或者根本无法使用测试脚本。
集成测试(I&T) 团队的介入
目前为止,我们到达了进行系统构建的阶段,I&T 团队完全的投入到并领导这个过程。在项目的开发周期中(在 第 6 部分) 我们就将 I&T 团队引入到了项目团队中,并且进行全职的工作,因此现在他们已经做好准备了。在我们之前的项目中,我们比较迟的将I&T 团队引入到了项目中,几乎接近开发周期的尾声,但这会产生一定的问题。我们最终意识到 I&T 团队需要一定的准备时间,就像其他项目团队的技术成员一样。虽然对于我们较早的构建来说,在组装系统方面 I&T 团队要比系统团队慢,但是这是我们对他们预期的学习过程的一部分,并使他们自由的进行构建,而工程团队则可以继续他们的开发工作。
I&T 团队根据他们对工程团队进展的理解定义预计将要构建的目标。他们与项目工程师一起讨论构建以确保构建能够符合他们的预期。例如,如果因为一些组件或者子系 统没有准备好,工程团队没有为功能测试准好准备,对于组装,检查每一个被编译的的代码、被匹配的接口和第三方的工具(JDK、库和购买的工具)在线程和子 系统团队成员中是一致的来说,构建只是简单的练习活动。对于系统十分成熟的构建来说,团队将根据系统特定的方面进行负载测试或者功能测试。
接 近开发周期的尾声,I&T 的领导是一个项目团队中非常重要的角色 - 甚至比团队领导或者项目经理还重要。I&T 领导为测试执行指定计划,了解系统区域的弱点和长处,并不断的监控缺陷分析数据。同时,他也管理需求、组件、线程、测试脚本和缺陷的完全的跟踪映射,这可 以帮助他对他的团队的动作进行计划和优先级划分。
修复缺陷
修复缺陷绝不是微不足道的任务。每一个缺陷都会引发以下的问题:
无论 I&T 团队什么时候在系统中发现了一个缺陷,他们都会在 ClearQuest 数据库中提交它,在数据库中他们能够获得上面所提到的很多细节。他们在 ClearQuest 中连接数据库,并在提交缺陷表单中填写缺陷,如图 1 所示。
图1:提交一个缺陷 |
( 点击放大) |
缺 陷数据库能够被所有的工程团队的成员所共享,并能够通过网络在任何时间内被访问。例如,在图 1 中被提交的缺陷的所有者,他的工作是在产品的搜索能力上,他与搜索团队负责用户信息的成员分在同一组中。为了保持对任何被分配的打开状态的测试问题的跟 踪,I&T 团队使用了一个 ClearQuest 的查询。图 2 显示了搜索团队的查询结果,图 1 中被提交的缺陷被显示在了结果集中。查询(结果总是反映被 I&T 团队更新的数据库的最新内容)结果被过滤了,仅仅包括搜索团队的缺陷,并通过优先级和提交时间进行排序。
图 2:被过滤的缺陷查询结果 |
( 点击放大) |
其他的团队以相似的方式在他们各自的区域查询 ClearQuest,并收到适当被过滤的结果。仅仅是 I&T 团队、项目过程师和团队领导能够看到项目进展中的完整的缺陷列表。
在图 2 中的 Actions 按钮提供了修改、分配、关闭、复制、推迟或者删除当前被选定查询结果的选项。根据项目团队成员的职位,不同人能够进行不同的操作:
|
系统测试
系 统测试通过使用被录制的测试脚本对整个系统进行测试。这种测试不仅对客户的验收测试十分重要,同时它也深层次的检验了系统并提供了在测试脚本中的缺陷的洞 察力。无论我们多么严密的对变更进行跟踪,也经常会有一些小的变更超出我们预计的范围从而带来一些冲突,以未预料的方式影响其他的代码片断。
我们通常在被I&T 团队建立的清洁环境中进行系统的构建,因此我们彻底的测试了构建的文档。如果在构建文档中遇到了任何的错误,一个问题(在“文档”分类中)连同任何被识别的测试缺陷被提交到缺陷数据库中。
从单元测试阶段(在 第 8 部分被讨论)到现在,我们测试了系统的功能需求和系统的非功能需求,现在我们在系统的非功能需求上投入了比在早期测试阶段更多的精力。我们测试的主要非功能领域是可用性和性能(负载测试),我们将在下面进行讨论。
可用性建议
我 们用了我们仅有的可用性专家。虽然她被包含在早期的用户界面的计划和模拟工作中,帮助人机界面的工作,但她没有加入到我们和 I&T 团队的其他成员中。她现在的工作是作为一名用户与系统一起工作,找出可用性的问题,并将问题提交到缺陷数据库中(通常在“不友好的行为”类别中)。
一些可用性的问题必须被推迟解决,因为他们超出了第一阶段的范围或者处理他们是非常耗成本的。然而,许多 容易修复的和会给客户带来混乱的小的可用性问题被发现了。这是我们最成本高效的测试活动中的一些,因为通常从客户的角度来看,只不过是一些小的代码改变就 能大大的改进产品。可用性的建议包括新的错误信息、布局的改进、调整按钮的标题和菜单、文档的整理和屏幕工作流程的修改。
负载测试
我 们的系统没有苛刻的性能需求,但是我们想让系统在最大负载下是可用的。我们在早期做了一些负载测试,但是这个测试类型会在接近开发周期的尾声时达到最高 点。我们想确保系统能够超越 ASDI 的期望。我们希望我们能够以项目的第二阶段的形式得到接下来的工作,我们不希望造成性能的问题。我们对系统的两个部分进行了负载测试:Web 应用接口和通过基于 SSL/XML 的 command gateway (在 第 5 部分被介绍)的 B2B接口。
Web 负载测试
对 于 Web 的负载测试,我们使用了 Rational SiteLoad 。这个工具能使我们录制由一系列我们执行的 Web 事务组成的脚本,然后将这些步骤复制作为多个虚拟的用户。我们和 ASDI 一起复查了被预期的负载模式以确定有多少用户同时访问 Web 应用,我们决定测试 20 个用户的负载。
通过使用 SiteLoad ,我们能够容易的模拟 20 个系统的并发用户,并精确的统计相关的系统性能。当我们启动 SiteLoad 时,它启动了我们的浏览器,并提示我们创建一个测试或者运行一个已存在的测试(见图 3)。
图3:SiteLoad 的主屏幕 |
( 点击放大) |
当 我们选择录制一个新脚本时,SiteLoad 弹出一个基于 Java 的浏览器,并记录我们在它之上所做的所有动作。例如,当我们在这个浏览器中浏览我们的 partSearch.jsp 页面时,SiteLoad 从服务器端加载这个页面(如图 4 所示),并记录我们的动作,包括我们输入的任何数据值和按钮的点击动作。我们设计了这个特定的测试以执行基于多个参数的很多次数据库查询操作。这显然是一 个很简单的测试,因为数据库能够缓存查询;其他的一些测试会更加的严格和具有挑战性。
图 4:SiteLoad 记录浏览器的动作 |
( 点击放大) |
对 于我们录制的每一个脚本,我们也能够为测试设置一些通常的性能需求。我们决定当测试 partSearch.jsp 页面的脚本被回放时,我们希望至少有 90% 的页面在四秒或者更少的时间内被加载(见图 5)。虽然这并不符合高性能的要求,但这对于我们系统的可用性和整体质量来说已经足够了。
图 5:设置 SiteLoad 的性能需求 |
( 点击放大) |
图 6 显示了我们如何配置 SiteLoad 来模拟 20 个并发用户反复的执行我们记录的 partSearch.jsp 页面的动作。SiteLoad 能够进行更加复杂的性能建模以帮助我们找出我们的系统的“性能围墙”,但是我们选择在我们的首次尝试中直接进行 20 个并发用户的最大值测试。如果我们遇到问题,我们将减少最初的用户数量至 5 个,并每一分钟或者两分钟增加一个用户。我们也能够为终止测试设定一个标准,但我们没有这样做,因为我们正可视化的监视测试的过程以了解我们的系统有什么 样的行为。
图 6:设置 SiteLoad 用户特性 |
( 点击放大) |
当 测试正在运行时,SiteLoad 显示并不断的更新象图 7 中显示的统计数据。在这个例子中,一个柱状图表明我们的测试脚本的性能结果;几乎所有的页面都在 8 秒钟内被加载执行(换句话说,只有 0-20% 在我们的 4 秒钟内的性能限制中)。使用在屏幕顶部附近的绿色菜单栏中提供的选项,我们能够选择查看更加详细的测试报告,比如,页面访问、CPU 负载和平均负载时间。
图 7:SiteLoad 的测试结果 |
( 点击放大) |
B2B 负载测试
对于 SSL/XML 的B2B 负载测试,我们使用了 Rational Robot 来录制虚拟用户(VU)脚本。我们输入我们希望 Robot 执行的命令来监视并以一个脚本的生成最为结束,这个脚本与被 Robot 生成的 GUI 脚本(在 第 8 部分被 讨论)十分不同。不像 GUI 脚本,VU 脚本记录和接收与传输信息相关的低级信息。通过从多台机器运行 VU 脚本,我们能够模拟并发操作系统的 B2B 客户端会话。 ASDI 怀疑可能会有多余两个的并发会话会发生,因此我们能够完成一些超越这个需求的步骤,以确保良好的系统性能。
测试完成情况检查
在 我们计划中的最后两周里,工程团队进行了系统测试,并通过了所有的需求,并且 I&T 团队关闭了所有的问题,除了一些我们已经与客户讨论过得认为可以被推迟的不重要的问题。对于我们来说下一个里程碑是测试完成情况检查(TRR),我们执行 了两个 TRR :一个是内部的,一个是与客户一起的。内部的 TRR 以下列检查来实现:
除了检查上面的项目,我们还复查并预排了一个系统演示,整个演示作为产品的最终展示服务于与客户进行外部的 TRR 。我们为我们构建的产品自豪,并且我们希望确保显示系统所有关键的特性,因为我们知道 ASDI 的高层管理人员将出席这个外部的 TRR 。
在外部 TRR 期间,我们按照与内部 TRR 相同的日程安排进行。我们与 ASDI 一起审阅了检查列表以显示每一件事情都被完成了,并且结束了这个演示。并不令人惊讶,在最终的演示中出现了更多的一些想法,处于对将来的考虑我们将他们注释下来。
|
验收测试
为 了 ASDI 同意项目的第一阶段已经被成功的完成,系统必须通过一些最终的验收测试。我们有理由相信系统能够通过这些测试,因为我们已经为执行系统的端到端的测试编写 了一套脚本来检查是否所有的需求都被覆盖到了。这些脚本使用 Rational Robot 创建的,并且被 ASDI 彻底的检查过了。我们能够想到的唯一能够防碍我们验收测试成功的事情就是被工程团队最后时刻的变更可能会影响其他的代码片断。但是在我们开始验收测试之前 我们收到了一个令人惊讶的消息, ASDI 在外部 TRR 中告诉我们他们想让我们手工的进行验收测。我们认为我们在验收计划中指出使用测试脚本的意图是非常清楚的,但是现在我们意识到我们在计划中的措词是含糊不 清的。
当我们在外部 TRR 中陈述 CAT (客户验收测试)将是相当简短的,并且我们能够非常快速的执行和检查脚本的执行结果时, ASDI 表示他们想看到所有一步一步的测试执行以便他们知道发生了什么。虽然我们不希望这样,但看起来对我们还是公平并且可行的。我们为我们的测试脚本文档化了所 有的测试过程和计划,甚至当脚本升级时,我们也维护了我们的测试计划,因此,对于我们来说手工执行测试不是什么问题。
我们没有准备的是手工进行验收测试要花费多长时间。现在我们根据我们文档化的测试过程进行手工的测试,我们意识到自动化的测试为我们节省了多少时间。
我 们发现在我们的测试过程中丢失了一些必须提供的细节。我们不总是能够获得足够的信息来创建一个明确的并且可反复使用的测试。我们也意识到有时我们更新了测 试脚本但没有修改测试计划。在对测试计划进行了小的变更后,我们为一个快速检查向客户交付了测试计划;我们同意变更是非常小的,并不需要其他的 TRR 。
验收测试发生在我们的开发环境中,开始于根据构建文档进行清洁的构建,并引发测试过程的执行。这些测试大概会花费一共两 到一天半的时间来执行。我们团队中的三个成员执行这些任务(I&T 领导、项目工程师和团队领导),还有三个来自 ASDI 的人员(QA、项目经理和技术领导)。
我们引以自豪的是在验收测试期间没有软件缺陷出现。仅仅出现了一些不重要的问题,通常是在“文档”和“不友好行为”类别中的。所有的需求都被满足了,客户在测试结束时非常的高兴。
|
总结
这也许是我们的团队在开发和测试的结尾不必花费大量时间工作的第一个项目。其中对此作出贡献的因素是我们有更好的工具、对技术的熟悉和一个在项目早期就一起工作的工程团队。
尤 其是测试过程有一个很大的成功。Rational 工具给人印象最深刻的也许是测试的功能。这是我们第一次引入自动化测试,并且我们对它工作的如此好感到惊讶。自动化测试的最大痛处是相应需求变化的脚本修 改;然而,这个责任被传递给了集成与测试团队,因此不会影响我们的工程团队的工作。
计划未来
现在我们在客户的环境中安装了软件,并给他们一些时间评估系统。虽然没有一个正式的保证阶段,但是 ASDI 一直在向 ClearQuest 数据库中提交问题。最后,一个是否进行项目第二阶段的协议必须被达成。
主要风险
在此时我们觉得已经没有任何主要的风险了。我们很自信所有大的问题都已经被解决了,并且我们充分的准备了这个项目剩余部分可能会出现的任何问题。
本文中所虚构我们是一家软件公司 Lookoff Technologies Incorporated,我们的客户 Audiophile Speaker Design, Inc. (ASDI),它雇用我们实现他们最初的 IT 需求。对于更详细的信息,参见 第 1 部分。
这 个系列的文章的最后一部分讨论了一些为结束 ASDI 项目需要做的剩余的小事情。我们已经通过了验收测试,系统现在已经准备好移交到 ASDI(交付和维护)。这篇文章的结束部分我们来对我们在项目中所观察到的进行一个讨论,并希望能够从我们在这个项目的工作中学习到一些经验和教训。
第 10 部分快照 |
在第 10 部分演示的工具和技术:
|
项目交付
现 在是时候将项目的第一阶段交付给客户了(并决定是否会有第二阶段)。我们将系统交付给了 ASDI 并帮助他们在他们的站点上安装了系统。他们通过真实世界的使用立即开始测试系统,开始输入管理和配置数据并将他们预期的“正在使用的”部分列表移植到了系 统中。他们也尽力的输入订单并产生部分的报告。系统正常的运行了,客户感到非常高兴,而我们剩下的所有工作就是对系统进行维护。
维护
因 为我们的和约是包括系统的所有部分的工作,并没有一个正式的担保期限。而 ASDI 仅仅向我们提出了一些新想法或者不适合的需求等方面的问题,我们将这些问题提交到了 Rational ClearQuest 缺陷数据库中。因为我们没有为 Rational ClearQuest 安装 Web 界面,因此客户的输入是通过硬拷贝的形式与我们进行沟通的。虽然这个过程对于整个开发的分析阶段作出的系统变更请求工作的很好,但它在维护阶段被证明是繁 重的工作;我们的第一选择是让客户直接访问我们的数据库。其次的问题通过电话会议被讨论和确认,而其他的问题被推迟直到我们对项目维护的范围、影响和实施 计划达成一致意见。
ASDI 没有基础设施或者资源来维护软件系统本身,因此我们在我们的公司保留了开发和测试环境。这也是有意义的,因为如果 ASDI 决定为这个项目继续第二阶段的开发,那么分解我们的环境将是浪费时间和资源的。
我 们在我们的站点上修改了软件并将构建好的系统适当的交付给客户。这是稍微有点笨拙的安排,因为我们仍然有被分配的资源以全职的形式投入到项目中,但是在这 个项目的维护中,并没有足够的工作可以保证工程和集成与测试团队进行全职的工作。然而,因为 ASDI 并没有合适的人员、软件或者硬件来执行他们自己的维护,这种安排还必须持续一段时间。
在第一阶段的维护期间被提交到 ClearQuest 数据库的问题有一个粗略的分配:
问 题的多数都是在“好看的外观”类别中,比如一个能够使应用更加便于使用的变更,但是他们都不是关键的。例如,在系统的用户界面上有一个区域,在那说明 ASDI 业务领域的术语是不正确的或者字母拼写错误。理想的情况是这些问题在早期的复审中被挑出来,但是在第一次复审中挑出所有的错误总是困难的。
大量对于新特性的请求简单的反映了这是一个未完成的产品 — 向没有从一开始被包括在项目中的用户展示系统的一个自然的结果。因为项目的第一阶段成生的只是一个概念验证的系统,我们的目的是验证系统的功能性,我们的大量工作是围绕着这个目的完成的。
被残留在系统中的不重要的 bug 不是与需求有很大的矛盾,他们是在比较底层上的不正确的实现。这些问题包括被系统产生的一些在金融数据报告上的不完善的数值的舍入。
我们没有必要太担心关于需求上的错误。我们的分析工作是非常彻底的,但是记住两件事是重要的:
第二阶段?
有一些关于是否、何时并且 ASDI 如何继续进行这个项目的第二阶段的讨论。下面有一些讨论中的观点:
当 最初计划第一阶段和第二阶段时,我们就知道我们最终将面临这个岔路口。上面问题中的一些成为了在第一阶段的末期创建的一个精练的原型的结果,当你在一个概 念验证的系统中进行预期时,系统中还存在一些不具备产品化质量的部分。就像上面所提到的,向 ASDI 提供的用于企业批量操作的 B2B 接口还没有完全的被实现。很多对于新特性的需求被记录在了 ClearQuest数据库中,并且被设置为等待状态的动作。用户文档是不够充分的,存在一些对于操作者来说不够清楚的任务操作指示说明。
我 们指出了一些定性的证据证明如果我们继续项目的第二个阶段,产出的系统将要比第一阶段产出的系统更加高效。很多特性将被加到第二阶段中 — 比如,通过与数据库集成的数据输入屏幕支持数据输入的能力,而不是通过命令行的接口 — 这将无疑意味着更高效率的增加。与此同时, ASDI 的项目经理觉得当前的系统已经有了巨大的改进,当我们将它向公司展示时,我们完全可以将它从一个“beta”版本重新命名为“完全版本 1”。
最 后,ASDI 同意我们继续扮演系统维护的角色,虽然 ASDI 保证他们至少会从我们这里雇佣两个全职的支持角色的人员(一个开发人员,一个测试人员),而其他被需要的支持可以通过电话的方式实现。在 ASDI 有了他们自己的财政状况的更多数据和更加清晰的认识后,他们决定推迟第二阶段的工作直到一个比较靠后的时间。
|
观察
我们从这个项目中学到了相当多的东西,因为这个项目是我们在几个新技术上的第一次探索。作为我们首次广泛的实践 RUP ,它为我们提供了一系列的对于过程的项目观测和想法。
客户关系
在 这个项目期间,我们与 ASDI 有着非常良好的关系。经过这么多年,我们发现能够成功的建立与客户的良好关系的是良好的沟通、对项目进展的可见性和具有实际意义的提议。与 ASDI 唯一棘手的问题是他们最初预期项目应该严格的按照瀑布型的开发方法进行。这与我们运作项目的方式截然不同,并且与 RUP 方法也有着巨大的差异。最后,我们能够执行我们觉得是必要的迭代,而尽量的向 ASDI 展示类似于瀑布型方法的结构以满足他们的需要。
客户对于项目范围的视角改变了大约三分之一的贯穿项目的路线。虽然变化不是强烈的(见图 1),但是也造成了从最初的 SOW 的一些转变。我们能够使用 Rational RequisitePro 来跟踪需求,但是他们对整个系统带来了影响。
图 1:在项目范围上的变化 |
在 范围上的改变添加了一些功能方面的区域,但是也删除了其他一些功能的区域。B2B 接口的重要性被降低时,而操作员屏幕的重要性被增加了,我们觉得这对 ASDI 是安全并且明智的决定。虽然我们已经被给了命令(和预算)来实现并测试一个安全的 B2B 接口,与此同时 ASDI 意识到他们所花费金钱的最大价值是在数据集成、基于 Web 的数据入口、报告和订单管理上。这不仅仅强调帮助 ASDI 向他们的潜在用户销售使用系统的思想,而且也提供了立即可用的结果(不要求他们等待业务伙伴采用 B2B 的接口)。
在我们的团队中 ASDI 的信心在项目的周期中不断的变化着。对此我们的非常主观的估计被显示在图 2 中,在图中在信心曲线上的主要的点与下面图中列出的被标号的条目是对应的。
图 2:客户的信心 |
过程
我们之前的项目借鉴了一些 RUP 中的增量的和迭代的内容,但是这个项目是我们第一次真正大规模的实施 RUP 。我们没有完全的照搬 RUP 的内容,因为我们想避免对于项目团队通过太多新的步骤所带来的“过程工作”的风险。
Rational 的工具能够很好的帮助我们理解 RUP ,并且在线的 RUP 文档也是非常有价值的。 RUP 的文档在实施 RUP 的道路的每一个步骤上为我们提供了卓越的策略建议,并且 RUP 的工具指导也帮助我们理解 Rational 的每一个工具应该如何被应用。
RUP 的一个长处是它关注在降低风险上。迭代的方法,早期的原型、演示和大量的客户参与的合并,所有的这些可以帮助降低项目的风险。我们觉得我们项目的风险与图 3 中的路径比较相符(相应的标号条目在下面)。注意这个图不是图形,仅仅是 被识别风险的标号。显然,一个项目在开始时风险最大的,因为未知的总是在前面;在项目的一开始你几乎很少知道什么是项目的所有风险。
图 3:项目风险 |
技术与工具
所有对于架构所选择的技术都按照预期执行了。在初始和细化阶段的早期原型帮助我们确认了这些技术的选择并给了我们在培训、 API 熟悉和开发上的良好开始。
回想一下,我们很高兴我们采用了使用 IBM DB2 数据库的路线。当我们面对来自于 ASDI 的将面向对象的数据库引入到架构中的压力时,我们进行了一个可选方案的仔细评估和对比,并能够演示了面向对象的数据库实际上是不够安全的,或者在产品上还有更好的选择。
Ratioanl 的工具在我们以老的方式做事情之上提供了一系列的好处。我们也许能够在相同的预算下以老的做事情的方法交付符合需求的产品。我们在第一阶段系统的改进从三个方面比较了新的方法是如何压倒老方法的:可用性、质量和性能。
团队生产力
团队之前一直在一起工作,因此在团队成员之间已经具有了良好的士气、沟通和协作。这允许他们将更多的精力放在项目和学习新的工具上。
我 们发现在项目的过程上跟踪团队的生产力是有趣的。虽然我们不是度量分析的狂热者,比如,代码行陈述(SLOCs),但是在这个例子中度量分析的确是很有趣 的。在我们之前的项目中,在相同数量的金钱下,我们能够编写更多的代码;然而,在那些项目中对于同样的金钱我们从来没有提供过如此多的功能。因此,即使我 们做了更加好的工作,但是我们的 SLOC 度量分析看起来却是更低的。我们将这归结于有一个更加清晰的设计、对购买软件的更好利用和极少的返工。工程团队也很少的感觉到时间的压力,因此他们能够花 费一些时间在代码复审之前来重构代码。
图 4:团队生产力 |
|
结束语
这 个部分对这个小型的基于 J2EE 的使用 RUP 和 其他 Ratinoal 的虚构项目进行了总结。这个系列文章显示了一个项目能够采用 Rational 的工具和过程的很多可能的路径中的一个。这个特殊的路径包括了保持事情的简单性,并在决定之前尝试了每一种技术和工具。团队并不试图在一个单独的项目中精 通 RUP 和所有的 Rational 工具,而是以一种稳定的、有纪律性的方式来采用 Rational 的过程和工具。
项目的技术、团队结构和时间计划非常有益于在不阻碍进度的情况下合并 RUP 和 其他工具。而你的项目中的情况也许有所不同,因为你使用的技术的合并可能比这篇文章描述的更加高效或者低效。对于能够给予他们的预算,有一些培训的机会能 够帮助更加容易的将 Ratioanl 的工具引入和集成到项目中。你不应该有这样的感觉 -这些工具是能够挽救你的项目的“银弹”,他们只是能够使团队更加好的工作。
记住这篇文章不是我们以前工作的任何实际项目 的说明,虽然它是基于我在实际项目中的经验的。被描述的新技术和 一些 Rational 工具对于我所从事的很多项目来说仍然是不能得到的。也要注意我不同意在 ASDI 项目中被做的许多决定,但是我将他们写入到文章中的目的是为了演示和开发不同的思想。
我百分之百同意这个文章的结论:正式 的、现代的软件工程工具和过程能够为一个软件项目带来卓越的生产力和质量。虽然要对“银弹综合症”保持警惕,我还是一直在寻找简化工作的方法。 Rational 的一系列工具恰恰能够做到这一点,并且这些工具良好的集成甚至能够提供更多的价值。