如果要接手一个已经运行了好几年的软件项目,那么怎样才能得到对项目开发历史的认识呢?最好的方法可能就是与曾经参与该项目的开发人员对话,但是这说起来容易,做起来却很困难。原有的开发人员通常都已转到了其他项目中,而且要找到他们也很难。您可以查看释出频率(release frequency),尽管这可能受非技术性的强制规定控制(有时可能只是出于“我们要在本财政年度末做一个发布”的理由)。您可以查看 bug 和特性请求跟踪器,还可以在开放和关闭的 bug 讨论中挖掘信息。或者可以直接进入源代码历史记录,用 StatCVS 这样的工具查看曾做过哪些记录,这些记录是谁修改的。我将 StatCVS 运用在各种大型项目上已经有好几年的时间了,它生成的报告一直都很不错。在本文中,将演示如何在项目上设置、运行 StatCVS,如何阅读它生成的报告,以及 StatCVS 需要改进的地方。
安装 StatCVS
StatCVS 是一个 Java 程序,需要 JDK 1.4 或更高版本的支持。从命令行安装 StatCVS 最容易:只要下载最新的发行版,将它解压到一个目录中即可;我用的是 /usr/local/statcvs/ 目录。而且,如清单 1 所示,我还创建了一个符号链接,叫作 statcvs
,它链接到刚刚安装的版本上。这可以节约日后的一些打字工作时间,更重要的是,日后只要把符号链接修改为指向要使用的版本,就可以在 StatCVS 的不同版本间切换。
|
如果列出 statcvs 目录中的文件,就可以看到那里没有任何适用于 StatCVS 的支持 JAR 文件(supporting JAR file)。惟一的 JAR 文件是 statcvs.jar,它包含 StatCVS 使用的惟一的第三方库:JFreeChart。这种方法使得开始了解 StatCVS 变得更容易,因为不需要关于类路径的更多知识。
运行 StatCVS
为了演示 StatCVS 的工作方式,需要找到一个带有有趣的 CVS 历史记录的项目,并生成一些活动报告。developerWorks 的项目 Jikes 已经进行了一段时间,有大量开发人员,还有一个公共的 CVS 储存库,所以它是一个好例子。
从 CVS 中获得源代码
为了从 StatCVS 得到 Jikes 的报告,需要得到最新的源代码,并生成一个 CVS 日志文件让 StatCVS 分析。所以,需要从 Jikes 的 CVS 储存库签出它的源代码。Jikes 的开发人员允许拥有只读权限的匿名用户对其储存库进行访问,所以可以用这个方法得到源代码,如清单 2 所示:
|
创建 CVS 日志文件
现在机器上已经有了 Jikes 代码,需要创建一个 CVS 日志文件供 StatCVS 处理。要创建这个文件,需要进入 jikes 目录,运行 cvs log
命令。正如从清单 3 中看到的,我把命令的输出重定向到了一个叫作 logfile.txt 的文件:
|
只是为了好玩,我对此进行了计时。在我的工作站上,这大约花费了 40 秒的时间,生成的日志文件大小约为 3.3 MB。
命令行界面
现在可以运行 StatCVS 生成报告了。可以从命令行运行 StatCVS,也可以从 Ant 运行。首先来看一下命令行界面,然后再来讨论 Ant。
StatCVS 从命令行运行很容易,因为只有一个 JAR 文件,而且可以把 JAR 文件名直接传给虚拟机。可以用不同的选项控制输出。这里是一些比较有用的选项:
-title [标题]
—— 放在报告上的显示标题。
-output-dir [目录]
—— 报告文件存放的位置;如果目录不存在,则自动创建该目录。
-include [模式]
—— 只包含与指定模式匹配的文件。
-viewcvs [ViewCVS url]
—— 储存库的 ViewCVS Web 界面的 URL。
下面用以上选项创建报告。首先,必须移动到 jikes/ 目录上,然后从命令行运行 StatCVS,如清单 4 所示:
清单 4. 从命令行运行 StatCVS
|
注意,上面使用了 -include
参数,只捕获 C++ 源代码文件和头文件。在 CVS 模块中有许多其他文件(文档、配置脚本、报告、Web 页面等),但是本文只关心源代码。
Ant 任务
清单 5 显示了与清单 4 的命令行调用功能相同的 Ant 任务定义:
|
图表和图形
报告放在清单 4 指定的报告目录中。如果用浏览器打开该目录中的 index.html 页面,该页面如图 1 所示:
可以看到可用报告的分类:关于代码作者的一些统计数据、查看提交日志、代码段的行,以及关于文件和目录大小的一些统计。
代码行
代码行图表如清单 2 所示,它可能非常有趣:
从这个图表中可以看出,代码最初是在 1999 年初导入的。从那以后,它增长得非常稳定,一直到 2001 底,那时代码的数量开始略有下降。还有几次,新的代码被引入或者旧的代码被重构出去,这些可以从代码行计数的急剧升降上表现出来。从 2004 年开始,似乎没有加入太多代码,这可能表明 Jikes 已经成熟到了某种程度,主要对它做些维护工作即可。
如果从主报告页上单击 Authors 链接,就可以看到数字和图表,它们指出每个参与者贡献了多少代码,如图 3 所示:
很明显,ericb 和 shields 对 lion 负责的代码有所贡献,而其他参与者也偶尔参与其中。注意,没有任何一个参与者从头到尾都参与了该项目。这个事实清楚地证明:长期项目需要那些拥有良好变量名和干净设计的清晰代码。
偶尔,StatCVS 在生成报告时表现得更聪明。如果 CVS 储存库只有一个参与者,那么主报告页上的链接只会写上“Author page for joe_smith”,而且不会生成比较图表。这样 StatCVS 会运行得更快,报告页也会更整洁。
现在再来看一个参与者的活动图表。在主报告页面上,单击 Authors 链接可以访问 Author Activity,如图 4 所示,图中显示了每个参与者是添加了文件,还是修改了文件:
您可以看到,shields 添加了大多数代码,这在预料之中,因为这个人显然是代码导入 CVS 之后的第一个维护者。同样,ericb 在项目启动之后几年之间一直进行类似的工作,主要在修改文件。
提交日志
提交日志(Commit Log)仅仅是对模块做的全部修改的一个列表。这个报告显示了谁做了修改,以及提交者在所做修改上附加的注释。而且,因为 Jikes 的储存库中有一个 ViewCVS 界面,运行 StatCVS 时还使用了一个 -viewcvs
参数,所以报告中包含了到已实际修改的源代码的链接。例如,在 2004 年 12 月 12 日,src/decl.cpp
有一个改动。如果点击 decl.cpp,会看到添加了一个 if
语句,还有一个注释。图 5 显示了 ViewCVS 的一部分,展示了两个文件版本之间的差异:
还有其他一些报告:一个报告显示了平均文件大小,另外一个显示了如何通过目录树分布代码,还有一个则显示了哪个文件的版本改动最多。Jikes 的整个报告可以通过单击本文顶部或底部的 代码 图标得到。只要将它解压,并用浏览器打开 index.html,就可以看到这个报告。
为多个项目生成报告
前面已经看到了如何在一个 CVS 储存库上运行 StatCVS。但是,如果拥有多个储存库,那么您就会希望有一种方法能够每天夜里为所有的储存库生成 StatCVS 报告。因为可以从命令行运行 StatCVS,所以这是一个用脚本就可以解决的简单问题。以下是一些需要牢记的事项:
- StatCVS 是一个 Java 程序,所以需要大量内存才能启动。处理大型 CVS 储存库时也需要相当一段时间。所以如果运行它的机器还有其他用途,那么最好在处理不同的储存库之间让机器休息一会。如果运行的系统支持优先级设置,那么用低优先级来运行耗时比较长的任务是一个好主意。
- 如果定期将储存库添加到机器或从机器中删除储存库,那么某些储存库可能不包含模块。所以请事先检测这种可能性,免得没有必要地启动 StatCVS。
清单 6 显示了一个小小的 Ruby 脚本,可以在拥有公共父目录的多个储存库上运行 StatCVS;在下载代码中也有这个脚本:
清单 6. 运行 StatCVS 处理多个储存库的脚本
|
StatCVS 内幕和限制
因为 StatCVS 是一个开源项目,所以您可以得到它的代码。要得到 StatCVS 的代码,请从 StatCVS 的页面下载源代码 zip 文件,或者从这个 Web 站点上的 CVS 储存库签出代码。
内幕
这里是一些关键的统计数字:
- 4,463 行代码,由 JavaNCSS 测量。
- 176 个 JUnit 测试。
- 一个很好的 Ant 构建文件,可以促进定制构建的编辑。
- 一个好标志 —— PMD 在 StatCVS 中找不到未使用代码的例子。
StatCVS 用 JFreeChart 来创建图表和图形。所有的图表都用可移植网络图形(Portable Network Graphics - PNG)格式生成,大多数现代 Web 浏览器都支持这种格式。生成图表的代码被很好地封装在 net.sf.statcvs.renderer
包中。
限制
最大的限制可能是 StatCVS 不支持分支;它只能报告对每个模块的 HEAD 所做的修改。所以,如果开发团队的应用模式是为产品的每个版本建立一个新分支,并且只提交到这个分支,那么 StatCVS 无法返回正确的结果。这个问题曾在 StatCVS 的邮件列表上讨论过,但是看起来近期不会得到解决。但是,既然它是开源的,谁会知道以后会怎样呢?
另一个限制是 StatCVS 只支持 CVS。随着 Subversion 正在迅速赢得 CVS 继承人的地位,所以如果 StatCVS 能够两者都支持,那就太棒了。在 StatCVS 的邮件列表上已经有了一些关于这点的讨论,但是 Subversion 修改集的格式看来正是目前的障碍。
结束语
挖掘 CVS 储存库来查找使用信息,可能产生大量的数字和图表。但是要认识这些数字的有用性,以及它们能够为特定项目开发提供什么样的深入观察,这些则要取决于您的判断。在脑子里要有这样一些概念,StatCVS 可以提供一些有趣的可视快照,让您了解项目源代码在其生命期间发生的事。
而且,StatCVS 也是开源项目良好运行的一个优秀模型。它的代码整洁、构建过程简单、文档清晰。如果您对于如何做好开源项目有兴趣,那么可以从了解 StatCVS 中学到许多东西。
- 您可以参阅本文在 developerWorks 全球站点上的 英文原文。
- 获得 StatCVS 的最新发行版。请务必参阅 discussion of branch support 和 discussion of Subversion support。最后,获得 latest StatCVS release 的源代码。
- Jikes 是 Java 程序的一个快速的开源编译器。Jikes 的 Web 站点中还包括 instructions on how to access its CVS repository。
- 学习更多有关 JFreeChart 的内容,它是 StatCVS 使用的图形库。
- 请下载 CVS 的最新发行版。其中还有大量的 文档,CVS 邮件列表 上的一些高手可能对您很有帮助。
- 不要错过这个介绍 CVS client and the CVS server 用法的教程(developerWorks,2003 年 7 月)。
- 还应该参阅以下这篇文章,它介绍了 using Eclipse with CVS and Ant(developerWorks,2003 年 3 月)。
- Open Source Development with CVS, Third Edition(Paraglyph Press,2003 年)是一个对所有 CVS 特性都有用的指南。可以用 PDF format 免费得到它。
- Ruby 是一个解释型脚本语言,可以进行迅速而容易的面向对象编程。它有许多处理文本文件和进行系统管理任务的特性。它简单、直接、可扩展、可移植,还有友好的、活跃的 邮件列表。
- 在 RubyForge 上可以找到数百个开源的 Ruby 项目,其中包括一些有助于 Java 开发的项目。例如,Ruby JDWP 是创建 Java Debug Wire Protocol 客户机的 Ruby 实现的一个尝试。
- Michael Squillace 和 Barry Feigenbaum 在他们的文章 Take a shine to JRuby(developerWorks,2004 年 9 月)中讨论了 Ruby 与 Java 代码的交互。
- ViewCVS 提供了 CVS 储存库的只读 HTTP 界面。它会显示文件版本之间的差异,显示分支和标志,还支持语法着色,使代码更易阅读。
- JavaNCSS 计数 Java 程序中的代码行数。它能提供正确的测量,因为它会跳过注释和空白行。
- JUnit 框架自动运行单元测试。它提供了良好的 GUI ,当所有测试通过时显示绿色进度条。这使得“如果条是绿的,代码就是干净的”这句话用得越来越多。而且 developerWorks 还有一篇关于 用 Jython 构建 JUnit 测试包 的文章。
- Apache Ant 是一个基于 Java 编程语言的构建工具,developerWorks 上有许多关于 Ant 的文章和教程,其中包括:
- 让编译和测试过程自动化(2001 年 8 月)
- Extending Ant to support interactive builds(2001 年 11 月)
- Apache Ant 101: Make Java builds a snap(2003 年 12 月)
- Maven 是为 Java 程序设计的项目管理和项目范围的工具。它定义了标准的项目描述模型,可以自动执行许多标准的项目任务。
- 请务必参阅 StatCVS-XML plug-in for Maven 的文档。
- Charles Chan 写了以下这篇有趣的文章,描述了 项目管理:Maven 让事情变得简单(developerWorks,2003 年 4 月)。
- PMD 是一个 Java 源代码的静态源代码分析工具,可以找出没有使用的变量、空的 catch 块、没有必要的对象创建,等等。
- Elliotte Harold 对 PMD 的世界进行了思考,并撰写了这篇文章,解释如何 用 PMD 铲除 bug(developerWorks,2005 年 1 月)。
Tom Copeland 从 TRS-80 Model III 上开始编程,但是对这项技能的需求已经衰退了,所以他现在主要编写 Ruby 和 Java 代码。他参与过各种开源项目,其中包括 PMD 和 GForge,他还帮助管理 RubyForge,这是一个开源的 Ruby 项目储存库。他和妻子 Alina 有四个孩子(Maria、Tommy、Anna 和 Sarah),他们一起住在北佛吉尼亚。