【IT168 技术文档】
前言
持续集成是极限编程十二实践之一(1999年Kent Beck编写的《解析极限编程》),最初被使用极限编程方法的开发人员所推捧,并在过去的几年中得到广泛应用,成为业界广为人知的软件开发实践。该实践用于解决软件开发过程中一个具体且重要的问题,即“确保当某个开发人员完成新的功能或修改代码后,整个软件仍旧能正常工作。”
然而,持续集成并非像大多数人想像的那样,首次部署好持续集成环境后就大功告成,一劳永逸了。恰恰相反,它与你项目中的其它产品代码一样,需要改进与重构,否则,就会使你进入一种“持续闹心”的状态,甚至可能让你觉得这件事根本不应该做,如何解决这一问题呢?对“持续集成”应用“Retrospective”和“重构”。本文将结合Cruise团队一年多的实际历程,讲述持续集成实践在软件开发过程中的演进。
友情提示:请读者在阅读本文时,注重文中所述的思考过程与“持续集成”的重构方式,而非产品本身。
基本持续集成——万里长征第一步
实际问题:我们需要一个持续集成环境
为什么要做持续集成不在本文讨论之内。
理论基础
持续集成基于这样一个假设:如果两次代码集成的间隔时间越长,最终集成时痛苦的经历就会越多。而其目标有两个:一是“频繁集成”,二是“反映代码质量”。为了做到“ 频繁集成”,就要求任何开发人员在每次向中央代码库提交代码时,就将所有代码进行编译,打包,部署,以确保能够产生交付物。然而,“频繁集成”仅仅证明了每次提交是否可以得到交付物,而我们真正需要知道的是“这个交付物的质量如何”。如果交付物有问题,引起问题的代码则要么被回滚,要么被修正。当然,这样的任务也可以通过手工来完成,但手工工作的特点就是易出错且耗时,所以需要将其自动化。为了做好“持续集成实践”,写一个自动化构建脚本来自动构建并运行一些自动化测试套件还是必要的。这种传统的持续集成方式常被固化于开发环节,即:开发人员安装一个专门的持续集成服务器来自动化运行这些单元测试,然后通过各种各样自动生成的测试结果分析代码的质量,这也是CruiseControl诞生的原因。
解决方案
最初,我们的代码并不多,自动化脚本比较简单,在一台机器上运行所有的测试也仅需要几分钟,该构建套件的运行顺序是:CheckStyle -> Compile -> UnitTest -> FunctionTest -> Report。示意如下:
<project name="Cruise" default="all" basedir=".">
<target name="all" depends="checkStyle, Compile, UnitTest,FunctionTest, Report"/>
<target name="checkStyle">
....
</target>
<target name="Compile" >
...
</target>
<target name="UnitTest" depends="Compile">
...
</target>
<target name="FunctionTest" depends="Compile">
...
</target>
<target name="Report" depends="FunctionTest">
...
</target>
</project>
这也是大部分软件团队进行持续集成的起点。
目前,有很多种持续集成工具,其中不乏开源产品,如CruiseControl家族。项目伊始,我们使用CruiseControl建立了自己的持续集成服务器,整个项目的持续集成基础结构如图所示:

图1 基础持续集成模式
注:得到快速反馈是开发好产品的关键。因此,我们自己就做了Cruise的第一个用户,首先解决自己的持续集成需求。项目开始后仅几周,我们的产品Cruise已经基本满足自身团队持续集成的需求,因此,我们就将CruiseControl替换成Cruise,但持续集成基本结构并没有变化。