Oracle ADF 开发必读 — 第 3 部分


借助 Subversion 进行版本控制:避免“问题”


如何避免在 Oracle ADF 项目中使用版本控制时出现的一些常见“问题”。

作者:John Stegeman 

2008 年 12 月发布

在本系列的第 1 部分,您已学到了安装 Subversion 、设置信息库和使用 Oracle JDeveloper 11g 执行基本操作等基础知识。在第 2 部分,您了解了向团队中加入另一个开发人员时的工作方式。在此第 3 部分,您将了解使用 Subversion 对您的 Oracle ADF 项目进行版本控制时可能产生的一些问题。

支持的版本

截至本文撰写之日,Oracle JDeveloper 11g 支持 Subversion 版本 1.4.x。虽然此版本和更高版本的 Subversion 服务器兼容,但是更高版本的 Subversion 客户端使用的工作副本格式与版本 1.4.x 中的工作副本格式并不兼容。如果您在您的开发设备上安装 Subversion 1.5.x 客户端,切勿使用该版本客户端软件对您的工作副本进行任何操作。否则,您的工作副本将会悄无声息地转换为版本 1.5,Oracle JDeveloper 将不再将它识别为工作副本,您将不能再使用内置的 Subversion 命令。

检查您当前使用的 Subversion 客户端版本的一个简单方法是使用 svn --version 命令:

c:\>svn --version
svn, version 1.4.6 (r28521)
   compiled Dec 20 2007, 16:19:22


就公用标准达成一致

要确保您的团队使用 Oracle JDeveloper 和 Subversion 高效工作,您应该针对您的 ADF 项目制定一系列公用标准。(我在第 2 部分中介绍代码样式首选项时提供了一个示例。)另外,您的团队还应该统一一些其他标准,例如,数据库连接名称、Oracle ADF 业务组件配置设置等。如果您在项目开始时就制定了一系列公用标准,则可避免在后期不得不将所有代码转换为统一样式的麻烦。

Subversion 有一个特性叫做“钩子”,可以帮助您在将代码签入信息库时强制执行一组公用标准。钩子是用户提供的脚本,Subversion 会在特定时间运行它,例如在向信息库提交更改之前。您可以使用开源工具(如 Checkstyle)轻松地编写一个预提交钩子来检查 Java 文件的代码样式,并在不符合统一代码样式时拒绝文件。还有一个适用于 Subversion 的框架叫做 SVNChecker,带有现成的 Subversion 钩子,可以在将代码提交到信息库之前,针对代码调用 Checkstyle。


无法代替交流

对版本控制系统的常见误解是,使用版本控制系统减少了开发人员之间的交流需求。事实上,使用 Subversion 或任何其他版本控制系统并不会减少您团队成员之间进行交流的需求,并且有可能会增加交流的需求,因为您使用结构化程度更强(而不是结构化程度较低)的方法进行开发。

当使用 Oracle ADF 开发应用程序时,您应该特别注意协调团队成员在模型层中的开发活动。此原则对于 ADF 业务组件尤为重要,因为其中的单逻辑对象(如视图对象)可能包含多个文件。如果两个开发人员都尝试添加或修改同一个视图对象,就很容易造成多文件构成的视图对象不同步并且变得不可用。要避免该问题,您应该确保您的团队成员就他们的工作内容进行交流。

跟踪外部依赖性

当您在使用 Oracle ADF 开发应用程序时,您的应用程序经常需要依靠非 Oracle JDeveloper 生成的组件。一个常见的例子是第三方库的使用;另一个外部组件的常见例子是应用程序所依靠的数据库对象。如果您不将您的版本跟踪方法应用于这些外部组件,当团队中的一部分成员使用的业务组件版本与另一部分成员使用的版本不同时,则可能出现问题。要避免该问题,您应该将您的版本跟踪方法也应用于外部组件。

现在,让我们来了解涉及更多常见外部组件时的情况。

第三方库

虽然 Apache Maven 为实现项目对特定版本的第三方库的相依性提供了方法,但 Oracle JDeveloper 11g(在本文撰写时)还没有对 Maven 的内置支持。而且,不是所有人都在其项目中使用 Maven,所以我将介绍另一种方法。

出于演示目的,我们假设您希望在您的示例应用程序中使用 Apache POI 库。执行此操作的方法之一是将所需的 JAR 文件下载到每个开发人员的文件系统上的某个位置,并在 Oracle JDeveloper 中创建一个指向该 JAR 文件的库定义。然而,当使用该方法时,不同开发人员的 JAR 文件版本可能不同,因此会产生问题。要避免此类问题,我使用的方法是创建一个包括所有第三方 JAR 文件的 Oracle JDeveloper 项目;然后可以将此项目添加到 Subversion 信息库中,可以像管理您的应用程序源代码一样管理该项目。

为了演示,让我们看看团队成员 John 如何针对 Apache POI 库使用此方法。John 做的第一件事是从 Apache POI 网站下载相应的文件。然后,他在其应用程序目录结构中为第三方库创建了一个目录:

图 1

图 1 为第三方库创建一个目录

接下来,John 为 POI JAR 文件创建了一个子目录,并将它们从 POI 分发解压缩到该目录:

图 2

图 2 解压缩 POI JAR 文件

在 Oracle JDeveloper 中,John 为第三方 JAR 文件创建了一个新项目。他在之前创建的目录中创建该项目。他使用 Application Navigator 中的快捷菜单来完成此任务:

