乘时间机器,看敏捷旅程
|
BOSCO系统是一个在线品牌管理系统,项目客户是一家跨国酒店集团,旗下拥有多个世界著名的酒店品牌。BOSCO系统将服务标准化、标准符合度审查、改进流程管理等酒店品牌管理的工作内容整合到一个信息系统中,来提高相关人员的工作效率。目前BOSCO系统已经被全球十个酒店品牌、超过1000家酒店使用,用户超过8000人。 BOSCO系统的开发基于Ruby On Rails,在项目的开发过程中应用了敏捷开发方法。在开发此系统的8个月中,经历了15个迭代和3次发布。通过这种与客户紧密合作的工作方式我们按时交付了系统,并得到了客户的高度认可。笔者作为开发团队的一员,从开发者的角度对基于Ruby On Rails的敏捷开发实践总结出一些心得体会,其中有成功的经验,也有失败的教训,愿与敏捷开发爱好者分享。 在我们的系统中,有一个有趣的类,叫做TimeMachine,用于修改UAT服务器的系统时间。但现在,让它带我们穿梭时空吧。 TimeMachine.go_to("2008-04-15") 半路接手——关键字:Knowledge Transfer,结对编程 2008年4月,BOSCO系统漂洋过海来到中国。此时,它已经在美国经过了3个月的开发,且完成了第一次发布。现在要开始它的移植过程(从美国团队的大脑移植到中国团队的大脑)。给我们的资源并不多,只有3个项目原有工作人员:一个BA(业务分析师),两个Dev(开发人员)。但时间却相当有限:一个月。 虽然BOSCO系统的开发时间并不长,但Rails强大的表现力使系统已经足够庞大,我们也担忧Knowledge Transfer能否在约定的时间内完成。而且中国的开发团队中,真正有Rails开发经验的只有一人。如何在这么短的时间内,掌握这么庞大的系统,成了摆在眼前的挑战。 很多遇到过此种情况的开发人员,都不会对以下几种经历感到陌生: ● 阅读大量关于系统原理和项目架构的文档,但它们并不能直观、准确地反应项目情况。 ● 参加各种标榜着“Knowledge Transfer”且耗时长久的会议,但收益甚少。 ● 独自面对系统时不知从何下手,不断地寻求原有开发人员的帮助。 ● 由于不熟悉系统造成在开发过程中不断犯错,贡献了很多“垃圾”代码,并影响了系统开发进度。 其实对于开发人员而言,掌握一个项目最重要的是提升对项目本身的“熟悉度”。此熟悉度代表对陌生的技术知识、代码的编写风格、开发的习惯、程序的架构、环境的搭建等等的掌握和了解。而结对编程是快速掌握这些知识技能的秘诀,还是拿事实来说话吧。 两个星期之后,先行和两个美国Dev结对的同事已经能够带新人了,而且开发速度不亚于两个美国 Dev。短短两个礼拜,中国团队对项目的整体架构,不说了然于心,也是熟门熟路;对于一些story,也能得心应手开始实现。这是我们自己也预想不到的速度。 之所以能在如此短的时间内掌握项目,就是拜“结对编程”所带来的好处所赐。有人会说,结对编程到底有什么魔法?其实没有魔法,它只是简单实践了很多人都懂得的道理:学习一件东西最快速的手段就是动手去做。而结对编程,不仅能让你有立即动手去做的机会,而且边上还有个让你观察学习、给你指导的老师。这是我对结对编程的初次体验,让我非常兴奋。还记得一个朋友给我电话告诉我“项目中的新人不能快速掌握知识”时,我告诉他:不要犹豫了,结对编程吧。我相信,一旦你开始尝试,你就不愿意停止。 TimeMachine.go_to("2008-05-15") 加速前进——关键字:最佳实践 随着Knowledge Transfer期满、美国同事离去,客户一度很担心中国团队能否掌控项目,能否保持开发速度。但在快速接手项目之后,项目开发随即进入了加速通道。在完全接手项目的第一个迭代之后,中国团队已经赶上了美国同事的开发速度。在这个过程中,除了因为团队的快速学习能力之外,还有我们保持的一些最佳实践让我们赢得了胜利。下面让我简单介绍其中一些。 一致的开发机器。我们有6个开发人员,也就是3对pair。Pair的3台机器都是漂亮精致的Mac Mini。当然这不是重点,重点在于,3台机器都有一致的开发环境:一致的程序目录,一致的安装软件,一致的快捷命令等等。完全一模一样的配置使pair在进行切换时,不会对另外一台机器感到丝毫的陌生,这有助于开发人员迅速进入开发状态。 快捷化常用命令。在开发时,我们每天都要进行无数次相同的一些操作:进入Rails开发根目录,启动Web server,签入代码等等。比如当你要进入Rails开发目录,你就得打入命令:cd /Users/rails/workspace/bosco/rails_root。这是一个简单的命令,但同时也是一个繁琐的命令,特别是当我们每天要进行多次这样的操作时,就会浪费大量的时间。这时,如果你为它加一个alias,把这个枯燥的操作用一个简单的命令“rr”代替,它会帮你节省多少时间呢?效率的提升有时就源于一些简单的改善。 不做简单重复的劳动。每天的工作总会有一些事情需要简单重复的劳动。比如当你要验证一项功能时,你需要手工打开网页,然后按着流程一步一步操作,来看实现是否正确等。每当此时,我们的选择是:绝不做简单重复的劳动,而是实现一个自动化的脚本来帮助我们进行这些操作。自动化不同的任务,可以选择不同的工具,比如Selenium、Ruby、Shell等等。后来我在《The Productive Programmer》中读到Neal Ford大师如是说:“手工执行简单重复的任务会让你变傻,会消耗你的注意力,而注意力是最重要的生产力之源。找出一种聪明的方法来自动化这些任务,这会让你变得聪明,因为你能从中学到一些东西。” 每天早上的code diff:在早晨的站立会议结束后,我们并没有马上着手清扫story。所有开发人员会挤在一台机器前,查看前一天的code diff。大家会看到所有成员在前一天的工作中修改的代码,相关的开发人员会对自己的代码作出解释。当有人对一段修改有疑问时,我们就会对此段代码进行讨论。或者是实现上的一些逻辑漏洞,或者是一些不规范的代码编写,或者是一些可能的性能改进,我们总能对一些代码提出疑问,并提出改进意见。Code diff过程是对站立会议以及结对编程的补充,是对代码质量的进一步检验,有助于团队对代码的了解,也促进了代码质量的提升。短短十分钟,何乐而不为? 每周的技术session:每周的技术session是我们一直保持的良好传统,团队从中受益匪浅。项目中总会遇到一些难题,或许是一种陌生的技术,或许是一个难解的问题。而此时,总会有人站出来说:“让我来讲讲这个吧”。或许这项技术对于主持者也是完全陌生的,但不要紧,接下来一周紧张的学习已经足够(这也会促使他更加快速地学习)。一周之后,主持者就为我们带来了一道“丰盛的大餐”。在session中,团队成员都会踊跃发言,并乐于抛出任何疑问让大家讨论。讨论是最能产生火花的,来自每个人不同的思考会让你对问题了解得更加深刻。讨论帮助我们解开了一些困扰已久的疑问,并加深了对一些技术的理解,比如:CSS,Memory Cache,REST,Ajax,Ruby的对象模型等等。通过技术的讨论和学习,团队成员的整体开发能力得到了提升,这极大地促进了项目的开发速度。 团队需要勇于尝试一些实践来促进团队的开发效率和提升团队的整体能力。上面所提及的有些实践都是我们在平时的工作中摸索、体会和总结出来的。比如每周的技术session,就是在成功地开展了一次之后,被保留和坚持下来了。 如何发现一些值得尝试的实践?这看似很难,其实很简单。在项目中遇到的问题,工作中偶然发现的一些事情,别人的经验,或者是你自己的一些想法,都可能是对一项实践的启发。你唯一要做的,就是勇于尝试。“从来没有人这么做过”,或者“别人都不这么做”不是你不这么做的理由。 TimeMachine.go_to("2008-08-01") 当项目开发进入第5个月,我们遇到了一些真正的困难,它们分别是“历史”story和系统性能优化问题。 当项目遇到困难时,正是审视敏捷实践的最好机会。TDD,简单设计,持续集成,重构等等,让我们看看这些实践在项目开发中显现的力量吧。 笑看历史——关键字:简单设计,TDD(测试驱动设计) 历史story:作为全球质量管理员,我要查看一个酒店的标准审查历史记录,从而跟踪并比较酒店在各个时期的标准符合度。 简单分解一下这个story,它要求提供的功能是: ● 系统在一些比如标准变化、酒店审核等事件发生时能保存当时的数据。 ● 系统应该提供一个界面,让用户通过选择特定的日期查看历史信息。 跟通常一样,我们经过estimation(当时估的是5个points,并不太大)以及tasking(简单的设计)之后,开始实现这个story。 刚开始,这个story如预期一样顺利开发下去了。一天,两天,到了第三天,我们突然发现在实现一些功能时有点举步维艰。但通过一些“邪恶”的手段,我们还是解决了那些问题,虽然觉得并不是最佳实现。到了第四天,在实现另一些功能时,我们陷入了绝境:实现得过于复杂让代码改动极其困难,通过了这边的测试,那边的测试就失败了,如此反复。还差两天迭代就要结束了,这个story却深陷泥沼,团队陷入担忧之中。我们决定重新跳出来看一下原来的设计。 基于实现中遇到的困难,我们讨论了原先的设计,发现一些缺陷,并迅速找到了更好的方案。新设计雏形初具,再次动手吧。改动代码,很多原先的测试应声失败了。好事情,失败的测试告诉我们哪里出了问题,过去修正那些失败的测试吧。红,绿,红,绿,按照这样的节奏,出乎所有人意料的事情发生了:一个下午,仅仅是一个下午,我们把历史story完成了! 因为这个设计并不在技术层面,而在业务层面,所以在这里我并不想多讲story的详情。但发生这样的问题,是否会让你怀疑敏捷实践“简单设计”呢?如果你有此怀疑,我的想法就正好跟你相反,因为通过这个story让我更加相信“简单设计”的好处。 首先,即使现在回头看,我们还是认为就算当初花几倍的时间去做设计,也难免犯同样的错误。其次,检验设计优劣的最佳工具就是代码本身,及早地应用设计于代码,让代码来告诉你设计正确与否。这正是在这个story陷入泥沼时我们的反应:实现不能继续,来看看设计的问题吧。再次,之后我们的设计之所以如此成功地符合了业务的需求,是因为前一次失败的经历让我们对代码有了更进一步的了解,对问题有了更清晰的洞察。谜团是在行进中解开的,并不是一开始就能知晓。最后,我想我们唯一应该改进的,就是在发现开发出现困难时,能更早地跳出来,从设计角度分析一下问题。 (编辑:安卓应用网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
