贪婪与恐惧

September 3rd, 2010

有个小姑娘对我说:“我们真的很想用TDD的方式来开发,可是我们的基础太差了,我们真的能做到那样吗?”

人性的两大弱点:贪婪,和恐惧。亲眼看到了美好的可能性,于是迫不及待想要得到它,是为贪婪。一旦理想与现实抵牾,马上开始担心是否天堂遥不可及,在忧心忡忡中停止了前进,是为恐惧。

不要贪婪。静下心来把远景细化成一个个可以实施的细小改进,把一件件小事落实做好。不要恐惧。不要停下自我改善与帮助别人的步伐,在看不到山顶的时候也不要踯躅不前。每天向上走一点,也许到不了天堂,一定会比现在好很多。

(与WJ共勉)

作为管理工具的持续集成

September 3rd, 2010

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

我打算怎么做这件事呢?

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

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

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

Migrating To A Decent SCM

September 1st, 2010

I know that lots of organizations are still using old-expensive-counterproductive configuration management systems (ClearCase, VSS, etc.). I understand the fear that prevents many of them from moving to a decent SCM (Subversion, Mercurial , etc.). I’ll try to tell a story about that kind of migration, which might alleviate the fear.

A huge company, with 40,000+ software developers, with 10+ years history using ClearCase, wants to migrate to Subversion, because of SVN’s encouragement to atomic commit and optimistic locking. The movement is still ongoing. Every single pace involves at least one delivery team, normally with 100+ programmers in it.

The movement must be as seamless as possible, because people are pushed to meet their next milestone. For a codebase sized over 4GB, we made the migration in a week:

  • Monday
    • Export the existing codebase and check it into SVN AS-IS—it’s time consuming so you have enough time for following items.
    • Send mail to everyone to inform the migration plan, ask them to install SVN client if they haven’t.
    • Make sure everyone can access new SVN repository.
  • Tuesday
    • Check out the codebase from SVN and build it, to make sure you are not breaking anything—that’s why you really should migrate AFTER you have a decent build script.
    • Compose a shell script to synchronize from ClearCase local view to SVN working copy. Synchronize frequently and build every time.
  • Wednesday
    • Clean the codebase: legacy repositories often have lots of garbage (temp files, compiled binaries, etc.) checked in, it’s now a chance to do some clearance, delete and ignore them from SCM. Just don’t break the build.
    • Install continuous integration instance for the codebase in SVN.
    • Synchronize and build frequently. Ask people to fix build if it breaks.
  • Thursday
    • Send mail to everyone, ask them to commit any modifications by the end of day, and tell them “there’s an SVN training tomorrow morning”.
    • Keep doing clearance. Synchronize and build frequently.
  • Friday
    • Disable write-access to ClearCase.
    • Training: Configuration Management & SVN. People need to understand some SCM principles to make a better use of SVN—at least not to mess up the codebase with garbage again.
    • At the same time, synchronize a last time, build, check in.
    • Package your working copy and upload it to a shared directory: it’s much faster to copy and unzip, than checking out from the repository. Mail everyone about how to get a working copy and make first commit.
    • Publish your CI to the team. It’s now the team’s CI.

That’s it. Now your team is on SVN.

有效访谈的技巧

August 30th, 2010

你是一个外来者,你想了解一个完全陌生的团队。最快的方式就是找到他们,和他们谈话,让他们告诉你。为了让谈话更有效,你会需要一些小技巧。

  • 解除他们的戒心,尽量。戒心无非来自一个很简单的原因:如果说实话不会有好处、甚至会有坏处,那么人们就不会说实话。因此你要先告诉他们,你需要快速了解信息,不是为了任何考核,只是为了帮助他们改进──告诉他们,你会在未来几个月里跟他们一起改进。
  • 话题明确。每场访谈开始之前,把你要谈的话题写在白板上,以及具体要了解哪些信息,以及计划用多长时间来谈。让进入房间的人在第一时间知道你要他干些什么,这样他就不会更紧张。并且在没话说的时候可以很快找回话题。
  • 微笑。有很多人说过这事,可是真的有很多人没有做到。微笑,活泼一点,拿自己开个玩笑(例如嘲笑自己刚在白板上写下的字)。在访谈中你会必须制造紧张气氛(例如你会有意指出两个人对同一件事的不同描述),保持微笑,把它变成一件好玩的、和所有“人”对立的“事”。不要让任何一个受访者感到寂寞或者紧张,因为这时候你还不知道究竟谁才是值得信赖的人。
  • 记下别人说的话。更多的人说过这事,可是我们真的做得都不好。不要一边跟人对话一边在记事本上写字,更不要用电脑做记录。这些行为会让你获得权威感,会让受访者感到不安──“他有代表权威的记事本/电脑,而我仿佛裸体”──甚至为了抵抗这种不安也拿出记事本来写字。但这些行为不会帮你得到更多有效的信息。在白板上做记录。把他们说的事情画下来。这会让受访者感到,你们在一起画一个作品。他们会告诉你,什么地方画得不对,还缺少了什么,这是你的记事本上永远不会出现的东西。
  • 问他们有什么想告诉你的。当你问完了所有的问题,问他们:还有什么想告诉你的,有什么问题,有什么痛点。你在这里的原因是你要帮助这些人。这些人最关心的事不一定是你最高优先级的事,但一定不是你应该忽视的事。
  • 最后,不要相信访谈。用眼睛去看。受访者一定会告诉你假话。有这样的觉悟之后,访谈才会真正是有效的。

(性能优化…我这一辈子都在做性能优化…)

