代码改变世界

我的常识—— Do it early, do it often, do it automatically

2011-11-12 21:02  菜阿彬  阅读(5098)  评论(10编辑  收藏  举报

缘起

  上篇博客转眼已是半年前的了,最近有两个原因,促使我再次写博:

  一是深深感到,在软件开发行业,有很多我认为已经是“常识性”的东西,可是对很多团队却完全没有体会。敏捷软件开发已走过十年时间,可是仍未普及,我觉得一个原因正在于此:很多“最佳实践”,它背后的原理,仍不被很多团队理解。反过来说,只有行业把这些东西当做“常识”了,敏捷才会真正的普及开来。

  这些“常识性”的东西,往往很小。很小的实践,背后却隐藏着一种价值观。作为个人来说,如果能跟拥有共同常识、共同价值观的人共事,无疑会让每天的工作更加愉快。可是正因为它“小”,导致我一直没有动力把它们写下来,直到前几天参加上海的敏捷沙龙,聆听了Daniel Teng的演讲《Survival》。

  这个主题演讲非常好,讲的是个人和组织怎么在当今信息爆炸的年代生存下来。其中有一个观点:个人在自己的知识更新过程中,要保持“habit to ship”——如同软件开发中的“持续集成”/“持续交付”,个人所学的知识也要经常“交付出去,“交付”的形式可以是写博客、可以是做演讲……目的是一样的:1是寻求反馈;2是小步伐前进,积少成多。

  很有趣的是Daniel的这个演讲所用的PPT,在他演讲时并未完成。他的演讲本身就在实践“ship it”的思想——不必等自己的知识体系很完整了,才能去给别人讲(知识爆炸的年代,这样太没有效率了),有了想法,就可以“交付”给社区,从社区获得反馈,再做下一步学习的调整,避免方向上的错误。

  这就是促使我再次写博的第二个原因。 

说明

  我希望把“我的常识”写成一个系列,把我认为的在软件开发中的常识一个个写出来,并尽量阐明背后的价值观。有几点想说明:

  1, 唯一不变的东西就是变化,“常识”也会变。我所写的,仅代表我目前的认识水平。

  2, 我所写的,不代表全是对的,尤其是不同的团队,有不同的“context”,没有放之四海而皆准的东西。因为希望能从社区得到反馈的同时,也希望能抛砖引玉。 

正文

  这是这个系列的第一篇,其实主题已经在上面的“缘起”里体现了,这篇的正文只举几个或真实或假想的案例来说明。

案例一

  A团队在进行一个预计3个月后上线的小项目,项目经理排的计划是2个月后完成开发,然后半个月Alpha测试,半个月Beta测试。项目很小,需求很简单,似乎没什么风险。2个月后顺利进入Alpha测试,结果发现bug很多,有些细节没有达到客户的要求。半个月很快就要过去,于是大家加班修bug。

  相信很多团队都经历过类似的上线前的鸡飞狗跳的日子。问题出在什么地方?——团队把测试放到最后的阶段,并且只有一次。如果回到3个月前,项目经理可以做些什么改变呢?Do it often——团队可以先完成一个小的Feature,然后让QA针对这个Feature进行测试;同时团队继续下一个Feature的开发……如此循环。这其实就是“迭代开发”的概念了。

  总结:如果一个团队需要使用“测试阶段”来对产品进行质量的保证,那么让这样的“测试阶段”多一些。

案例二

  B团队在重写一个为期一年的中型应用软件,旧的应用软件已经成为遗留系统,维护成本太大,因此公司决定重写。除了要实现老系统的原有功能外,这个项目还有些特殊的需求:1,该系统跟其他几个系统有集成,重写后仍然需要支持。2, 新系统的数据库会有调整,但老系统的数据需要在新系统上线的时候,无缝地Migrate到新系统中。

  团队在经历了几个月的开发后,终于完成了所有功能的开发。然后就进入了上线前的准备——1, 把新系统部署到服务器;2, 配置好与其他系统的集成,并且进行测试;3, 把老系统的数据库备份一个出来,然后运行脚本进行数据库的升级,然后进行测试。

  所有这一切都是手工完成。导致的问题是:上线前有很多繁琐的,让人精神紧绷的事情,完全靠团队里个人的能力和细心程度,稍有差错,就会导致真正上线时的混乱甚至失败。

  这其实不是个新鲜的问题,就是ThoughtWorks公司《软件开发沉思录》里提到的“最后一英里”的问题。

  可以做些什么来改善这种状况,来减轻上线前的压力,增加上线的信心和可靠性呢?还是Do it often,如果能在每个月、甚至每天、甚至“持续集成”里的每次“代码check in”,都来演练一下上线前要做的所有这些事,那么到真正上线的时候,团队就几乎不会有任何额外的担心和压力了。

  当然要做到这一点,“自动化”是不可或缺的。最理想的状态,一切都应该“一键完成”——团队需要维护一系列脚本,团队成员只需要按一个键,就能完成“代码迁出——build——部署——数据库升级——集成测试”等整个过程。或者,至少,可以把最没信心、最复杂的环节单独拿出来做自动化。

  总结:越是困难的事情,越是要do it early, do it often, do it automatically。

案例三

  C团队在做一个新项目,在团队进入功能代码的编写前,架构师已经把架构搭好了。团队基于这个架构开始进行开发,可是随着代码越来越多,需求越来越复杂,大家发现,架构师的架构已经不能满足需求了。

  于是团队向项目经理建议:需要时间来调整、完善框架,这样对开发更有利。项目经理的答案是:时间不允许了,我们需要把功能全部做完,赶紧发布1.0。架构的完善,以后再说。

  结果导致什么问题呢:由于架构不够好,代码写的越来越乱,没有可测性,bug越来越多,在发布1.0之前,团队花在修bug的时间大概有4个月。

  于是团队总结:如果不在前期花2个月的时间来改进代码的质量,那么就等着在后期花4个月的时间来修bug吧。

  可是团队其实还可以做更进一步的总结:为什么改善架构需要向项目经理要额外的时间?架构是什么?架构无非是一些大的设计,软件开发中无处没有设计,难道我们开发一个功能时,需要做一个设计,比如这边想用一个单例模式,也要向项目经理额外要时间吗?当然不用,写代码就是设计,架构无非是大一些的设计,架构不是什么特殊的东西。它可以也应该在编写Feature时不断的完善和演化。架构的演化是日常开发的一部分。提前有个架构是好的,然而日常的演化必不可少。这就是“进化式架构”的概念。

结语

  作为软件工程师,我们编写软件就是因为人脑的运算速度、精确程度、可重复性都不如电脑,因此编写软件,用电脑来帮忙干活。可是在编写软件的时候,为什么很多人会忽略让电脑来帮我们验证我的软件呢?

  1,不要完全依赖人来测试我们的代码——用代码来测试我们的代码。

  2,不要完全依赖人来验证我们系统的集成——用自动化脚本,用持续集成软件。

  3,不要依赖人工一次性的劳动来确保软件的正确——用分而治之、迭代开发来“反复确保”。

  4,不要等软件腐化后再来“重写”软件——时时刻刻“重构”它。

  5,不要期待设计/架构可以一步到位——时时刻刻进化它。

  do it often。

参考阅读

  Daniel Teng:我谈迭代 。迭代就是do it again and again。也是do it often的体现。

  Matin Fowler:有机会就重构。大师最新的关于重构的文章,教导我们:refactor it often。

  刘未鹏:为什么你应该(从现在就开始)写博客。经常写博客。