作为管理工具的持续集成

September 3rd, 2010

有一个敏捷推行人,给她的团队设立了一个规则:每个函数不要超过30行。一开始,领导们都说,很好,很有道理。可是真的做起来,就发现遗留代码里有这样那样的特殊情况。紧跟着,开发人员也有了抱怨:我这里写32行又有什么损害呢?为什么一定要那么死板呢?于是,一个又一个的口子被打开。当然,你可以想象,有了越来越多的口子以后,“改善代码质量”也就成了纯理念──跟没有规则之前没什么区别。

我打算怎么做这件事呢?

  • 把持续集成搭起来,只做编译。编译失败就红。红了就不能转测试,红了就必须马上修复,红了就是在阻塞整个团队的工作,红了就是最高优先级。让领导开始盯住持续集成。破坏构建就是和整个团队作对。
  • 大家讨论一下,30行是不是一个合适的门限?如果不是,35行?40行?50行?行。我们就把门限定在50行。把静态检查放进持续集成。旧的代码我们既往不咎。就算现在有100个函数超过50行吧,没关系,我们容忍它。但是如果出现第101个长函数,就会让持续集成变红,要马上修复。
  • 每次构建失败就是一个教育和学习的机会。一个人第一次写出长函数,我跟他一起重构;第二次写出长函数,我要看着他用我教的方法重构;第三次再写出长函数,那就要让领导来关心一下了。没有能力可以学,有了能力还破坏规则,说不过去了吧?
  • 现在大家都学到怎么写更短小的函数了。偷偷把门限降低到45行试试?又多出来10个长函数。拉上几个开发者,我们来搞一次代码优化活动,把这10个长函数解决掉。于是大家又学到了更多的重构技巧。于是45行的门限变成了持续集成的要求。
  • 两周搞一次代码优化学习会,降一次门限值。两个月以后,30行的标准就放在了持续集成里。如果有时间就去重构以前遗留的长函数,如果没时间就留着吧,至少大家已经不会写出新的长函数了。

先讲道理,再定规则,然后帮所有人提升能力以遵守规则,随着能力的提升逐渐拉高规则。30行的规则落实不下去?我就不信了。

把持续集成作为团队规则的自动、可视执行者,于是敏捷推行人就不必扮演那个凶恶的执法者,只需专心帮人排疑解难。持续集成把违规行为变成一个人与整个团队的对立,而不是一个人与另一个人的对立。

在连续举办四届敏捷中国大会以后,ThoughtWorks将以“敏捷十年”为主题在今年10月份举办第五届敏捷中国大会,目前国际知名讲师如敏捷宣言创始人Martin Fowler和James Grenning、精益方法专家Mary Poppendieck和Tom Poppendieck,均确认参会并演讲。本次大会的亮点之一是组委会将采取开放、透明的方式,面向全球的敏捷实践者征集话题和招募讲师;大会的报名工作也已启动,现在报名享有多种优惠。

如果从2001年2月份敏捷宣言面世那天开始计算,敏捷已经走过了近10个年头。在这10年的发展过程中,敏捷的分支和外延不断扩大,比如Scrum、Crystal、XP精益,包括仅今年新出现的看板等均快速发展,在不同的行业和领域帮助企业提高生产效率。虽然敏捷在国内的实施并不如国外那么普及和先进,但是像华为、中兴等大型电信企业,如上海贝尔、赛门铁克等软件企业也已经开始了自己的实践。这次第五届敏捷中国大会的主题即是“敏捷十年”,希望通过回顾过去十年间软件开发行业发生的变化,敏捷的诞生和发展,“全面呈现敏捷方法在中国的推广历程和实施经验”。

如前所述,今年敏捷中国2010的亮点之一即是从“业务敏捷、实践与新技术、领导力与组织和敏捷工具”等方面,面向全球公开招募讲师和征集话题

