本文是演示了在分布式的、基于 J2EE 的项目中使用 Rational 工具的系列文章(如下面所列)的第 6 部分。
第 1 部分: 项目介绍;高层次计划 第 2 部分: 风险管理;需求管理 第 3 部分: 模型创建和访问控制;需求分析 第 4 部分: 用例细化;产成报告;工具和技术选择 第 5 部分: 体系架构和设计 第 6 部分: 详细设计;早期开发;双向工程;早期单元测试 第 7 部分: 继续开发;早期的构建;演示 第 8 部分: 单元测试策略;功能测试;GUI 测试脚本 第 9 部分: 系统构建和测试;缺陷跟踪;产品交付 第 10 部分: 项目完成;结论;未来的工作本文中所虚构我们是一家软件公司 Lookoff Technologies Incorporated,我们的客户 Audiophile Speaker Design, Inc. (ASDI),它雇用我们实现他们最初的 IT 需求。对于更详细的信息,参见 第 1 部分。
本文讨论了团队的进展进入了实现阶段,并且因此进入了 RUP 的构建阶段。我们挑选了在 ASDI 项目的第一阶段被使用的大部分技术。设计的情况相当的好,虽然在本系列的第五部分中被讨论的包的结构和设计在未来的一到两周内还将继续的演进。例如,包结构的部分被重新定义来反映预期的 Java 包命名习惯。
第 6 部分快照在第 6 部分演示的工具和技术:
Rational Rose 企业版 — 支持双向工程 Rational Purify — 用于检查 Java 内存的使用情况 Rational Quantify — 用于了解性能瓶颈 J2SE (Java 2 平台标准版) 1.3 — Sun 的 Java 参考实现 Jikes — IBM 的高速编译器(Sun 的 Javac 的替代物) Castor — 来自于 ExoLab Group 的数据绑定框架,用于绑定 XML 到 Java ,反之亦然。被创建或者更新的产物:
设计模型 (Rational Rose) — 随着代码的发展被更新 Java 代码 — 为 command gateway 和其他的子系统而创建铺平道路
在能够进行开发之前,我们必须在管理和团队领导的层面上完成下面的事情:
指导方针和标准
RUP 强调在一个产品被构建时同级评审的重要性;我们将在后面了解更多的细节。团队必须对同级评审的标准达成一致意见,以避免走向两个极端:松散的评审将带来非常微小的价值,或者过度严格的评审将产生大量的注释行,比如"这个被实现了,但这里我是如何实现的"的注释。
对于我们的 Java 代码,我们创建了一个基于AmbySoft Inc. Java 编码标准的编码标准文档。这些标准被证明在我们进行同级评审中是意义重大的。这些标准不仅可以帮助我们为客户产生更加一致的和高质量的交付系统,而且还允许我们的团队成员更加容易的在不同的子系统(和项目)之间进行调整。我们发现如果开发人员们对编码的形式和构建非常熟悉的话,他们将能够非常快的融入到统一的团队之中。通过避免使用模糊的命名习惯、不充分的注释和不好的编码风格,开发人员能够创建出使其他开发人员更加容易接手的代码。
培训
通常的情况下,工程师们都在尽力的学习被需要的技术以在业务上保持竞争力;然而,一些项目也会引入一些需要团队培训的新技术。我们在 ASDI 项目中并没有处于这种情况下,因为这个项目中使用的架构和技术都是我们所熟悉的。我们在这个项目中的培训是关于 Rational 工具的使用、UML 、Java 编码标准和 J2EE 设计模式的。虽然我们在这些领域有着非常好的知识背景,但是这些知识多数是在团队领导的头脑里。因此,培训由非正式的午餐时间和被团队领导发起的下午会议组成。我们发现这些维持在一个小时到半天的会议是非常成本高效的(但前提是,你必须要有具有充足知识和良好沟通能力的团队成员)。
因为我们的话题是与整个公司相关的,因此我们鼓励其他的技术人员参与到这些培训会议中。我们发现有更多的技术人员参与将会引发更加有价值的思想上的交换。最其码,我们计划能够让 ASDI 项目中所有的工程师都参加的会议(不论是参与分析、设计、实现或者测试的工程师)。
团队结构的演变
团队的结构从在系统的分析期间演变到了为满足实现期间的不同需要的结构。如表 1 所示,大量时间上的约定发生了变化,并且有五个新的职位被加了进来。
团队结构的变化和变化背后的原因被总结如下:
项目管理减少,关注点放在了客户的接口和预算的跟踪上。 财会的支持增加,因为我们的目标是在每一个任务进度上的更加精确和低粒度的报告。 质量保证增加了。我们需要这个角色来确认代码评审的进行和工程的笔记簿被开发人员维护等等。 项目工程增加了,高级分析人员角色加上团队领导角色减少了。因此,项目工程和团队的领导层(分别下降到了 25% 和 75%)被合并成了一个全职的职位。 除了配置管理之外,工程支持增加了,因为到现在为止多数的基础架构(也就是,计算机硬件)是时候被用到了。配置管理增加了以允许集成和测试人员参与构建,同时也支持用于版本控制的配置管理的存储。 支持和评审团队的工作增加了,因为我们要让他们为大的问题把关。多数的代码评审是通过团队的同级评审完成的。这些职位被增加:
高级的、中级的和初级的开发人员,他们支持着增加的开发工作。这些团队成员在总部中进行着远程的开发活动,提供“后端系统”的专家意见。(我们原计划将项目的管理移到总部进行,但是项目当前的安排正在很好的进行工作,因此我们都同意继续保持在项目中的协调方式。) 一个集成与测试的团队有一名领导和一个初级的成员组成。领导成员起草最初的测试说明书,制定高级的测试计划,并且指导初级成员使他能够以生成测试数据、编写测试脚本和书写测试文档的形式为测试提供支持。后来我们发现,我们的团队结构也许是太具有杀伤力了,因为我们的工具仅仅是为了实现在第一阶段中的概念的验证的。我们也许应该在没有太大伤害的前提下调整一下系统的构建和质量保证的正式过程,并且依然要满足我们的第一阶段的目标。最后,我们建立了高质量的概念的验证,而且比我们最初预想的为第二阶段的工作提供了更多的可重用性。
开发方法
一些之前的项目要求我们在共享的开发环境下工作,并且这经常是痛苦的源头。工作在公共代码之上的开发人员经常会打断开发过程中其他的软件部分的工作。我们有时因为架构上的或者许可证上的限制被要求在一个共享的环境下工作,但是我们还是希望在每一个开发人员的机器上拥有一个独立的环境。我们计划以一种正规的基础将开发人员的组件集成到一起。
在 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 部分。就像在本系列第五部分所注明的,这个网关是一个 B2B (business-to-business)接口,这个接口允许大公司可以查询 ASDI 的零件的可用性、提交订单、更新他们的客户信息和查询运输或者帐目状态。
更新设计:双向工程
command gateway 的设计经历了一系列的迭代,已经成为了被显示在本系列的第五部分成熟的设计;然而,一种情形引发了远程的高级开发人员得到与设计的同步。她在她自己负责的部分提出一些优秀的想法,并且我们能够通过双向工程合并他们 — 也就是说,通过逆向工程她的改变合并到我们的 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; j:\usr\local\lib\castor\castor-0.9.3-xml.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)。
逆向工程在分析类之间的关系上是相当有效的。当类的变量被声明为类的成员变量时,找到所有权关系是更加可靠的。有些关系被获取的并不正确(例如,在我们的 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 被识别出来。最初这看起来显示了一种在代码评审价值的缺乏,因此项目工程师们并不是非常认真的检查每一件事情。这里是他们所发现的:
同级评审也通过技能和方法的交叉传授改进了整个团队的能力。开发人员通过了解其他每个人的想法建立起良好的设计模式和编码习惯的部分。代码的评审允许使用大量的时间对各种编码策略进行有价值的赞成和反对的讨论;因此,通常为了学习的目的我们会尽量让至少一个初级的开发人员参与评审。
我们的编码标准不仅仅是简单的针对风格的问题,而且也涉及到了编码习惯、编码实践和性能问题。标准在三个午餐小时被呈现给了团队,连同的还有针对评审过程的指导方针。
评审过程的步骤如下:
在完成了代码和单元测试之上,开发人员创建一个由设计说明、代码、单元测试说明和单元测试结果组成的评审包。 评审包被分发给评审人员 — 也就是根据代码的复杂程度分发给团队领导和其他的两个开发人员。 开发人员为评审人员执行 1 到 3 个小时的代码预排。 评审人员分别的评审和标注代码,并将标注返回给开发人员。 开发人员查看评审人员的注释。 开发人员与评审人员一起执行 1 到 2 个小时的注释预排,并为每一个注释达成一致的行动计划。最初我们存在着对这个评审过程会花去过多时间的担心,但是我们发现它这个过程是极有价值的,它提供了:
每个人都很好的为每一个阶段进行准备。 简单的说,代码有很少的评审人员 — 有时仅仅是团队领导。 最后的预排会议不是匆忙的,因为它提供了很多在方案上的交流、一致意见,和冲突的讨论。总结
我们已经通过指导方针铺好了路,调整了团队的结构和经过深思熟虑的开发方法,我们发现开发(包括对设计的细化)正很好的向前进展着。工程团队开始了解了 Rational Suite DevelopmentStudio 工具的威力。对于这些工具的学习曲线是不寻常的,但是通过这段时间我们已经能够很舒服的使用他们了。特别要指出的是,我们通过使用 Rational Rose 的双向工程、Rational Purify 的检查 Java 内存使用和 Rational Quantify 的代码分析的能力获得了很大的利益。使用这些工具,连同建立单元测试和同级评审,我们很好的达到了 ASDI 系统的质量目标。
计划未来
我们越快的使我们的团队习惯小版本的构建,将对我们的项目越有好处。我们预期为子系统建立每星期五的构建周期,并也建立每第二个星期五进行子系统的集成。为这些小版本的构建组成团队是有价值的,并且对于团队来说也是非常好的通过让大家看到事情被合并成为一个整体来鼓舞士气的方法。
在接下来的几周中将是产生内部和外部的早期演示的工作。为了外部的演示我们将很快的将用户界面屏幕集成到一起。这对我们来说也是非常好的机会来得到额外的需求反馈。
主要风险
甚至是在开发的早期阶段,远程开发的挑战就一直敲打着我们,并且我们知道当我们开始集成我们的组件和子系统时这个挑战将会变得更加的辣手。早期的”实践构建“需要很快的开始以便我们能够平滑的实现集成的过程和解决早期的问题。
贯穿整个项目远程开发对于我们来说都是一个挑战。虽然我们以前也做过远程开发,但是我们还没有解决如何集成跨越分离的地理位置的团队工作结果的问题。我们了解到 Rational 的工具不能完全的消除远程开发的问题,但是他们至少能够减轻远程开发的痛苦。例如,我们还不能防止高级开发人员在 command gateway 设计方面的分歧,但是逆向工程能够通过最少的工作帮助我们评估和集成她的变化。
为了符合我们严格最终期限,开发必须以高效的步伐继续前进。自从我们提供给客户软件的架构文档,已经有一段时间了,客户渴望看到一些进展。尽快的提供集成的演示是重要的。
资源 "Writing Robust Java Code: The AmbySoft Inc. Coding Standards for Java v17.01d" Scott W. Ambler 编著。
关于作者Steven Franklin 在软件的设计、架构和工程过程方面有非常广泛的背景,这些经验通常被用到大的,分布式的信息管理和控制系统中。他从1997年开始使用 Rational 工具,他主要的兴趣在 XML 、J2EE、无线和软件工程技术方面。你可以通过 [email protected]联系 Steven.
本文地址:http://com.8s8s.com/it/it12077.htm