引言
下面研究一下软件开发中的一个典型场景。软件开发人员 Zoë 在 Web 浏览器中刷新“My Bugs”页面,并看见团队负责人 Rick 已分配给她一个新的错误报告。她打开 Eclipse IDE,并在工作区中查找出错的代码。她修复该错误并向测试套件添加一个递归测试。她运行测试套件以确保一切都按预期工作。她更新构建说明,以记录代码流中的该错误已修复。然后 Zoë 可以将她的所有更改签入源代码存储库,并使用错误报告编号和标题作为签入备注。然后她使用将在其中应用修复的计划的构建版本,对该错误报告做出注释,并将该错误报告标记为“已解决/已修复”。更新错误报告会自动导致向相关各方发送电子邮件,包括报告该错误的团队成员 Mike。一旦某个构建版本变得可用,Rick 将下载该构建版本,验证问题已修复,并将该错误报告标记为“已解决/已验证”。
这个小插曲对于许多软件开发人员来说实在太熟悉不过了——甚至有点单调——但是从整个团队的角度看,其中发生了几件非常有趣的事情。修复错误的工作在团队中流动,从发现并报告问题的 Mike,到复核传入的错误报告并将该工作分配给 Zoë 的 Rick,到修复该错误的 Zoë,并最终返回到 Mike 以进行验证。错误修复本身也在团队中流动,从修复代码流中的该问题的 Zoë,到验证包含该修复的构建版本中的修复的 Mike。这些流可能非常脆弱。如果签入某个修复而没有更新错误报告,或者如果不存在将修复与特定代码流和构建版本联系起来的纽带,则团队中的流就会中断。这些中断会在团队中导致混淆并妨碍进度。更糟糕的是,中断也许不会立即在团队中的任何人面前表现出来。与领域相关的工作(例如,为软件产品编写代码)和主要与维持团队协作相关的工作(例如,在修复错误时标记错误)之间的交织也是非常令人生畏的。
在团队中开发软件非常类似于在乐队中演奏乐器。每个音乐家必须集中精力演奏他或她自己的部分,同时还要与乐队保持合拍和同步。他们必须就将要如何沟通达成一致,并注意彼此发送的信号,否则表演就会失败。强有力的协作和个人的精湛技艺都是出色的乐队表演所必需的。类似地,开发人员一定不能仅集中于构建高质量的代码,他们还必须对自己的活动进行协调,以便所有各个部分能完美地结合在一起。诸如 Eclipse 等 IDE 已成功地提高了个人的工作效率,使得功能强大的工具(例如,代码自动完成)对开发人员来说触手可及。如果能够确认开发人员像编写自己的代码一样积极地致力于与团队进行协作,并提供支持这种工作方式的途径,则能实现更高级别的工作效率提升,这是将重点从个体工作效率到团队工作效率的转变。
尽管 IDE 集成了若干工具,但开发人员仍然要手工做大量的重复性簿记工作——对于保持团队有效地协作来说非常关键但同时也很容易遗忘或出错的工作。如果 Zoë 只需告诉 IDE 她现在正在设法修复某个特定的错误,这就要好得多。然后,当她完成修复和测试用例时,可以指出她已经完成该工作。Zoë 无需执行进一步的操作,系统将提交已更改的文件,并将这些文件与错误报告相关联,更新构建说明,并将错误报告标记为“已结束”。如果工具以这种方式自动化簿记工作,则能通过确保错误报告与代码签入之间的重要联系是可靠的,从而帮助提高团队的工作效率。同时,通过自动化繁琐和容易出错的簿记工作,还可以提高单独的团队成员的工作效率。
Jazz 是一个用于整个软件生命周期的团队协作平台,旨在支持跨所有软件生命周期阶段的任务的无缝集成。Jazz 在客户端和服务器端都设计为可扩展的,并且可以从非常小的团队扩展到大型企业环境。Jazz 整合了工具支持的流程指南的概念,其中工具了解团队已决定使用的开发流程,并无缝地帮助团队成员遵循该流程而不会妨碍他们。Jazz 不仅旨在集成现有的点工具 (point tool),而且还旨在提供一个平台,在该平台上可以构建比以前更加集成的生命周期工具功能。当以这种方式在整个生命周期中集成开发工具时,使用一组结合在一起的点解决方案 (point solution) 来完成难以想象的事情将成为可能。像这样的集成端到端工具可以帮助团队更有效地构建软件,并使得软件开发活动更加令人愉快。
设计目标
|
Jazz 平台的设计和构建目的是:
Jazz 平台的主要作用是为工具编写人员提供要使用的机制和要遵循的规则,这些机制和规则可产生无缝集成的生命周期工具。这些机制通过定义良好的 API 来公开。Jazz 平台还提供了帮助开发新工具的有用构件和框架。
体系结构概述
Jazz 是一个基于客户机-服务器体系结构的平台。通常在受保护的服务器级计算机上运行的 Jazz 服务器承载一组服务,并在其存储库中存放数据。远程客户端通过网络使用 HTTP 与 Jazz 服务器通信。远程客户端具有多种形式(图 1),典型的形式是带有集成的 Jazz 支持的 IDE,这种形式由用户参与的协作软件开发所推动。其他远程客户端(例如 Jazz 特定的命令行工具或 Ant 脚本)在 Headless 模式下操作。还有其他远程客户端则使用 Web 浏览器直接访问服务器,而不需要在本地计算机上安装 Jazz 特定的软件。
客户端-服务器
Jazz 具有两个匹配的部分:服务和客户端库(图 2)。服务在服务器端。服务的实现采用 Java® 编写。服务使用者通过服务接口来联系服务。服务接口充当Web 服务接口的 Java 服务定义,Web 服务接口用于从客户端到服务器的 RPC 样式的同步通信。
对应的客户端部分是一个基于 Java 的客户端库,该库公开一个客户端接口。客户端库向对应的服务接口发出调用,调用通过网络发送到服务器上的对应服务以进行处理。客户端库提供缓存、事件通知和其他使得该 API 比原始服务接口更易于使用的功能。
诸如 Eclipse IDE 和 Ant 等基于 Java 的 Jazz 前端使用客户端接口中的方法。(可以编写类似的客户端库以供非基于 Java 的客户端使用。)
Web 浏览器客户端以类似的方式进行处理,并使用一个更适合于从 JavaScript® 中访问的相关服务接口(将在稍后有关 Web UI 的部分中讨论)。
组件
Jazz 具有模块化和可扩展的体系结构。称为 Jazz 组件 的典型模块提供有助于软件开发生命周期某些方面的功能,例如缺陷跟踪或自动化构建。典型的组件提供一个或多个服务和对应的客户端库,以及建立在这些较低层基础上的领域特定的 UI 部分。将某个组件安装在 Jazz 服务器上将使该组件的服务普遍可用,而将组件安装在 Jazz 客户端上则为一个用户提供对新服务的访问。Jazz 组件可以独立存在(仅依赖基本的内置功能),或者可以利用其他已安装组件所提供的功能。
虽然组件的概念对于解释 Jazz 的扩展方式非常方便,但是 Jazz 并没有提供新的通用组件机制。相反,Jazz 同时在服务器和基于 Java 的客户端利用 Eclipse 平台 的可扩展机制(不熟悉 Eclipse 平台的插件和扩展点概念的读者应该阅读 Eclipse Platform Technical Overview 的 Platform Runtime and Plug-in Architecture 部分以了解背景信息。)组件被打包为 Eclipse 概念上的插件,并使用 Eclipse 的扩展点概念为其他组件提供扩展。单个组件由一组插件组成,其中有些插件安装在服务器上,有些插件安装在客户端。
原型 Jazz 组件包括五个插件:
服务、公共和 Web UI 插件安装在服务器上。
插件使用扩展点向 Jazz 注册。组件的公共插件(同时安装在客户端和服务器上)通过扩展点注册组件的服务接口。服务插件通过仅用于服务器端的扩展点注册对应的服务实现。客户端库插件通过仅用于客户端的扩展点注册客户端接口。这些扩展内容带有该组件的 ID 字符串。这些扩展内容用于在运行时将组件结合在一起(图 3)。
该组件的客户端 UI 的客户端插件和客户端库安装在 Eclipse IDE 中。客户端 UI 插件通过 Eclipse 平台扩展点提供视图、编辑器等等;客户端库插件通过一个 Jazz 特定的扩展点注册其客户端接口。
客户端库设计为在没有 OSGi® 运行时的客户端中工作,例如 Ant。客户端库只可以依赖其他组件的客户端库,而不可以依赖其服务或 UI。
组件必须声明任何对其他组件的依赖性。依赖关系图一定不能包含环。组件还可以声明自己的扩展点,从而使其可由其他组件扩展。
服务器
Jazz 服务器是一个基于 Java 的 Web 应用程序,可以在任何兼容 Java EE 1.4 的应用程序服务器中运行。Jazz 的技术预览版中支持两个不同的应用程序服务器:Apache Tomcat 和 IBM® WebSphere®。Apache Tomcat 是一个开放源代码的 Servlet 容器,可以将其安装在桌面级计算机上。IBM WebSphere Application Server 是一个适合各种规模的商用产品解决方案。服务和服务器端 Jazz API 的语义与应用程序服务器选择无关,从而允许在将来版本中支持更多的应用程序服务器。
对于熟悉 Eclipse 的读者,Jazz Web 应用程序在内部是围绕一个 OSGi 运行时进行构造的。Jazz Web 应用程序处理服务器上安装的所有 Jazz 组件的服务。在 Jazz 服务器上安装新组件涉及到使主 Web 应用程序的 OSGi 运行时知道该组件的服务器端插件(OSGi 包)。该包的清单声明了任何对其他已安装组件的依赖性;单独的扩展清单包含任何对各个扩展点的扩展。OSGi 运行时在启动时处理包清单,并确保所有已安装组件的组件间依赖性得到满足。Jazz Web 应用程序管理将所有已安装组件的扩展聚集在一起的扩展注册中心,并将组件的服务接口上的传入请求路由到对应的服务以进行处理。
内核组件
Jazz 项目开发构成 Jazz 平台 的组件集。Jazz 社区的其他成员(包括 ISV)将开发附加组件以向 Jazz 增添新功能。Jazz 平台的主要组件如图 4 所示。Jazz 平台内核 是必需的组件集,其中两个组件为:Repository 和 Team Process。其他组件处理软件开发生命周期的特定方面。
以下几个部分将提供内核组件的概述。
Repository 组件
许多应用程序生命周期工具的一个特征是需要在一个中心位置存储工具特定的信息,并使信息在该位置对所有团队成员可用。Jazz 的一个重要功能是由 Repository 组件提供的可扩展的存储库。Repository 组件在内核中,因此其功能对所有客户端和服务器配置中的其他组件可用。
Jazz 组件通过采用 UML 表示的高级对象模型来描述其数据。该对象模型称为组件的逻辑模型。该模型由各个项和 Helper 类构成。数据以称为项的顶级对象形式存储在存储库中。每个项具有固定的项类型和全局唯一的项 ID。Jazz 组件可以声明新的项类型,这些项类型在 UML 中指定为类。简单的项属性可以是基元数据类型,例如整数或字符串,或者是称为内容的特殊数据类型,这种数据类型用于存储诸如文件字节等批量数据。复杂项类型的逻辑模型还可以包括 Helper 类,并且项可以具有引用 Helper 对象的属性。所有项都被视为顶级对象,并且所有项间引用都是非包含引用。另一方面,Helper 对象始终包含在某个项中,并且对 Helper 的所有引用都是包含引用。Helper 对象的生存期由包含项的生存期控制。Jazz 强制项与其 Helper 对象之间的引用完整性,但是不强制项之间的引用完整性;也就是说,悬空项引用是允许的。
对于某些类型的项,为审核目的而维护项的创建和后续的修改的历史记录是非常重要的。这在该平台中通过 auditable 项类型表示。对于声明为 auditable 的项类型,存储库自动记忆该项的过往状态的审核跟踪,包括保存该项的用户和更改时间。各个项状态被赋予唯一的状态标识符。对于不需要审核历史记录的项类型,该平台允许将它们声明为 simple 项,并且存储库将仅保留该项的最新状态。对于不存在当前状态的全局概念的项类型,该平台允许将它们声明为 versionable 项。versionable 项状态通常称为版本或修订。(有关 versionable 项的更多详细信息,请参阅单独的 Source Control 组件概述。)
存储库中的每个项具有唯一的项 ID,可将其用于检索项的键。事实上,项 ID 是全局唯一标识符(universally unique identifier,UUID),因此可以将一个存储库中创建的项复制到另一个存储库并保留其标识。类似地,为项状态和内容值分配了全局唯一标识符,因此可以将某个项或内容流的任何特定状态复制到其他存储库并保留其标识。
组件的逻辑模型在较高级别描述项,但是 Jazz 使用较低级的存储模型来了解数据。存储模型直接派生自逻辑模型。组件通过扩展点提供存储模型,Jazz 的通用基础设施的各个部分在运行时使用这些模型。事实上,存储模型“教会”Jazz 有关新的项类型的知识,包括如何在基础关系数据库中布置适合于存储该项的属性和关系的表,如何高效地查询那些项,以及如何对项进行序列化以用于服务器和客户端之间的通信或用于存储库之间的项复制。可以使用一个 Jazz 特定的工具将组件的逻辑模型编译为存储模型。Eclipse Modeling Framework (EMF) 用于以声明形式表示存储模型:存储模型是一个 EMF Ecore 模型。
存储模型由 Java 类(位于组件的公共插件中)组成,这些类对应于逻辑模型中的 UML 类。每个项和 Helper 类型都存在一个 Java 类,其中具有针对每个所建模的属性和引用的实例字段。对于每个项类型,存在一个单独的项句柄类,用于表示对该类型的项的引用;项句柄由项类型和项 ID 组成。逻辑模型中的非包含项引用在存储模型中映射到包含项句柄的字段。这些类为处理项的 Java 代码提供了强类型的编程模型。最适合将生成的 Java 类视为带有标准 get/set 方法的数据结构,这些方法用于数据结构的每个属性。当组件需要将其数据结构作为 API 公开以供其他组件使用时,一般是通过手工设计的 Facade 接口来完成的,这些接口提供更加受控制的访问,并隐藏了实现细节。数据结构的这些 Java 类表示形式是项在内存中的表示形式。
Repository 组件提供了用于创建、检索、更新和删除存储库中的项的通用服务器端 API 方法。组件的服务器端逻辑调用这些方法来直接操作它在存储库中的项。有了项句柄,任何组件都可以使用通用 API 方法,直接从存储库中完整(所有属性)或部分(仅针对指定的属性)地检索对应的项。但是,每个组件完全控制其声明的项类型的创建、修改和删除。组件 X 不能直接操作组件 Y 的项;相反,X 只能通过调用 Y 已选择作为 API 提供的服务方法来实现此目的。
在使用服务器端 API 来更新其中一个项时,组件遵循一种简单的模式。调用者从存储库中获取该项的当前状态,并基于检索到的状态创建一个内存中的工作副本。调用者修改该工作副本的属性值。当完成时,组件代码调用保存方法,并向其传递工作副本。保存方法更新存储库中的该项。工作副本记住了被获取时的状态 ID。保存操作检查该状态是否仍然是当前状态,如果不是则失败。这确保对某个项的并发更新不会导致意外的数据丢失。
除了按项 ID 直接检索某个项以外,服务器端 API 还包括基于项的属性和关系对存储库中的项运行复杂查询的操作。该查询语言基于面向对象的 EJB QL 的语法,此语法经过了改编以适应存储库中找到的对象类型。
存储库读和写操作是原子的。服务器端 API 还包括一个操作,用于显式地将任意的读和写操作序列包装为单个原子事务。Jazz 具有对来往于存储库的内容对象进行流处理的服务器端 API,旨在使流处理能够在存储库事务之外安全地完成。
Jazz 还提供了一个由存储库支持的 Feed 服务。组件通过服务器端 API 报告更改事件,以通告相关的更改,例如某个构建版本的完成,或者到某个流的传输。更改事件记录在存储库中(并参与常规的存储库事务)。Feed 服务发布最近的更改事件的 Web Feed(Atom 或 RSS),该 Web Feed 适合于由任何与标准兼容的 Feed 阅读器(分别为 Atom 1.0 或 RSS 2.0)进行分析。尽管所有的更改事件具有相同的固定结构,但是组件可以通过服务器端扩展点注册专门的呈现器 (renderer),该呈现器选择性地覆盖从更改事件到 Feed 条目的缺省转换,并允许组件添加自定义文本元素和链接。
存储库由一个关系数据库提供后端支持。Jazz 的技术预览版支持两种关系数据库系统:Apache Derby 和 IBM DB2®。Apache Derby 是一个最适合于小型存储库的开放源代码关系数据库系统。IBM DB2 是一个为各种规模的存储库提供解决方案的商用产品。逻辑模型、存储模型和服务器端 Jazz API 的语义全都与特定的关系数据库系统选择无关。将来的版本中可能添加对其他关系数据库系统的支持。
在运行时,Jazz 服务器发现由组件通过扩展点提供的存储模型。Repository 组件将存储模型映射到关系数据库模式和表。根据该映射,用于获取、保存、删除和查询项的服务器端 API 操作在运行时被转换为 SQL 语句,并由关系数据库系统执行。
该事务机制利用了保存操作的“如果被并发修改则失败”(fail-if-concurrently-modified) 语义以提供完整性。在读写事务期间保存的项保留在内存中,直到该事务结束,并延迟实际的数据库更新(尽管 Jazz 确保在事务期间检索项时可以看到该更新)。只有在事务提交时才需要数据库写入锁,以确保原子地更新已修改的项,而不受到并发更新的干扰。
在客户端,组件的客户端库为客户端提供了 API,以便客户端操作组件选择公开的项类型。创建、更新和删除存储库中的项只能通过上面讨论的服务器端机制来完成。组件的客户端库调用组件的服务方法,这些方法在服务器上远程运行并访问存储库。在客户端和服务器之间传递的参数和结果类型可以包括在组件的存储模型中声明的类型。存储模型的运行时表示形式用于对对象进行封送处理。组件的存储模型包含在组件的公共插件中,该插件同时安装在客户端和服务器上。建立客户端和服务器之间的连接以后,Jazz 将检查两端是否具有相同版本的存储模型。
Jazz 客户端接口需要对客户端片段可用,例如 Eclipse IDE 中的各种视图和编辑器。这意味着该接口必须提供相关方法,以帮助客户端的各个部分在所访问的存储库中的项的当前状态方面保持协调。Repository 为此目的而提供了一个客户端项管理器。对于简单和可审核的项类型,项管理器分配共享项。共享项是存在于客户端的内存中对象,并且可由需要对该特定项的当前状态进行读访问的客户端使用。客户端不允许修改共享项;对于客户端来说,共享项是只读对象。当客户端将该项的新状态保存到存储库时,各个属性的新值将复制到共享项中,并向相关各方发送通知事件。由于共享项实例就是在该项发生改变的相同地方进行修改的,因此存储对该实例的引用的客户端随时可以访问该项的当前状态,而不需要进行服务器往返以检索该项(除非是在最初向项管理器请求某个特定共享项的时候)。
与服务器端编程模型相反,不存在用于构成针对存储库的原子事务的客户端机制。一般情况下,在设计组件的客户端接口中的方法时必须考虑到潜在的并发更新,并将其实现为在服务器上作为原子事务运行的组件特定的服务方法。Repository 组件具有用于针对存储库上载和下载内容对象的客户端 API,旨在使流处理能够在存储库事务之外安全地完成。
Team Process 组件
Team Process 组件提供了 Jazz 的流程支持基础。Team Process 是一个内核组件,因此其功能对所有客户端和服务器配置中的其他组件可用。
在此上下文中,流程是指用于对工作进行组织的实践、规则、指导原则和约定的集合。团队的流程是团队已决定(或养成)的行事方式的总和。
对于非常小的团队,流程通常是非正式的,并且没有文档记录。随着团队的发展壮大,流程的部分内容可能在团队的项目主页上做了文档记录,以使新的团队成员能够迅速吸收这些内容。大型组织可能编写了预期其项目团队要遵守的一般实践和过程的描述;项目团队预期将以标准流程模板为起点,并对标准流程模板进行自定义以适合项目和团队。有些组织和团队则更进一步,并创建了涵盖流程的绝大部分的正式模型。
Jazz 旨在实现跨整个软件开发生命周期的全面支持。贯穿所有项目阶段的一条主线是团队成员一致同意遵循的流程。通过教会 Jazz 有关流程的知识,Jazz 就能够以流程特定的方式帮助团队。这种流程支持可以具有广泛(并且完全开放)的形式,范围从动态规则检查,到提供在线(例如,F1 键)流程帮助,再到自动化簿记工作。
Jazz 通过以下方式支持流程:
以下几个部分将详述以上内容。
项目区域是系统对软件项目的表示形式,并且旨在完整地承载开发和维护方面。项目区域在存储库中存储为顶级项。项目区域拥有构成项目资源的所有项目构件和这些构件之间的所有关系。对项目区域和其中的构件的访问通过权限进行控制。
存在一个从事该项目的人员团队。人员由贡献者 (contributor) 项显式地表示。团队显式地表示为属于该项目区域的项目构件。贡献者组成的团队一般负责该项目区域和其中的一切。
与某个项目区域关联的是一个团队流程。团队流程控制在关联的项目区域中从事的所有活动、构件、构件关系和操作。流程由一个流程规范和一个迭代结构进行定义。流程规范和迭代结构都存储在项目区域中。迭代结构定义现有的开发线 (development line),并将开发线分解为各个迭代。它还定义了每条开发线的当前迭代是哪一个迭代。流程规范描述团队成员所能扮演的角色,以及在多个迭代中适用于每个角色的流程规则。流程规范还定义了哪些流程规则可以进行进一步的自定义。
项目区域划分为各个团队区域,并安排为具有多个根的层次结构。每个团队区域确切地仅属于一条开发线。每个团队区域可以自定义沿着父链继承的流程规则。因此,团队区域的流程规则可能与项目区域以及项目区域的流程规范设定的范围中的其他团队区域的流程规则不同。
项目区域的每个项目构件确切地仅属于其中一个团队区域。随着时间的推移,项目构件可能从一个团队区域移动到另一个团队区域,但是始终在最初的项目区域的范围之内。项目构件与项目区域和项目区域与其控制流程之间的关联相结合,允许系统的各个部分从项目构件导航到控制该构件操作的特定流程的表示形式。这使得系统的各个部分可以按照对团队成员有帮助并且与流程保持一致的方式操作。
支持流程的 Jazz 组件的设计特点在于,在系统已知的某个流程控制着所做工作的环境中,这样的组件能够表现良好。流程支持必须开放某个组件,以便流程规则能够指导该组件。“支持流程”对每个组件的含义千差万别,但是所有 Jazz 组件预期都以适合于其功能的方式支持流程。其目标是使可能对制定任何类型的流程有用的东西变得可用。
组件本身保持独立于流程:它没有规定自己提供的哪些功能应该在任何特定的情况下使用。控制流程将通过指定流程规则集来负责做出这样的决策。但是,要开放什么以及开放程度如何,则完全由组件编写人员决定。
组件提供流程支持的几种一般方法如下:
每个组件编写人员将负责确定这些类型的流程规则中哪些对他们的组件有意义。
组件的客户端库插件通过扩展点以声明的方式定义其对流程支持的贡献。类似地,组件的服务实现插件定义了服务器端对流程支持的贡献。
客户端和服务器端流程实施各有其用途。客户端流程实施可以通过 UI 与用户交互,并与 IDE 交互;服务器端流程实施则不能与其中任一方交互。另一方面,服务器端流程实施可以在与主操作相同的存储库事务中运行;客户端流程实施则不是事务性的。例如,这使得服务器端流程代码可以将更改集传输到流,并向所传输的更改集的工作项添加说明,这一切工作全都在同一个原子事务中完成。服务器端流程支持不能规避,而客户端流程支持天生就不太可靠,因为它依赖于各个开发人员个人的客户端配置。
正如计算机程序是对事情应该如何在运行时动态地展开的静态描述一样,流程规范是对事情应该如何在软件开发过程期间展开的静态描述。在后一种情况下,动态展开的是团队成员执行的工作;项目区域是动态上下文;项目构件是运行时对象。
当从事该项目的团队成员着手做他们的工作时,他们将遇到受流程规则影响的情形。理想的情况下,系统在发生这种情形时发出通知,并将以有帮助并且与流程保持一致的方式进行干预。问题的要点在于如何将这种理想情况投入实际应用。仅当团队成员执行某个触发组件特定的流程实施机制时,流程支持才会发挥作用。使用受影响的构件,操作将确定自己应该在哪一个团队区域的上下文中执行。流程支持通过参考沿团队区域的父链的流程自定义和项目区域中适用于当前迭代的流程规范,从而确定团队区域的有效流程。有效流程提供了操作的参与者列表、组件配置数据等等。
流程规范以声明的形式表示,而基本操作则表示为 Java 代码。流程规范以能够高效地执行的编译形式保存。在特定情形下执行流程规范意味着确定和执行适用的流程规则。
存储在项目区域中的流程规范是在流程模板基础上实例化而来的。Jazz 提供了用于创作流程模板、编辑项目区域的流程规范和迭代结构以及编辑团队区域的流程自定义的方法。
使用工具(例如 Eclipse Process Framework 所提供的工具)创作的流程描述可部署到 Jazz 存储库,并与现有的流程模板相关联。然后对于其流程规范派生自这些流程模板的项目区域,可以在其上下文中查看流程描述。
可选的平台组件
除了提供通用基础设施的内核组件以外,还有其他平台组件处理软件开发生命周期的特定方面。与内核组件相反,其他组件是可选的。感兴趣的读者可以参阅各个组件的概述文档以了解进一步的信息:
客户端 GUI
用户将通过桌面上的 UI 与 Jazz 交互。本部分研究主要的 UI:基于 Eclipse 的 IDE 和 Web 浏览器。
IDE 集成
Eclipse 平台 是一个用于工具集成的通用平台。设计用于集成应用程序开发生命周期工具子分类的 Jazz 平台旨在与包括 Eclipse 在内的其他集成工具密切协作。实际上,Eclipse 是主要的客户端 IDE 集成工具。
在 UI 级别,Jazz 平台为 Eclipse 贡献了两个高端视图部分:Team Central 和 Team Artifacts。这两个视图充当信息中心,并且旨在由 Jazz 组件进行扩展。
Team Central 视图是可由用户自定义的 Jazz 平台协作中心,允许团队成员查看团队中正在发生的事情(图 5)。Team Central 是带有多个通过扩展点提供的部分的 Eclipse 视图。典型的部分显示简明的摘要,并连接到另一个提供更详细信息的视图或编辑器。用户可以在任何时候配置哪些部分可见。Jazz 提供了一个用于编写各个部分的简单框架,并提供了用于产生简明的可视化摘要的特殊图表小部件。Jazz 内核提供了相关的部分,用于显示通常有用的东西,例如 Web Feed 和聊天好友列表。其他 Jazz 组件提供了组件特定的部分,例如用于工作项和构建版本的部分。
Team Artifacts 视图提供了对与 Jazz 相关的构件的集中访问(图 6)。该视图以按项目区域分组并按团队区域筛选的方式显示构件。各个条目通过扩展点提供。Jazz 内核提供了用于诸如 Web Feed 订阅等的条目。其他 Jazz 组件提供了组件特定的构件,例如构建版本和计划。
Web UI
除了高质量地将 Jazz 集成到 Eclipse 和其他 IDE 中以外,Jazz 还允许用户从 Web 浏览器直接访问 Jazz 服务器。该 UI 称为 Jazz Web UI。Jazz Web UI 比 IDE 更适合于随意或偶然的用户,因为它不需要在客户端计算机上安装任何特殊软件;所需要的只是一个 Web 浏览器。
每个 Jazz 服务器具有一个主网页,用户可以在其中选择项目区域并登录。一旦已登录,用户即可与 Jazz 服务器交互,并浏览 Jazz 存储库中的信息,包括阅读最近的事件、输入和更新工作项和下载构建版本。图 7 演示了显示某个工作项的 Jazz Web UI。
Jazz 平台提供了可扩展的体系结构和 API,可以简化特定组件的基于 Web 的丰富 UI 的开发。与 Jazz 组件的其他部分一样,组件的 Web UI 被开发为在 Jazz 服务器上运行的 Eclipse 插件。每个 Web UI 插件向某个扩展点提供组件特定的网页和脚本。在运行时,服务器将所有已安装的组件提供的内容聚合到构成服务器 Web UI 的网页中。
Jazz 平台的技术预览版的 Web UI 包括几个关键的 Jazz 组件,包括工作项、构建版本和报告。
Jazz Web UI 遵循一个基于 Ajax 和 REST 的编程模型。Ajax 是一种使用基于标准的 Web 技术(HTML、JavaScript、CSS 和 DOM)的Web 编程风格,这些技术无需刷新整个页面即可实现页面和服务器之间的交互。传输到客户端的 Web UI 包含脚本,这些脚本处于 Web 浏览器中显示的 GUI 元素和带有逻辑以及存储库的服务器之间。客户端脚本语言为 JavaScript。服务器请求采用 URL 形式,这些 URL 调用 REST 样式的 Web 服务;响应为 XML 或 JSON 形式。使用此方法,所有用户界面逻辑和 UI 状态完全驻留在客户端上的 Web 浏览器中,并且所有逻辑和执行状态都保留在服务器上。与传统网站相比,这种方法使得用户界面可以更灵敏地响应用户操作。这种方法还提供了很好的可伸缩性:服务是无状态的,会话数据不通过网络来回发送,并且客户端缓存可以优化存储库中不常更改的项的获取。
构建 Jazz 组件的 Web UI 涉及到:
Jazz 平台的 Web UI Foundation 部分同时在两端提供了有用的框架。对于客户端 GUI,Jazz 基于开放源代码的 Dojo Toolkit,后者通过提供一个抽象浏览器之间的不一致性的丰富小部件和事件框架,从而简化了 Ajax 开发。对于 REST 服务,Jazz 提供一个 REST 框架,此框架抽象了处理 REST 请求的细节(HTTP、数据封送和取消分送等等)。REST 服务通过 Java 接口进行定义。该 Java 接口和项的基于 EMF 的存储模型在运行时用于对请求和响应进行封送处理。在许多情况下,REST 服务方法的实现只是调用组件的主服务接口上的对应方法。
与其他生命周期工具的互操作
Jazz 旨在涵盖全范围的软件生命周期工具,并在 Jazz 存储库中存储所有的持久数据,数据在存储库中进行集中管理。尽管 Jazz 有此雄心,也可能存在让 Jazz 客户继续使用其他软件生命周期工具和系统的理由,这些工具和系统在自己的存储库中存储持久数据。也许组织对某个特定工具所提供的服务非常满意,而未看见切换到使用基于 Jazz 的等效工具的重大好处;也许组织正在逐渐地过渡到 Jazz,并将在几年时间内分阶段推进。无论是什么原因,都存在让 Jazz 与企业中正在使用的其他软件生命周期工具和系统互操作的持续需要。
Jazz 和外部生命周期工具在 GUI 级别与相同桌面环境(例如 Eclipse IDE 或 Web 浏览器)的集成,使得用户同时访问两种工具变得非常方便。在某些情况下,这可能就足够了。由于外部生命周期工具的所有持久数据存储在 Jazz 存储库之外,互操作程度可能非常有限,使其无法参与 Jazz 特定的操作。
Jazz 提供了一个用于代理项的轻量级框架。代理项一对一地对应于另一个系统中的相关对象。代理项是通用的;它们通过标识字符串(例如某个 URI)引用外部对象,并且能够携带任意的键-值属性集,这些属性用于表示外部对象状态的“相关”部分。如果外部对象的类型在 Jazz 中具有直接的对等项类型,则可以将外部对象与对应的 Jazz 对等项进行配对。在此情况下,代理项提供两者之间的连接。每个代理项引用一个同步规则,该规则指定外部项中的命名属性与 Jazz 对等项的命名属性之间的映射。映射是有方向的:传入映射确定对外部对象的更改如何转换为对 Jazz 对等项的更改,而传出映射则确定对 Jazz 对等项的更改如何转换为对外部对象的更改。同步规则还确定做实际工作的服务器端同步管理器。可以通过扩展点提供新的同步管理器类型。