作为管理工具的持续集成
September 3rd, 2010
有一个敏捷推行人,给她的团队设立了一个规则:每个函数不要超过30行。一开始,领导们都说,很好,很有道理。可是真的做起来,就发现遗留代码里有这样那样的特殊情况。紧跟着,开发人员也有了抱怨:我这里写32行又有什么损害呢?为什么一定要那么死板呢?于是,一个又一个的口子被打开。当然,你可以想象,有了越来越多的口子以后,“改善代码质量”也就成了纯理念──跟没有规则之前没什么区别。
我打算怎么做这件事呢?
- 把持续集成搭起来,只做编译。编译失败就红。红了就不能转测试,红了就必须马上修复,红了就是在阻塞整个团队的工作,红了就是最高优先级。让领导开始盯住持续集成。破坏构建就是和整个团队作对。
- 大家讨论一下,30行是不是一个合适的门限?如果不是,35行?40行?50行?行。我们就把门限定在50行。把静态检查放进持续集成。旧的代码我们既往不咎。就算现在有100个函数超过50行吧,没关系,我们容忍它。但是如果出现第101个长函数,就会让持续集成变红,要马上修复。
- 每次构建失败就是一个教育和学习的机会。一个人第一次写出长函数,我跟他一起重构;第二次写出长函数,我要看着他用我教的方法重构;第三次再写出长函数,那就要让领导来关心一下了。没有能力可以学,有了能力还破坏规则,说不过去了吧?
- 现在大家都学到怎么写更短小的函数了。偷偷把门限降低到45行试试?又多出来10个长函数。拉上几个开发者,我们来搞一次代码优化活动,把这10个长函数解决掉。于是大家又学到了更多的重构技巧。于是45行的门限变成了持续集成的要求。
- 两周搞一次代码优化学习会,降一次门限值。两个月以后,30行的标准就放在了持续集成里。如果有时间就去重构以前遗留的长函数,如果没时间就留着吧,至少大家已经不会写出新的长函数了。
先讲道理,再定规则,然后帮所有人提升能力以遵守规则,随着能力的提升逐渐拉高规则。30行的规则落实不下去?我就不信了。
把持续集成作为团队规则的自动、可视执行者,于是敏捷推行人就不必扮演那个凶恶的执法者,只需专心帮人排疑解难。持续集成把违规行为变成一个人与整个团队的对立,而不是一个人与另一个人的对立。
持续集成铁的纪律是怎样炼成的
June 29th, 2010
持续集成问题说到底是人的问题
有一种常见的观点认为:持续集成是一系列技术问题;只要安装配置了适当的持续集成工具,解决了某些构建、测试自动化的技术问题,持续集成建设就能顺利开展。但实际上,持续集成建设中很少出现高难度的、超出团队本身能力范围的技术问题,涉及的工具也大多通用。持续集成建设中遭遇的一些典型难题,归根结底都不是技术问题,而是人的问题:
- 构建失败率高:背后的原因是开发人员质量意识不足,习惯把质量保证的责任全部丢给测试人员
- 构建修复难:背后的原因是开发人员在本地开发机无法重复构建过程,难以定位问题
- 在失败构建上继续提交代码:背后的原因是构建结果不够公开、受重视不足
持续集成建设就是提升团队质量能力的过程
建设一个运转良好的持续集成体系的过程,就是在培养每个团队成员重视质量的意识,就是在帮助团队发现交付“最后一英里”潜藏的问题、并督促团队解决这些问题。为了保持项目的健康,需要整个团队的努力:
- 加强对质量的关注,代码经过必要的自检再提交
- 制定简明严格的提交纪律,构建失败及时修复
- 用构建监视器显示持续集成状态,使项目健康情况公开可视
- 为开发人员提供本地构建能力,以方便自检和问题定位
《持续集成建设》引言
June 24th, 2010
软件开发的最后一英里
在任何软件开发过程中都有一个重要的部分:通过某种构建(build)流程,将已经编写好的源代码变成可用、能为客户创造价值的软件。尽管知道构建的重要性,但是我们仍然会经常因为构建中的各种问题而惊讶不已。曾有多少次,在所有人都认为“开发已经完成”之后,我们还要经历漫长而痛苦的编译、打包、联调、测试、上线过程?在代码都已经写好之后,我们还曾付出了多少个通宵的代价让软件真正可用?
编写源代码不是软件开发的全部。从源代码构建出可用的软件,这个过程也被称为“软件开发的最后一英里”:胜利似乎就在眼前,但各种潜藏的危机可能这段短短的路程变得艰难万分。
持续集成就是构建过程
构建之所以如此困难,是因为在绝大多数软件组织中,构建过程有以下几个特点:
- 它是一个神秘的、不可见的、只(模糊地)存在于少数人大脑中的过程
- 它是一个需要人工操作的、耗时费力的、容易出错的过程
- 它是一个偶尔为之的、缺乏练习的、充满未知风险的过程
为了减少“最后一英里”的浪费,让艰险的最后一英里成为坦途,我们需要将构建过程明晰化、自动化、频繁化。持续集成就是一个将构建过程明晰化、自动化、频繁化的实践。通过使用软件工具来实现自动化的构建过程、展示构建结果,原本虚无的构建过程就成为了一个实际存在的、可以重复进行的、可以被有效管理的实体。从这个意义上来说,持续集成就是构建过程本身:只有以持续集成的形式呈现的那部分构建过程,才是确定并可靠的;“最后一英里”中尚未被纳入持续集成的部分,仍然是不确定和有风险的。
配置分布式的CruiseControl
June 7th, 2010
这个文档 描述得不是很清楚,因此记录一遍。首先需要同时下载 src发布包 和 bin发布包 。
解开src发布包,在其中build distributed插件,然后把contrib目录copy到bin发布包解压后的目录:修改$CC_BIN/cruisecontrol.sh,在其中包含distributed插件的classpath:cd $CC_SRC/contrib/distributed ant cd $CC_BIN cp -r $CC_SRC/contrib ./contrib
在$CC_BIN/config.xml中指定需要分布的工程:... ... CCDIST=$CCDIR/contrib/distributed CCDIST_BUILDER=$CCDIST/dist/builder/ CCDIST_CORE=$CCDIST/dist/core/ CCDIST_JINICORE=$CCDIST/jini-core/ CCDIST_JINILIBDL=$CCDIST/jini-lib-dl/jsk-dl.jar CCDIST_CONF=$CCDIST/conf EXEC="$JAVA_HOME/bin/java $CC_OPTS \ -Djavax.management.builder.initial=mx4j.server.MX4JMBeanServerBuilder \ -Djava.security.policy=$CCDIST_CONF/insecure.policy \ -Dcc.library.dir=$LIBDIR -Djetty.logs=$JETTY_LOGS -jar \ $LAUNCHER -lib $JAVA_HOME/lib/tools.jar \ -lib $CCDIST_BUILDER:$CCDIST_CORE:$CCDIST_JINICORE:$CCDIST_JINILIBDL:$CCDIST_CONF \ $@ -jmxport 8000 -webport 8080 -rmiport 1099" echo $EXEC $EXEC & echo $! > cc.pid
打开Lookup server:<plugin name="distributed" classname="net.sourceforge.cruisecontrol.builders.DistributedMasterBuilder"/> ... ... <distributed> <ant antscript="/usr/bin/ant" antworkingdir="/path/to/my/project" /> </distributed>
cd $CC_BIN/contrib/distributed/dist/lookup ant
然后,把cc_agent.zip拷到Agent机器上,修改conf/agent.properties配置,ant启动,就好了。
(郁闷地搞了一下午的心得是:不要尝试在Windows上做任何严肃的开发工作。Stupid Windows.)
《持续集成》第二版译出
April 18th, 2010
《持续集成》第二版的中译本 。感谢雷镇的奉献。
如是我闻,一开始,我将已集成的源代码复制一份到本地计算机。这可以通过从源码管理系统的 mainline 上 check out 一份源代码做到。现在我拿到了工作拷贝,接下来需要做一些事情来完成任务。这包括修改产品代码和添加修改自动化测试。
一旦完成了修改,我就会在自己的计算机上启动一个自动化 build。
当我 build 成功后,我就可以考虑将改动提交到源码仓库。但麻烦的情况在于别人可能已经在我之前修改过 mainline。这时我需要首先把别人的修改更新到我的工作拷贝中,再重新做 build。如果别人的代码和我的有冲突,就会在编译或测试的过程中引起错误。我有责任改正这些问题,并重复这一过程,直到我的工作拷贝能通过 build 并和 mainline 的代码同步。
一旦我本地的代码能通过 build,并和 mainline 同步,我就可以把我的修改提交到源码仓库。
然而,提交完代码不表示就完事大吉了。我们还要做一遍集成 build,这次在集成计算机上并要基于 mainline 的代码。只有这次 build 成功了,我的修改才算告一段落。
持续集成不是敏捷的基础
April 10th, 2010
它就是敏捷本身。或者说得更大一点,持续集成就是软件交付本身。
持续集成反映交付形态。这句话实际上是肖鹏说的。实际上是肖鹏很久前说过然后李丰用了很长时间理解了然后再说出来然后我听了一耳朵然后又用了很长时间理解然后再说出来的。持续集成是什么样,不是由持续集成负责人设计的,而是由软件交付形态决定的。
所以持续集成反映交付团队的一切现状和问题。分层分级的持续集成,说明团队与团队之间的沟通成本高。层级之间以二进制还是源代码集成,代表团队之间的依赖层面和交付形式。测试用例失败时构建不失败,说明交付团队没有可依赖的质量标准。构建的频率,代表团队关注质量的频率。每日构建,说明质量没有内建在生产流程中,全靠“守门人”把关。
没有持续集成,说明交付流程是混乱不清晰随机的。
(推论:关于“敏捷是不是必须有持续集成”的讨论再也不想听到,因为持续集成不是敏捷的组成部分,它就是敏捷本身。连交付流程都没有还提什么敏不敏捷的,没有意思。)
《持续集成》第二版召唤译者
March 17th, 2010
Martin Fowler的文章 ,现在网上流行的那个第一版是我好多年以前翻译的。内容已经太旧了,并且我的翻译太差了。
我在译言上建了一个 翻译文档 。有兴趣的同志们赶快把它搞了吧。
大团队的持续集成建设路径
November 29th, 2009
- 状态:有缺陷的代码持续产出,软件最基本的功能无法保证
- 建立“缺陷发生时自动停线”的自働化机制
- 实施可视化管理:停线立即告警,作为最高优先级处理
- 解决基础质量问题:消除环境不稳定性,消除伪随机质量问题
- 提升团队基础能力:
- 采用令牌制提交,明确责任人,谁破坏谁修复
- 设立专人负责监控持续集成状态
- 对于不能快速解决的问题,预备有效的修改撤销机制,快速恢复生产,减少破坏的影响范围
- 状态:能得到可用基线,提交失败频率高
- 分层分级的配置管理和验证体系
- 验证提前:提交代码之前的准入构建
- 更严格的令牌制:以成功的准入构建报告申请令牌
- 状态:主线稳定可用,分支合入主线困难
- 标准化的分支持续集成环境
- 分支持续集成状态巡检,及时发现问题提供支持
- 帮助分支组培养持续集成专门人才
- 状态:持续集成稳定可用,需要持续提升
- 配置管理下的持续集成,解决了改进措施在大团队中复制的难题
- 迭代式改善的持续集成
- 从“贪多求快”、“一步到位”的建设思路转变,确立“小步走稳”的持续改进路线,将PDCA方法应用于大团队持续集成建设
自动化 vs. 自働化
November 29th, 2009
什么是自动化?是让生产线自动运行起来的技术吗?
那顶多也就是个传送带技术。
《图解丰田生产方式》 说,自働化,是在出现问题时让生产线自动停止。
自动停线的自働化,才能在现场、现物根据现实找到问题的根因,才能从源头上消除质量问题。只管自动运行不管自动停线的自动化,既无助于发现根因,又不能及时阻止不合格产品的生产,于是生产线末端的检验人员照样不能省。
建立真正的自働化,首先就要改变这个认识。全员意识到,自働化就意味着一旦缺陷发生立即停线,作为最高优先级处理。有了这样的觉悟才能继续前进。
意识之外,自働化的三个必要条件:
- 可视化。停线的同时以最直观的方式让所有人警觉,并作为最高优先级处理。
- 质量基础。如果设备经常发生异常故障,如果产品经常出现不明原因的质量问题,频繁的自动停线可能直接把生产线打倒。
- 能力基础。自动停线之后,团队是否具备快速发现问题、快速恢复生产的能力。
持续不能集成
November 1st, 2009
持续集成只是信息源。持续集成的检验是在代码提交之后而非之前进行的,因此持续集成的作用只是使项目健康情况可视化。并且这种可视化必须建立在构建经常成功的前提下。因为软件本身的复杂性决定了只有“是否达到质量要求”能够被简单度量,而“达到(或不达到)质量要求的程度”无法被简单度量。所以,如果构建经常失败,持续集成所能提供的信息就只剩“项目一直不健康”──这个信息的价值很小,如果不是完全没有价值的话。
让持续集成保持经常成功,必须规范三件事:
- 提交代码之前必须更新
- 提交代码之前必须进行本地验证
- 线上构建失败时不得进行任何提交(或更新)
如果做不到这三件事,持续集成就可能降格化为持续不能集成:你知道项目有问题,但不知道问题出在哪儿,也不知道该如何解决这些问题。
为了避免这种降格化,在持续集成到位之后,需要用更多的手段确保三点规范得以落实:
- 代码库和持续集成分级
- 责任逐级下压
- 建立提交前本地构建基础设施
要言之:持续不能集成会使持续集成的价值降低到约等于0(甚至低于0)。要避免持续不能集成的发生,第一要严格规范,第二要提供技术手段使规范能够被落实。