1. 线程。不要啊不要自己做锁…并行计算首先要让被并行的任务尽量独立,然后只要把任务放进Thread扔出去,在主线程等待子线程完成任务就行了。
var thread = new Thread(worker.Execute);
thread.Start();
...
thread.Join();

2. 还是线程。然则,.NET的线程是昂贵的,据说一个线程启动需要100毫秒左右,还需要1M左右内存。所以,不能肆无忌惮地开线程…要用 BackgroundWorker …话说,为什么要设计出这种重量级的线程呢…

3. 容器。List不能赋值给IList,IList不能赋值给ICollection…设计这种傻逼容器框架的人真的会写程序吗?

4. 还是容器。List不是线程安全的,多个线程一边写一边读就会告诉你 InvalidOperation 因为内容被修改了;多个线程一起写就会告诉你 ArgumentError 因为某个线程可能以为容器空间够用而不去extend它直接往里放东西结果空间被另一个线程用掉了。好吧…可是,据说ArrayList是线程安全的…但多个线程一起写也会ArgumentError…

5. 日志。Log4Net很慢 …真的非常慢…所以只要把大量的log关掉,于是性能就好了…其实最大的优化是这个…

总之,感想是…真的有人用.NET这种东西做什么严肃的应用程序吗?这些东西…设计得也未免太弱智了吧…呃,想起来了,还有一个:

6. 还是日志。胡凯 说,做个小工具吧,统计一下日志里的信息…嗯,我觉得,那个工具应该叫 grep …一个连grep都没有的操作系统啊…

把事情做完

August 11th, 2010

一个小朋友 结对。拿在手上的是一张叫做“高级搜索”的故事。小朋友说,功能已经做好了,今天的目标是给它加上 WatiN 的功能测试。

于是打开页面,搜索一把,呃…高级搜索的四个条件输入框,有两个填错了东西。小朋友不好意思地说,后台的逻辑都做好了,HTML还差一点点。因为昨天晚上要聚餐,所以就留下了。

改好HTML,再试一试,呃…正好是刚才没弄好的两个条件输入框,如果组合起来使用就会出错,啥也搜不出来了。仔细往里面一看,原来这两个条件的组合是比较奇妙滴…需要修改整个搜索算法,还需要自己实现一个“集合的交集”(stupid C#...)总而言之,用了大半天时间,才把“高级搜索”真正做完…咻~可以开始写测试了。

记得某人曾经告诉我,H司某产品的代码,有40%是在大家都以为“差不多做完了”的连调测试阶段写进去的。(给小朋友讲这个故事,似乎小朋友不是很有感觉,sigh~~)

所以,做一件事就做完,做到可以给客户验收的程度,然后再开始下一件事。自以为90%完成的东西,通常还需要再花一倍时间才能真正做完。(昨天 胡凯 再次验证了这一理论的正确性。)

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

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

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

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

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

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

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

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

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

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

不做小叮当

July 14th, 2010

ZD亲热地搂着我的肩膀说:“还是你有本事啊,这次才看到你的能力有多强。”我苦笑着说:“我的英名早晚要毁在你手上。”

他是我的客户,也是老乡,而且常常配合很默契。

第一次,二百多人的团队分散在两个城市五个办公地点。ZD对我说,那个产品,发货量巨大,是整个公司最赚钱的部门,客户遍布全球,要是把它搞定了,意义重大。(当时ZB在旁边热情澎湃,被我俩联手泼了一盆冷水。那是我第一次发现,和ZD配合有不需准备的默契。)我沉吟良久,说它真的风险太大,我真的不敢做。但最后我还是去了,因为一个不能让ZD知道的理由。

第二次,一支孤零零的团队正在被一个巨兽客户折磨得要死要活。ZD对我说,这次能让客户感受到我们的变化,要是把它搞定了,意义重大。我又沉吟良久,说它真的真的风险太大,我真的真的不敢做。但最后我还是去了,又是因为一个不能让ZD知道的理由。

我跟他说,其实只是运气好。他笑笑,不信,或者说是装着不信。

小熊说,每个问题解决者都有多拉A梦情结,而康夫每次痛扁技安之后灿烂的笑容便是对小叮当最好的褒奖,是他继续从口袋里掏出法宝的源动力。我不得不承认,挑战一下自己并且挑战成功(不论这成功的原因是什么)的感觉是很爽的。我想ZD一定也知道我的爽感,所以他笑而不语。

所以,尽管真的很想亲眼看到这个大雪球轰然滚下的最后一刻,尽管真的很嫉妒 小熊的博客 比我写得更有料并且更有文采,还是应该抽身了。让自己沉浸在小叮当帮助康夫破涕为笑的愉悦之中,这不是我想要的。

何况,ZD你懂的,我不能等到英名真的毁在你手上的那一天。

出新意于法度之中

July 12th, 2010

周末去看了 邱志杰的展览 。对他的 舞蹈课 很是喜欢。

创新不得和以前重复,这是艺术界的游戏规则;创新会越来越难,这是艺术史的规律;在早期,更多的事不用多加思索的本能选择,游戏越往后,组合、颠覆等可以开发创意就越来越经常被依赖;而是否被认可为创新,这是由之前已经出现过的现象以及众人的裁定所决定的。

在很大程度上,艺术家并不像传说中的那样自由,相反,自由和个性要通过艰难的开发才最终会获得。因此,你必须去研究整个系统,你必须形成一种能够开发创造力的工作机制。

缺乏创意或是坐井观天,如果一定要选的话,究竟哪一个更糟?和Miya说,想一想,如果有一天我也变成这样,以为自己看见的一个小圈就是整个天空,挺可怕的。何况,井里的创意,又能有什么好玩的。