只要您有过敏捷(开发)实践,或者深入思考过敏捷,或者持续关注过,或者有其他独到观点,都可以报名成为本届敏捷中国大会的讲师。此外,敏捷爱好者还可以通过提交自己感兴趣的话题参与到本届敏捷大会中。主办方将通过大会组委会,统一审核话题及备选讲师,通过公开、公正、透明的组织方式,鼓励全球敏捷爱好者积极参与,共同创建敏捷实践经验分享平台。近年来,国内越来越多的公司已不再仅仅是关注,而是开始有了更多的创新敏捷实践,在本次大会,我们将遴选超过20位讲师分享他们在应用敏捷实践过程中的经验和教训,通过实际案例与参会人员交流在各种典型的真实软件组织和项目中采用敏捷方法带来的实际效果。

曾经我认为,敏捷的各种实践,只要有了标准化的动作,加上一点点定制,加上PDCA/SDCA,就能做好。迈向敏捷之路,是可以唯一定义并且重复实施的。比如说持续集成,大师说 “在自己的计算机上启动一个自动化build”是重要的──我们把它叫做“本地构建”。做不好本地构建,提交构建失败率就会高,对持续集成的信心就会失去。这个问题,和它的解决方案,都是确定且可重复的。

可是这个团队让我吃惊了。他们一直没有真正意义上的本地构建。但他们真的相信持续集成──不仅仅是几个领导,是整个团队,真的相信:如果每天发现的小问题不能及时解决,那么到版本上线时一定会被客户骂得狗血淋头。他们不想被骂,他们也不想同一个战壕里的战友被骂,所以他们就把持续集成做好了。尽管没有真正意义上的本地构建,就靠着原始简单的代码评审,更认真的态度,他们就真的把持续集成做好了。

这个团队颠覆了一些正在我脑中渐渐成型的东西,让我想起了一些原本印象深刻但被渐渐遮掩起来的东西,比如敏捷宣言的第一条:个体与交互 重于 过程和工具。

面对巨大组织时强烈的无力感、无助感会让“敏捷推行人”们(包括我自己在内)不自觉地选择把自己的定位拔高──也许真是想帮助更多的人,也许只是想从残酷的现实中逃开,抑或两者兼而有之。但这些人不会做高层面的事情。于是离开低层面、离开具体事务的结果就是不知道该做什么,就是把敏捷推行简化为过程和工具的推行。

有一个敏捷推行人对我说,我负责几十个项目的改进,如果每次只到一个项目去做具体的事,对整体的帮助很小。我对她说,也许你救不了所有的鱼,但被你救的这一条鱼,它会在乎 ,它会得救。在反复思考如何拯救所有鱼的过程中,其实你什么也没有做,没有一条鱼真的得救。

敏捷的改变,最终是一个一个的改变。过程和工具会帮助你。但如果把敏捷简化成过程和工具,你就在一步步远离敏捷,因为你已经违背了敏捷宣言的第一条原则。

持续集成问题说到底是人的问题

有一种常见的观点认为:持续集成是一系列技术问题;只要安装配置了适当的持续集成工具,解决了某些构建、测试自动化的技术问题,持续集成建设就能顺利开展。但实际上,持续集成建设中很少出现高难度的、超出团队本身能力范围的技术问题,涉及的工具也大多通用。持续集成建设中遭遇的一些典型难题,归根结底都不是技术问题,而是人的问题:

  • 构建失败率高:背后的原因是开发人员质量意识不足,习惯把质量保证的责任全部丢给测试人员
  • 构建修复难:背后的原因是开发人员在本地开发机无法重复构建过程,难以定位问题
  • 在失败构建上继续提交代码:背后的原因是构建结果不够公开、受重视不足

持续集成建设就是提升团队质量能力的过程