图 3

图 3 为第三方库创建一个新项目

出现提示时,他选择 Generic Project 作为项目类型:

图 4

图 4 选择 Generic Project

John 然后指定了相应的项目名称,并提供了他之前创建的目录。不需要向此项目中添加任何库:

图 5

图 5 指定项目名称和目录

现在,项目在 Application Navigator 中可见(尽管当将它展开时还看不到有文件):

图 6

图 6 新创建的项目

为了让 POI JAR 文件成为项目的一部分,John 必须将项目配置为包含项目资源的源路径中的所有子目录。为此,John 右键单击 3pLibs 项目并选择 Project Properties

图 7

图 7 显示项目的属性

然后,通过展开 Project Source Paths 节点并选择 Resources,他可以单击 Include Content from Subfolders 复选框以包括项目所有子目录中的 JAR 文件。

图 8

图 8 包括项目资源中的子目录

进行完该配置后,现在,POI JAR 文件在 Application Navigator 中将可见:

图 9

图 9 Application Navigator 中的 POI JAR 文件

最后,John 通过 Pending Changes 窗口向 Sunbversion 信息库中添加四个新文件(一个新项目文件和三个 JAR 文件),并提交带有相应注释的更改:

图 10

图 10 提交新的项目和 JAR 文件

John 现在可以创建一个新的包含 POI JAR 文件的库定义,并开始在项目中使用 Apache POI。下一次 Josephine 更新她的工作副本时,她也将看到新的 3oLibs 项目和 Apache POI 文件。将来,如果团队决定更新所使用的 Apache POI 的版本,他们可以下载新的版本,用新的版本替换现有的 JAR 文件,并向信息库提交更改,以确保整个团队使用同一版本。

数据库对象

另一个外部依赖性的常见例子是您构建应用程序所使用的数据库对象(表、存储过程等)。如果您像许多开发团队一样 — 每个团队成员都使用其自己的开发数据库 — 您的团队成员的数据库很可能不同步,从而导致版本问题。为了避免此类问题发生,您应该将您需要的所有构件都存储在您的 Subversion 信息库中以保持数据库对象为最新。

在 Oracle JDeveloper 中,您可以通过多种方法完成此操作,包括:

  • 使用离线数据库对象来存储您的对象定义。当对象定义更改后,您可以使用 Oracle JDeveloper 根据数据库协调新的对象定义。
  • 使用 DDL 脚本存储您的对象定义。数据库模式相对稳定后,您可以开始创建用来在切换版本时修改数据库对象的“alter”脚本。
无论您使用什么方法控制对象的版本,不要忘记对常用数据项目也(例如存储在数据库表中的配置数据,查找值等)要进行版本控制。

K. Scott Allen 发布了一篇很有帮助的五部分系列,介绍了在数据库中进行版本控制的方法,其中包含对数据库进行版本控制非常有效的方法。

注意开发中的阻塞点

在许多基于 Oracle ADF 的应用程序中,在向应用程序添加新组件的时候会更改一些组件。我将这些组件称为“阻塞点”。使用 Oracle ADF 开发的应用程序中的两个常见阻塞点是,模型层中的应用程序模块和视图层的 faces-config.xml 文件。如果您的团队在修改这些组件时没有注意,那么很有可能两个团队成员同时修改一个文件。大多数情况下,Subversion 不能合并这样的更改,或者合并的结果为不可使用的组件(因为合并只作用于文本差异而不是语义差异)。

要避免这样的阻塞点,我根据团队规模和开发进展使用下面两种方法中的一种。

第一种方法是指定一个开发人员来拥有对每一个阻塞点组件的更改;当另一个开发人员需要更改组件时,他/她需要与组件所有者就所需更改进行沟通,然后由所有者进行更改并提交给信息库。此方法的优点是它几乎完全消除了出现冲突和语义错误合并的可能性。主要的缺点是,该方法需要开发人员坚持执行手动流程并且将会需要额外的层来进行交流,这可能会给开发过程带来瓶颈。在实际操作中,我发现此方法在阻塞点组件的变化较频繁的开发初期阶段更加实用。

第二种方法是允许所有开发人员对阻塞点组件进行更改。如果在提交时发生冲突或者在更新时发生合并,开发人员可以从信息库恢复更改之前组件的最新版本(还原他/她之前对该对象所做的所有更改)并重新将他/她的更改应用/编码到组件中。此方法避免了 Subversion 的合并操作生成一个不可用对象的可能性,但需要开发人员在发生合并/冲突时做更多的工作。在实际操作中,我发现此方法在阻塞点组件更改频率较低的开发后期阶段更为实用,因为发生合并/冲突的几率也降低了。

总结

您已经了解了如何结合使用 Oracle JDeveloper 11g 和 Subversion 信息库在具有多个开发人员和多个开发分支的团队环境中工作,并对常见的潜在问题有了一定的了解。您应该已经可以在任何 Oracle ADF 项目中使用 Subversion 了,无论是在单用户环境或是多用户团队环境下。

转至第 4 部分 | 返回目录

 

更多精彩内容


John Stegeman ( http://stegemanoracle.wordpress.com) 是 Cambridge Solutions(一家跨国 BPO 和 IT 服务公司)的 EMEA 地区的 Oracle ACE 总监(Oracle 融合中间件)兼首席架构师。他从 1990 年开始就使用 Oracle 产品工作,从版本 3 就开始使用 Oracle JDeveloper。