敏捷质疑: 持续集成
 
2009-04-07 作者:chelsea 来源:chelsea的blog
 

Q: 我的产品是电信级的设备, 几百人分成几十个项目组在开发, 各个项目组进度不统一, 如何集成?

A: 你要做的其实跟技术无关, 更多的是管理工作, 就是制定你的产品级别的集成策略.

这涉及到需求分析和发布计划(依赖管理, 价值和风险识别), 开发方法(自顶向下还是自底向上, 横向分层还是垂直特性), 集成粒度划分(完整特性的集成还是API的集成), 集成间隔计划, 版本控制策略, 还有尤为重要的集成测试/验证策略, 甚至你的决心.

任何集成策略在执行过程中都会遇到困难, 如迟迟得不到能够成功集成的版本. 这时你要找出原因, 并有权力或相应措施要求整个几百人的团队停下来, 做为第一优先级的任务去修复. 并让整个团队清楚进度停滞造成的损失. 这么做的意图是强调集成的重要性, 因此每个项目组在开发时, 都会优先考虑与其它部分的集成, 从而促进更好的沟通和反馈, 减少集成失败的次数, 缩小集成的间隔.

这在某种程度上会给你的设计带来正面影响. 比如为了更容易的集成, 模块间使用松耦合的协议/消息, 或者标准的数据格式来代替紧耦合的API调用. 定义可扩展的接口来隔离实现修改的影响...

用集成来驱动你的开发进程.

Q: 项目组在各自的分支上工作, 每次光合并版本就好几天, 怎么做持续集成?

A: 改变分支策略, 使用同一分支, 随时集成

Q: 构建一次, 包括编译链接, 测试, 需要几十个小时, 怎么集成?

A: 其实就是一速度的问题, 有很多潜在的优化措施

优化源文件依赖关系, 该调整设计就调整设计

优化构建脚本

优化测试用例, 能够共用一套测试环境的就一起跑

分类测试用例, 优先运行价值大速度快的用例; 价值小又耗时的测试运行间隔可以放大

分布式构建, 使用诸如 Cruise 或 IncrediBuild 之类的软件.

使用高性能主机

Q: 硬件依赖, 尤其是嵌入式, 怎么集成?

A: 理想的情况是: 产品代码运行在真实的嵌入式设备上, 测试结果可以报告给运行在 PC 上的 CI 工具

我们很多项目早已做到这一点, 方法也不难:

通过设备支持的方式(如FTP)将编译后的代码上传到设备

向设备发出命令加载新代码(TCP或串口)

运行测试用例: 可以运行在 PC 上通过网络(TCP或串口)与设备交互以断言其行为, 或直接运行在设备里, 然后将测试运行结果通过网络取回

在硬件不具备的情况下, 使用仿真模式设备

Q: 构建结束前有新的commit, 是否要等待上次构建结束才进行新的构建?

A: 取决于你用的CI工具, 大部分是这样的. 但在支持分布式构建的CI工具中, 可以使用另外一台机器来立刻运行新的构建, 这是一种可能的特性, 如果你知道哪个工具实现了它, 请告诉我.

对这种特性的争论在于一旦构建失败, 将不容易分清是谁的提交造成的, 但两个原因这个假设不成立:

大多 CI 工具基于轮询的机制, 总会发生一次构建包含多次提交的情况

在提交纪律严明, 有责任心, 视 CI 为第一要务的敏捷团队, 提交前都会在本地运行构建, CI server 上构建失败的几率不高.

Q: 我们的产品需要支持多种操作系统, CI 怎么做?

A: 多数 CI 服务器都能运行在多种操作系统上, 差别只在于是分别管理(单机构建)还是统一管理(分布式构建).

Q: 是否团队每个人都需要在自己的开发机器上运行 CI 集成环境?

A: 不需要运行 CI 环境, 只需要运行 CI 环境运行的构建脚本. 本地构建使用与 CI 相同的构建脚本将减少 CI 失败的概率, 参见<<Publish with a Publisher>>.

Q: 是否团队每个人都需要掌握 CI 知识?

A: CI 工具本身其实很简单, 更加重要的是整个团队的集成策略.

Q: 如果测试先行, 那集成环境中如何处理预先写的肯定会失败的测试?

A: 测试先行的另一个约束是步子尽可能小, 基本上你不应该在让测试通过前提交它.

Q: 可我们的测试人员提前写的自动化集成测试, 一开始是失败的, 只是随着开发的进行, 才逐渐通过的. 这怎么办?

