方法论

瀑布模型

敏捷与精益

周围经常有很多人在争论到底那种开发方式是正统的敏捷,就好比华山派的剑宗,气宗之争一样,只不过参与争论的门派更多而已。初学者会认为迭代开发,TDD,结对编程,站会就是敏捷;更高级一些的则又认为这些实践层面的未必是敏捷,敏捷更多的是根据实际情况来调整策略,让团队自己管理自己的流程。

当然,软件开发的各种方法论发展到今天,可能很难看到某个组织或者团队在进行某种敏捷或者瀑布的开发方式了,各种实践你中有我,我中有你,互相影响。

比如在ThoughtWorks,我们很多团队在传统的Scrum中融入了一些看板方法。除了站会,迭代开发之外,团队引入看板,控制在制品数量,价值流驱动等等。而有些客户团队里,则是在敏捷开发的形式下进行瀑布模型的开发,团队也进行站会,也划分迭代,但是仍然有独立的测试部门,运维部门,部门墙森然林立,任何一个单独的团队都无法描述一个完整的价值流,没有人真正知道一个功能的周期时间如何,也没有人真正了解整个流程(需求从何而来,如何做系统测试,如何保证最后的部署)。

追本溯源

敏捷一词来源于2001年初美国犹他州雪鸟滑雪圣地的一次敏捷方法发起者和实践者的聚会,与会者总结出一套软件开发价值观。

  1. 我们一直在实践中探寻更好的软件开发方法,
  2. 身体力行的同时也帮助他人。由此我们建立了如下价值观:
  3. 个体和互动 高于 流程和工具
  4. 工作的软件 高于 详尽的文档
  5. 客户合作 高于 合同谈判
  6. 响应变化 高于 遵循计划
  7. 也就是说,尽管右项有其价值,
  8. 我们更重视左项的价值。

你会发现几乎所有的这些实践都很难直接和我们平时说的“敏捷”对应起来。所以,所谓谁对谁错压根没有意义。因为敏捷只是一些理念,还没有具体到可以实践的层面。

所幸人们开发了一些工具/实践,来支持这样的理念,流传最广的是极限编程Scrum两类。后面的看板方法则是在精益的基础上扩展出来的。

精益原则

与敏捷宣言诞生于软件开发领域不同的是,精益的概念来自于制造业,具体来说,是日本丰田公司。该方法帮助丰田成为世界上最成功的汽车制造商,实践证明,精益制造原则同样适用于软件开发领域。

根据精益制造原则,人们为软件开发也总结了如下七条原则

  • 消除浪费
  • 增强学习
  • 尽量延迟决定
  • 尽快发布
  • 下放权力
  • 嵌入质量
  • 全局优化

极限编程(XP)

极限编程是敏捷中应用非常广泛的方法学之一,

  • 现场客户
  • 结对编程
  • 测试驱动开发
  • 代码所有权共享
  • code review

Scrum

  • 迭代开发
  • 每日站会
  • 回顾会议(retro)
  • 用户故事
  • backlog
  • 跨功能团队

看板方法

热力学第二定律的一个推论是:如果没有外部能量输入,封闭系统趋向越来越混乱。我们需要小心翼翼的维持一个系统(不论是软件系统,还是某个地区生态系统),使其达到某种程度的平衡。而且这个过程是动态的,需要不断调整的。

我们生活在其中的这个物理世界,是一个充满了随机,不确定,不完美的环境,所有一切顶多只能达到“刚好够用”的程度,一个细小的环境变化都可能使整个系统坍塌,崩溃。我们的呼吸系统非常适合20%的含氧量,一旦低于这个值,我们身体的各个子系统就开始出现各种问题,甚至宕机。我们的骨骼强健到足以支撑我们跳跃,奔跑,追击猎物,和不算太大的肉食动物搏斗,但是它并没有强健到缓冲从3层楼跳下来的冲击力。

我们一直引以为豪,或者至少觉得不可思议的思维系统,也是如此。平时大脑中的各种想法纷至沓来,而在我们真正需要的时候(比如公共演讲开场时),它又会变成一片空白。记忆破碎,短暂,而且它会发生偏差,遗漏,即使很重要的事情。

不论我们是如何认为的,人们在做出决策时,事实上是充满随机性和非理性的。即使我们认为非常聪明,非常有经验的那些人也无法幸免。做决策时,大脑很容易被一些事实上并不重要的因素影响,并形成不准确的判断。

既然如此,我们又如何敢将希望寄托在这些“不靠谱”的硬件上呢?

另一方面,人们热衷与做计划,然后按部就班地去实施。

传统的那些失败项目中,人们制定大而全的计划

中国有句古话,叫“凡事预则立,不预则废”,强调了做事情时制定计划的重要性。短期的计划当然是有用的,而且是关键的。

现实世界里,人们在实施软件工程时,通常有两个流派:计划派和无计划派。

计划派

计划派无一例外的喜欢大而全的计划,相信实现者会按照这个计划按部就班的实施,设计,开发,测试,部署,最后人们准确地在发布日饮酒庆祝上线成功。但是等一下,这种事情真的发生过吗?

计划派忽略了工程中各个步骤之间的交互,比如开发阶段发现设计有问题,测试阶段发现开发有问题等,这种异常的流程会导致之前的计划变形,而这些异常情况简直就是每个工程中正常部分。毕竟,谁能确保设计文档中的提到的消息队列服务在开发中一定可以实现呢(特别是只有很短工期的情况下)?

结果就是,每个部门都尝试为自己的环节加上缓冲,这会导致整个工程的时间变长。投资方(比如业务部门)则会根据经验压缩这个时间(毕竟,历史上IT部门从来没有兑现过自己的承诺嘛),或者加入额外的需求。这些都会导致项目的延期,或者功能的不完善。

无计划派

无计划派则是迫于压力,每日疲于应付各种突发情况,或者工作优先级随时都可能调整,一切以“高优先级”的客户需求为准。但是其实谁也不知道下一个任务会在合适插入你的待办事项列表。

2010年,我就在这样一个团队工作,开发人员每天扮演的就是救火队的角色。我们的工作可以分为两类:修改之前由于赶进度而产生的遗留问题,或者在赶进度。事实上,也并没有什么所谓的进度,我们有一个待办事项列表,列表中的条目有时还互不相关(就好像JavaScript中的数组一样,你可以在其中存入各种类型的数据)。

  • 工作流系统中DSL部分的测试(有人抱怨有语法错误)
  • 自定义文件管理系统(客户说必须在一周后可用)
  • 修改部署脚本,可以方便运维部门的人自动安装
  • 为某个Web服务器启动gzip

而总有一些优先级更高的任务被插入,这些任务可能来自于某个重要客户的一个暗示(是的,暗示!还有比猜测客户的真实需求更不靠谱的事儿吗?),也可能是公司某个其他领导的一个讲话。

另一个流派

我在这两种流派的公司都待过,也目睹了在这种情况下软件项目是如何失败的。幸运的是,除了这两个流派之外,我还见过其他的流派:粗粒度的规划+短期的计划。