建设一个运转良好的持续集成体系的过程,就是在培养每个团队成员重视质量的意识,就是在帮助团队发现交付“最后一英里”潜藏的问题、并督促团队解决这些问题。为了保持项目的健康,需要整个团队的努力:

  • 加强对质量的关注,代码经过必要的自检再提交
  • 制定简明严格的提交纪律,构建失败及时修复
  • 用构建监视器显示持续集成状态,使项目健康情况公开可视
  • 为开发人员提供本地构建能力,以方便自检和问题定位

软件开发的最后一英里

在任何软件开发过程中都有一个重要的部分:通过某种构建(build)流程,将已经编写好的源代码变成可用、能为客户创造价值的软件。尽管知道构建的重要性,但是我们仍然会经常因为构建中的各种问题而惊讶不已。曾有多少次,在所有人都认为“开发已经完成”之后,我们还要经历漫长而痛苦的编译、打包、联调、测试、上线过程?在代码都已经写好之后,我们还曾付出了多少个通宵的代价让软件真正可用?

编写源代码不是软件开发的全部。从源代码构建出可用的软件,这个过程也被称为“软件开发的最后一英里”:胜利似乎就在眼前,但各种潜藏的危机可能这段短短的路程变得艰难万分。

持续集成就是构建过程

构建之所以如此困难,是因为在绝大多数软件组织中,构建过程有以下几个特点:

  • 它是一个神秘的、不可见的、只(模糊地)存在于少数人大脑中的过程
  • 它是一个需要人工操作的、耗时费力的、容易出错的过程
  • 它是一个偶尔为之的、缺乏练习的、充满未知风险的过程

为了减少“最后一英里”的浪费,让艰险的最后一英里成为坦途,我们需要将构建过程明晰化、自动化、频繁化。持续集成就是一个将构建过程明晰化、自动化、频繁化的实践。通过使用软件工具来实现自动化的构建过程、展示构建结果,原本虚无的构建过程就成为了一个实际存在的、可以重复进行的、可以被有效管理的实体。从这个意义上来说,持续集成就是构建过程本身:只有以持续集成的形式呈现的那部分构建过程,才是确定并可靠的;“最后一英里”中尚未被纳入持续集成的部分,仍然是不确定和有风险的。

团队空间

June 18th, 2010

Martin Fowler说 ,一个好的团队空间,要有大面的墙作为 信息辐射器 ,团队要围着大桌坐以保持眼神接触,要有自然光线和看到外面景色的落地大窗。

ThoughtWorks北京的办公室,Martin Fowler认为是一个好的团队空间。

这个空间又如何?除了缺少自然光,也是个不错的团队空间。

一只土贼

June 13th, 2010

我承认一开始我认为 小熊 就是一只土贼。有次内部讲session的活动,别人的主题都是有模有样的理论结合实践,小熊搬把凳子往中间一坐,胶片也没有,开口第一句就是很土的话:

“其实搞客户就是将心比心。你想想他的利益是什么,帮他把事情搞定了,他就喜欢你了。”

好吧,确实是很有sense的实话。不过这种没有理论高度的话游沁说也就罢了,作为我司的咨询师用湖南塑料普通话这么讲出来,咋就觉得那么土呢?

广州 呆了一段时间之后我就发现这个小海龟基本上是故意装土,装得很土那么别人就觉得自己很洋于是就愿意跟他嘻嘻哈哈。处女座 在人际关系上的感觉就是特别敏感哈。而且他有两个特别的好处,第一很会 画画 ,第二对 浪费 极其敏感。我最喜欢和这种完美主义强迫症患者一起工作。

然后小熊就搞出了史上最华丽的故事墙。在他的感染下我也搞出了一个华丽的大屏幕CI监视器。并且开始用各种华丽的方式工作,虽然还不如他华丽哈。

今天小熊感到很兴奋,表示我们的工作很有意义,并且立下了要出名的目标。我觉得他可以出名。唯一的缺陷就像(忘了是谁)说 胡适 的:“这个人路子是对的,就是没读过多少书。”我们大部分人都是理论结合实践,他要把实践结合一下理论,拔高一下再写出来,一定会出名。

