今年7月份中下旬,笔者见过一个号称“资深开发者”的哥们(据说编程有十来年了),笔者问他:“你们平时用的持续集成工具都有哪些?”这哥们回答:“那些都是骗客户的,其实我们什么都不用,还是各干各的,然后让一个人收集代码,进行测试。那些大公司,比如XX数码什么的,CI用的也极差”。笔者于是愕然。可见在实际软件开发工作中,持续集成远未得到普及,其中的原因无非是:
l 程序员习惯了原有手工作坊开发的方式
l 没有真正体验过持续集成的好处
l 持续集成涉及的知识点、工具太多,学习比较困难,造成CI人才的严重缺乏
l 很多中小软件公司的老板不理解开发质量的重要性,认为持续集成是重复成本,不愿意花钱培养或雇用CI人才
其实,如果不吃几次亏,国内的软件公司很少会去主动实施CI。比如笔者一个朋友所在公司,以前软件开发连源代码备份都没有,产品被客户投诉N多回,结果以前的代码都找不到了,只好重新开发。后来不得已上了SVN、CVS,好歹可以备份源代码并且回溯版本了。最关键的是:没见到因为加了版本控制工作就多花了钱和时间!CI其实也是同样的道理。
以笔者有限的经验看,一旦你真的建立起自动化的持续集成环境,到开发软件的时候,就可以把主要精力放在产品设计和开发本身了,反而会节约不少精力。笔者作为一个门外汉,从知道有持续集成到能搭建出一个简单的、自动化的持续集成环境,实际花了一个多月的自学时间。对笔者来说,学习持续集成其实是件很头疼、很困难的事情,但这很有意义。对于软件开发专业人士来说,我想这个学习过程应该会更短、更简单吧。后面还有9篇学习笔记,待整理好后再逐次上传。
(一)为什么需要持续集成
“敏捷编程”(Agile Programming)的思想若干年前就已经提出,并在业界获得广泛支持。从团队日常开发的角度来看,Agile Programming就是:
"Short Cycles that are test-driven and feedback-driven, yielding constant improvement."
其中,
l short cycle是核心。整个软件开发活动应该被划分成一系列短的迭代过程,每个迭代完成一定数目的功能。迭代周期应该尽量短。
l 更为重要的是,迭代应该是由测试(TDD)和反馈驱动的。只有这样,我们才能为持续改进打下一个良好基础。
如何实现short cycle,就不得不用到持续集成(持续集成出现的时间早于敏捷编程)。一方面,良好的持续集成(集成时间频率可以根据项目需要自主决定)完全可以自动化地实现short cycle;另一方面,利用相关插件,持续集成可以实现对TDD的支持。可以说,持续集成是敏捷编程的重要实践基础,没有持续集成,所谓的敏捷编程便缺了最重要的一条腿,而基本不可能实现。
国内外比较有名的互联网、IT公司在开发中几乎全部实现了持续集成,比如淘宝、facebook、微软等。
(二)持续集成定义
那么,持续集成究竟是什么呢?根据敏捷大师Martin Fowler的定义,
“持续集成是一种软件开发实践。在持续集成中,团队成员频繁集成他们的工作成果,一般每人每天至少集成一次,也可以多次。每次集成会经过自动构建(包括自动测试)的检验,以尽快发现集成错误。许多团队发现这种方法可以显著减少集成引起的问题,并可以加快团队合作软件开发的速度。这篇文章简要介绍了持续集成的技巧和它最新的应用。”
这个定义本身不难理解,关键是要领会到:持续集成是自动化、每天都要进行的过程。如果是手工去做相关工作,估计会累死人的。
(三)持续集成过程
持续集成工作的阶段也比较明确,主要有两个大的阶段:持续集成准备阶段、持续集成使用阶段。
1、持续集成准备阶段的工作主要包括:
1.1. 通过版本控制/配置管理工具(比如SVN或GIT)建立源代码仓库
1.2. 使用构建工具,建立相关配置文件(比如maven的POM文件)
1.3. 通过CI服务器(比如jenkins)建立一个job,将版本控制仓库和构建工具有机整合起来,并设置构建触发条件
2、持续集成使用阶段的主要步骤包括:
2.1. 程序员从源代码仓库下载最新程序
2.2. 程序员编写代码、测试用例,并提交更新结果给版本控制仓库
2.3. CI服务器根据触发条件,从版本控制仓库提取最新代码,交给构建工具的工作空间
2.4. 构建工具对代码进行编译、测试,并进行打包。如有必要,实现产品部署、发布
2.5. 通过构建工具与版本控制工具的配合,实现产品版本控制与管理
2.6. 建立、管理项目开发的工作网站
从中,我们可以看到,持续集成涉及到的主要工具类别包括:
l 版本控制工具:实现源代码管理、版本控制
l 构建工具:实现自动化地编译、测试、部署等,这是持续集成的核心工具
l CI服务器:有机整合版本控制和构建工作,实现自动化持续集成
(四)持续集成的好处
Steve McConnell在《Code Complete》里提到,持续集成(书中使用Incremental Integration的术语)有以下几点好处:
l 易于定位错误。也就是当你的持续集成失败了,说明你新加的代码或者修改的代码引起了错误,这样你很容易的就可以知道到底是谁犯了错误,可以找谁来讨论。
l 及早在项目里取得系统级的成果。因为代码已经被集成起来了,所以即使整个系统还不是那么可用,但至少你和你的团队都已经可以看到它已经在那了。
l 改善对进度的控制。这点非常明显,如果每天都在集成,当然每天都可以看到哪些功能可以使用,哪些功能还没有实现。如果你是程序员,你不用在汇报任务的时候说我完成了多少百分比而烦恼,而如果你是项目经理的话,那么你也不再烦恼程序员说完成了编码的50%到底是个什么概念。
l 改善客户关系。理由同上。
l 更加充分地测试系统中的各个单元。这也是我们常讲的Daily Build与Smoke Test相结合带来的绝大好处。
l 能在更短的时间里建造整个系统。这点恐怕要你实施以后才能得出结论。就我们而言,持续集成并没有为每个项目都缩短时间,但却比没有实施时,项目更加可控,也更加有保证。
随着时间的推移,持续集成带来的更多好处,也逐渐被认识到了,比如说:
l 有助于项目的开发数据的收集。比如说,项目代码量的变化,经常出错的Tests,经常出错的source code,等等。
l 与其它工具结合的持续代码质量改进。如与CheckStyle, PMD, FindBugs, Fxcop等等等等的结合。
l 与测试工具或者框架结合的持续测试。如与xUnit,SilkTest, LoadRunner等等的结合。
l 便于Code Review。在每个build里,我们都可以知道与前一个build之间有什么改动,然后针对这些改动,我们就可以实施Code Review了。
便于开发流程的管理。比如说,要把一个开发的build提交给测试组作测试,测完满意了,再提交到发布组去发布。