A: 这基本上是你的测试管理策略, 一种简单的方案就是分开存放注定失败的测试和已经实现对应功能的测试, 随着特性的不断完工, 逐渐的移动测试.

自动化测试工具支持使用标记来控制运行时忽略/跳过某些测试.

Q: CI的愿景是好的, 但我们这里根本不可能, 我们的产品需要复杂的运行环境, 运行时需要人工干预, 怎么测?

A: 我不清楚你说的复杂具体是怎么复杂, 人工干预是怎么样的干预, 但这确实是个常见的, 有无数种真实情形的问题. 通常我们会具体问题具体分析, 但有几个通用的原则:

设计, 分离核心业务逻辑与外部界面, 争取让业务逻辑环境无关

自动化, 寻找合适的自动化测试工具, 必要时自己开发

尽可能搭建真实的运行环境

集成在很大程度上依赖你的测试策略和自动化程度.

Q: 你说集成依赖于测试策略和自动化程度, 是否不运行测试的集成不能算集成?

A: 任何一点集成方面的努力都是值得肯定的, 哪怕即使只是持续编译. 事实上在那些不得不常年维护大型遗留系统的公司, 即使只是持续编译, 保证每天能够编译通过, 也已经具有很大的价值了. 当然, 我们需要尽可能的集成更多的自动化检验工作.

CI 社区最近出现了一个出于商业目的攻击, 1, 2, 基调就是对持续编译这种 CI 的坏味道/反模式的鄙视. 其实没人认为 持续集成的核心是持续编译, 我们尊重任何集成方面的努力, 凡事总有第一步.

Q: 集成与测试, 是否经过集成的就是可用的?

A: 取决于你如何定义可用. 信心来自于全面的测试.

Q: 听说 CI 环境配置挺麻烦, 有没有简单一点的工具?

A: 软件业又不是电信, 其竞争激烈残酷, 如果一个工具配置起来麻烦, 早就有更简单的代替它了. 下载试用, 再配合搜索引擎, 一天之内你肯定能找到合适自己的工具. 如果没有, 那么是一个机会, 你可以创造一个更好的.

Q: 对 CI 工具本身, 我还是想不清楚, 它怎么知道去哪里取代码? 怎么知道有没有更新? 怎么取代码? 怎么编译? 怎么知道跑什么测试? 怎么知道成功失败?

A: 版本控制系统的客户端都是可用的工具, 也都提供了公开德协议或交互接口, 这都没问题. 至于编译和测试, CI 工具确实不必知道, 尽管很多工具都能按照某种约定或自动识别你的源代码和测试. 事实上, CI 工具只是忠实的运行你配置的行为, 通常是某个你编写的脚本, 因此是由你来指定如何编译和如何测试. 至于成功或失败, CI 遵循操作系统的惯例, 返回值0成功, 非0失败.

Q: 我们的版本控制系统是 ClearCase, 你们的 CI 工具支持吗?

A: 不支持, 换 Subversion 吧

ClearCase 慢

ClearCase 贵

ClearCase 难用

ClearCase 太悲观, 锁的你没脾气

Q: 怎样才能减少 CI 构建失败的几率?

A: 这其实是个最佳实践的问题, 比如对于需要在多个操作系统上运行的产品, 项目组内不同的开发者尽可能使用不同的目标平台开发,这样可以在本地构建时捕捉到平台类的错误. 关于CI工具CC的最佳实践, 可参考http://blog.csdn.net/gongflow

Q: 我们在遗留项目上工作, 面临前面提到的所有问题: 编译速度/环境依赖/多个项目组进度依赖/分支合并/甚至版本系统用的都是ClearCase, 总感觉你说的很虚, 未必就能给我们的现状带来多大改善

A: 这是投入产出比的问题(你的项目还要维护多久, 能带来多大利润, 花费大力气去改善值不值得), 也是价值观的问题(是放任现状,直到它自然灭亡, 还是逐步改善, 看看最后能改到什么程度). 我是建议试试, 从最简单的,对环境要求不高的开始做起, 慢慢扩大范围. 所有的软件都会被废弃, 人也会死亡, 意义只在于不断的尝试, 看看会发生什么. 如果明知不值得, 这样也就算了, 留点时间去尝试别的事情.


火龙果软件/UML软件工程组织致力于提高您的软件工程实践能力,我们不断地吸取业界的宝贵经验,向您提供经过数百家企业验证的有效的工程技术实践经验,同时关注最新的理论进展,帮助您“领跑您所在行业的软件世界”。
资源网站: UML软件工程组织