总之,我觉得这只土贼有可能成为国内最好的敏捷BA。所以我现在开始收集他的签名。

(还有哈,顺便给这个帅锅BA蒸个女盆友~~小熊表示青春痘都冒出来了的日子还是有点造孽~~有意的女童鞋可以找我报名~~)

这个文档 描述得不是很清楚,因此记录一遍。首先需要同时下载 src发布包bin发布包

解开src发布包,在其中build distributed插件,然后把contrib目录copy到bin发布包解压后的目录:
cd $CC_SRC/contrib/distributed
ant
cd $CC_BIN
cp -r $CC_SRC/contrib ./contrib
修改$CC_BIN/cruisecontrol.sh,在其中包含distributed插件的classpath:
... ...
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
在$CC_BIN/config.xml中指定需要分布的工程:
<plugin name="distributed" 
   classname="net.sourceforge.cruisecontrol.builders.DistributedMasterBuilder"/>
... ...
<distributed>
  <ant antscript="/usr/bin/ant" 
   antworkingdir="/path/to/my/project" />
</distributed>
打开Lookup server:
cd $CC_BIN/contrib/distributed/dist/lookup
ant

然后,把cc_agent.zip拷到Agent机器上,修改conf/agent.properties配置,ant启动,就好了。

(郁闷地搞了一下午的心得是:不要尝试在Windows上做任何严肃的开发工作。Stupid Windows.)

子曰:不得中行而与之,必也狂狷乎,狂者进取,狷者有所不为也。

一开始,我们只是想教他们写程序。因为我们相信,如果程序员不会写程序,那么不管用什么组织结构什么流程方法,也不可能把软件做好。就这么简单,而已。

于是一切就开始了。他们的测试一团糟,所以我们教他们做测试。他们的构建脚本不自动化,所以我们教他们做一键式构建。他们的持续集成没有规矩,所以我们帮他们建立持续集成纪律。他们角色之间沟通成本很高,所以我们帮他们建设一体化团队。他们做个培训叫人昏昏欲睡,所以我们帮他们培养敏捷教练……

我们还想得更多。他们的考核方式重个人目标多于团队目标,虽然我们不是绩效考核的专家,但我们给了他们建议,于是他们开始改变了。他们和客户打交道的方式让他们难受得要死,虽然我们不是搞客户的专家,但我们给了他们建议,于是他们想改变了。他们的项目监理让他们束手束脚,虽然我们不是监理的专家,但我们也想给他们建议,让他们改变。“如果有天让我做这件事……”我们经常这样的想着。

因为我们都是进取的狂者。某人说,就像丰田方法之于其他所有人讲的精益一样,我们能得到区别于其他所有人讲的敏捷的ThoughtWorks方法。他们需要的,我们能做的,远不止现在这些。那些我们还没有做、想要去做的事,才是对他们最有价值的。

然后伊涅什说,是的,我们当然可以做这些事,我们都是进取的狂者,然则当我们一次又一次地改变自己,我们最初的DNA在哪里?我们是不是会很容易地劝服自己,没关系,如果我们能做好这些最有价值的、最关键的事,程序员们自然会找到方法学会写程序的──我几乎就把自己劝服了。

两周前我和YH说,我很喜欢 豆瓣上的某个小组 。那天下午,YH就改了他的签名档。于是我问自己,我会给自己找一条有所不为的线吗?

YH的签名档说:最终我们都会变成自己讨厌的那种人。

禅意的对谈

April 27th, 2010

领导:大师你看,我们公司多久能达到敏捷的状态呢?

大师:五年。

领导:大师有所不知,我们公司执行力很强,只要我一句话下去,所有人都会照办。

大师:哦,那么十年吧。

(如有雷同,纯属巧合。请勿对号入座,谢绝跨省追捕。)