敏捷开发
一 、 简介
敏捷开发是一种以用户的需求进化为核心、迭代、循序渐进的开发方法。在敏捷开发中,
软件项目的构建被切分成多个子项目,各个子项目的成果都经过测试,具备集成和可运行的
特征。换言之,就是把一个大项目分为多个相互联系,但也可独立运行的小项目,并分别完
成,在此过程中软件一直处于可使用状态。
二 、 路线
Test - Driven ****Development , 测试驱动开发
它是敏捷开发的最重要的部分。实现任何一个功能都是从测试开始,首先对业务需求进
行分析,分解为一个一个的 Story,记录在 Story Card 上。然后两个人同时坐在电脑前面,
一个人依照 Story,从业务需求的角度来编写测试代码,另一个人看着他并且进行思考,如
果有不同的意见就会提出来进行讨论,直到达成共识,这样写出来的测试代码就真实反映了
业务功能需求。接着由另一个人控制键盘,编写该测试代码的实现。如果没有测试代码,就
不能编写功能的实现代码。先写测试代码,能够让开发人员明确目标,就是让测试通过。
Continuous ****Integration , 持续集成
在以往的软件开发过程中,集成是一件很痛苦的事情,通常很长时间才会做一次集成,
这样的话,会引发很多问题,比如 build 未通过或者单元测试失败。敏捷开发中提倡持续集
成,一天之内集成十几次甚至几十次,如此频繁的集成能尽量减少冲突,由于集成很频繁,
每一次集成的改变也很少,即使集成失败也容易定位错误。一次集成要做哪些事情呢?它至
少包括:获得所有源代码、编译源代码、运行所有测试,包括单元测试、功能测试等;确认
编译和测试是否通过,最后发送报告。当然也会做一些其它的任务,比如说代码分析、测试
覆盖率分析等等。
Refactoring , 重构
相信大家对它都很熟悉了,有很多很多的书用来介绍重构,最著名的是 Martin 的《重
构》,Joshua 的《从重构到模式》等。重构是在不改变系统外部行为下,对内部结构进行整
理优化,使得代码尽量简单、优美、可扩展。在以往开发中,通常是在有需求过来,现在的
系统架构不容易实现,从而对原有系统进行重构;或者在开发过程中有剩余时间了,对现在
代码进行重构整理。但是在敏捷开发中,重构贯穿于整个开发流程,每一次开发者 check in
代码之前,都要对所写代码进行重构,让代码达到 clean code that works。值得注意的是,
在重构时,每一次改变要尽可能小,用单元测试来保证重构是否引起冲突,并且不只是对实
现代码进行重构,如果测试代码中有重复,也要对它进行重构。
Pair - Programming , 结对编程
在敏捷开发中,做任何事情都是 Pair 的,包括分析、写测试、写实现代码或者重构。
Pair 做事有很多好处,两个人在一起探讨很容易产生思想的火花,也不容易走上偏路。还有
很多事都可以 Pair 来做,比如 Pair 学习,Pair 翻译,Pair 做 PPT。
Stand ****up , 站立会议
每天早上,项目组的所有成员都会站立进行一次会议,由于是站立的,所以时间不会很
长,一般来说是 15-20 分钟。会议的内容并不是需求分析、任务分配等,而是每个人都回
答三个问题:1. 你昨天做了什么?2. 你今天要做什么? 3. 你遇到了哪些困难?站立会议
让团队进行交流,彼此相互熟悉工作内容,如果有人曾经遇到过和你类似的问题,那么在站
立会议后,他就会和你进行讨论。
Frequent ****Releases , 小版本发布
在敏捷开发中,不会出现这种情况,拿到需求以后就闭门造车,直到最后才将产品交付
给客户,而是尽量多的产品发布,一般以周、月为单位。这样,客户每隔一段时间就会拿到
发布的产品进行试用,而我们可以从客户那得到更多的反馈来改进产品。正因为发布频繁,
每一个版本新增的功能简单,不需要复杂的设计,这样文档和设计就在很大程度上简化了。
又因为简单设计,没有复杂的架构,所以客户有新的需求或者需求进行变动,也能很快的适
应。
Minimal ****Documentation , 较少的文档
其实敏捷开发中并不是没有文档,而是有大量的文档,即测试。这些测试代码真实的反
应了客户的需求以及系统 API 的用法,如果有新人加入团队,最快的熟悉项目的方法就是
给他看测试代码,而比一边看着文档一边进行 debug 要高效。如果用书面文档或者注释,
某天代码变化了,需要对这些文档进行更新。一旦忘记更新文档,就会出现代码和文档不匹
配的情况,这更加会让人迷惑。而在敏捷中并不会出现,因为只有测试变化了,代码才会变
化,测试是真实反应代码的。这时有人会问:代码不写注释行吗?一般来说好的代码不是需
要大量的注释吗?其实简单可读的代码才是好的代码,既然简单可读了,别人一看就能够看
懂,这时候根本不需要对代码进行任何注释。若你觉得这段代码不加注释的话别人可能看不
懂,就表示设计还不够简单,需要对它进行重构。
Collaborative ****Focus , 以合作为中心 , 表现为代码共享
在敏捷开发中,代码是归团队所有而不是哪些模块的代码属于哪些人,每个人都有权利
获得系统任何一部分的代码然后修改它,如果有人看到某些代码不爽的话,那他能够对这部
分代码重构而不需要征求代码作者的同意,很可能也不知道是谁写的这部分代码。这样每个
人都能熟悉系统的代码,即使团队的人员变动,也没有风险。
Customer ****Engagement ****, 现场客户
敏捷开发中,客户是与开发团队一起工作的,团队到客户现场进行开发或者邀请客户到
团队公司里来开发。如果开发过程中有什么问题或者产品经过一个迭代后,能够以最快速度
得到客户的反馈。
Automated ****Testing ****, 自动化测试
为了减小人力或者重复劳动,所有的测试包括单元测试、功能测试或集成测试等都是自
动化的,这对 QA 人员提出了更高的要求。他们要熟悉开发语言、自动化测试工具,能够编
写自动化测试脚本或者用工具录制。
Adaptive ****Planning , 可调整计划
敏捷开发中计划是可调整的,并不是像以往的开发过程中,需求分析->概要设计->详细
设计->开发 ->测试->交付,每一个阶段都是有计划的进行,一个阶段结束便开始下一个阶
段。而敏捷开发中只有一次一次的迭代,小版本的发布,根据客户反馈随时作出相应的调整
和变化。敏捷开发过程与传统的开发过程有很大不同,在这过程中,团队是有激情有活力的,
能够适应更大的变化,做出更高质量的软件。
三 、 特点
敏捷方法主要有两个特点,这也是其区别于其他方法,尤其是重型方法的最主要特征:
敏捷开发方法是 “ 适应性 ” ( Adaptive ) 而非 “ 预设性 ” ****( Predictive )
这里说的预设性,可以通过一般性工程项目的做法理解,比如土木工程,在这类工程实
践中,有比较稳定的需求,同时建设项目的要求也相对固定,所以此类项目通常非常强调施
工前的设计规划。只要图纸设计得合理并考虑充分,施工队伍可以完全遵照图纸顺利建造,
并且可以很方便地把图纸划分为许多更小的部分交给不同的施工人员分别完成。
然而,在软件开发的项目中,这些稳定的因素却很难寻求。软件的设计难处在于软件需
求的不稳定,从而导致软件过程的不可预测。但是传统的控制项目模式都是试图对一个软件
开发项目在很长的时间跨度内做出详细的计划,然后依计划进行开发。所以,这类方法在不
可预测的环境下,很难适应变化,甚至是拒绝变化。
与之相反的敏捷方法则是欢迎变化,目的就是成为适应变化的过程,甚至能允许改变自
身来适应变化。所以称之为适应性方法。
敏捷开发方法是 “ 面向人 ” ****( people ****oriented ) 而非 “ 面向过程 ” ( process ****oriented )
Matin Flower 认为:“在敏捷开发过程中,人是第一位的,过程是第二位的。所以就个
人来说,应该可以从各种不同的过程中找到真正适合自己的过程。”这与软件工程理论提倡
的先过程后人正好相反。
在传统的软件开发工作中,项目团队分配工作的重点是明确角色的定义,以个人的能力
去适应角色,而角色的定义就是为了保证过程的实施,即个人以资源的方式被分配给角色,
同时,资源是可以替代的,而角色不可以替代。
然而,传统软件开发的这些方法在敏捷开发方式中被完全颠覆。敏捷开发试图使软件开
发工作能够利用人的特点,充分发挥人的创造能力。
敏捷开发的目的是建立起一个项目团队全员参与到软件开发中,包括设定软件开发流程
的管理人员,只有这样软件开发流程才有可接受性。同时敏捷开发要求研发人员独立自主在
技术上进行决策,因为他们是最了解什么技术是需要和不需要的。再者,敏捷开发特别重视
项目团队中的信息交流,有调查显示:“项目失败的原因最终都可追溯到信息没有及时准确
地传递到应该接受它的人。”
四 、价值观
实际上敏捷开发运动在数年前就开始了,但它正式开始的标志是 2001 年 2 月的“敏捷
宣言”(Agile Manifesto),这项宣言是由 17 位当时称之为“轻量级方法学家”所编写签署的,
他们的价值观是:个人与交互重于开发过程与工具;可用的软件重于复杂的文档;寻求客户
的合作重于对合同的谈判;对变化的响应重于始终遵循固定的计划。
个人与交互重于开发过程与工具的原因:一个由优秀的人员组成但使用普通的工具,要
比使用优秀的工具但由普通人组成、紊乱的小组做得更好。多年来人们花了很多时间试图建
立一种过程,以便把人当作机器上的一个可以替代的齿轮,但结果却并不成功。敏捷过程是
承认每个人都有特定的能力(以及缺点)对之加以利用,而不是把所有的人当成一样来看待。
更重要的是,在这样的理念下,几个项目做下来,每个人的能力都从中得以提高。这种人的
能力的提高,对公司是无价之宝。而不至于把人当成齿轮,随着时间的推移,人的能力慢慢
被消耗掉,最后变成留之无用、弃之可惜的尴尬人物。
可用的软件重于复杂的文档的原因:可用的软件可以帮助开发人员在每次迭代结束的时
候,获得一个稳定的、逐渐增强的版本。从而允许项目尽早开始,并且更为频繁的收集对产
品和开发过程的反馈。随着每次迭代完成软件的增长,以保证开发小组始终是处理最有价值
的功能,而且这些功能可以满足用户的期待。
寻求客户的合作重于对合同的谈判的原因:敏捷开发小组希望与项目有关的所有团体都
在朝共同方向努力,合同谈判有时会在一开始就使小组和客户出于争执中。敏捷开发追求的
是要么大家一起赢,要么大家一起输。换句话说,就是希望开发小组和客户在面对项目的时
候,以一种合作的态度共同向目标前进。当然,合同是必需的,但是如何起草条款,往往影
响到不同的团体是进行合作式的还是对抗式的努力。
对变化的响应重于始终遵循固定的计划的原因:敏捷开发认为对变化进行响应的价值重
于始终遵循固定的计划。他们最终的焦点是向用户交付尽可能多的价值。除了最简单的项目
以外,用户不可能知道他们所需要的所有功能的每个细节。不可避免地在过程中会产生新的
想法,也许今天看起来是必需的功能,明天就会觉得不那么重要了。随着小组获得更多的知
识和经验,他们的进展速度会比开始的时候期望值慢或者快。对敏捷开发来说,一个计划是
从某个角度对未来的看法,而具有多个不同的角度看问题是有可能的。
五 、 方法
敏捷方法很多,包括 Scrum、极限编程、功能驱动开发以及统一过程(RUP)等多种法,
这些方法本质实际上是一样的,敏捷开发小组主要的工作方式可以归纳为:作为一个整体工
作; 按短迭代周期工作; 每次迭代交付一些成果; 关注业务优先级; 检查与调整。下图
是典型的敏捷过程总图,下面介绍其有关的特点。
敏捷小组作为一个整体工作
项目取得成功的关键在于,所有项目参与者都把自己看成朝向一个共同目标前进的团队
的一员。“扔过去不管”的心理不是属于敏捷开发。设计师和架构师不会把程序设计“扔”给编
码人员;编码人员也不会把只经过部分测试的代码“扔”给测试人员,一个成功的敏捷开发小
组应该具有“我们一起参与其中的思想”, “帮助他人完成目标”这个理念是敏捷开发的根本管
理文化。当然,尽管强调一个整体,小组中应该有一定的角色分配,各种敏捷开发方法角色
的起名方案可能不同,但愿则基本上是一样的。第一个角色是产品所有者,他的主要职责包
括:确认小组成员都在追求一个共同的目标前景;确定功能的优先等级,以便总是处理最有
价值的功能;作出可以使项目的投入产生良好回报的决定。产品所有者通常是公司的市场部
门或者产品管理部门的人员,在开发内部使用的软件的时候,产品所有者可能是用户、用户的上级、分析师,也可能是为项目提供资金的人。
敏捷小组按短迭代周期工作
在敏捷项目中,总体上并没有什么上游阶段、下游阶段,你可以根据需要定义开发过程
在初始阶段可以有一个简短的分析、建模、设计,但只要项目真正开始,每次迭代都会做同
样的工作(分析、设计、编码、测试。等等)。迭代是受时间框限制的,也就是说即使放弃
一些功能,也必须结束迭代。时间框一般很短,大部分是 2~4 周,在 Scrum 中采用的是 30
个日历天,也就是 4 周。迭代的时间长度一般是固定的,但也有报告说,有的小组在迭代
开始的时候选择合适的时间长度。
敏捷小组每次迭代交付一些成果
比选择特定迭代长度更重要的,是开发小组在一次迭代中要把一个以上的不太精确的需
求声明,经过分析、设计、编码、测试,变成可交付的软件(称之为功能增量)。当然并不
需要把每次迭代的结果交付给用户,但目标是可以交付,这就意味着每次迭代都会增加一些
小功能,但增加的每个功能都要达到发布质量。每次迭代结束的时候让产品达到可交付状态
十分重要,但这并不意味着要完成发布的全部工作,因为迭代的结果并不是真正发布产品。
假定一个小组需要在发布产品之前对软硬件进行为期两个月的“平均无故障时间”(MTBF)
测试,他们不可能缩短这两个月的时间,但这个小组仍然是按照 4 周迭代,除了 MTBF 测
试,其它都达到了发布状态。
敏捷小组关注业务优先级
敏捷开发小组从两个方面显示出他们对业务优先级的关注。首先,他们按照产品所有者
制定的顺序交付功能,而产品所有者一般会按照组织在项目上的投资回报最大化的方式来确
定优先级,并且把它组织到产品发布中去。要达到这个目的,需要综合考虑开发小组的能力,
以及所需功能的优先级来建立发布计划。在编写功能的时候,需要使工能的依赖性最小化。
如果开发一个功能必须依赖其它 3 个功能,那产品所有者这就很难确定功能优先级。功能
完全没有依赖是不太可能的,但把功能依赖性控制在最低程度还是相当可行的。
敏捷小组检查与调整
任何项目开始的时候所建立的计划,仅仅是一个当前的猜测。有很多事情可以让这样的
计划失效:项目成员的增减,某种技术比预期的更好或更差,用户改变了想法,竞争者迫使
我们做出不同的反应,等等。对此,敏捷小组不是害怕这种变化,而是把这种变化看成使最
终软件更好地反映实际需要的一个机会。每次新迭代开始,敏捷小组都会结合上一次迭代中
获得新知识做出相应调整。如果认为一些因素可能会影响计划的准确性,也可能更改计划。
比如发现某项工作比预计的更耗费时间,可能就会调整进展速度。也许,用户看到交付的产
品后改变了想法,这就产生反馈,比如他发现他更希望有另一项功能,或者某个功能并不像
先前看得那么重。通过先期发布增加更多的用户希望的功能,或者减少某些低价值功能,就
可以增加产品的价值。迭代开发是在变与不变中寻求平衡,在迭代开始的时候寻求变,而在
迭代开发期间不能改变,以期集中精力完成已经确定的工作。由于一次迭代的时间并不长,
所以就使稳定性和易变性得到很好的平衡。在两次迭代期间改变优先级甚至功能本身,对于
项目投资最大化是有益处的。从这个观点来看,迭代周期的长度选择就比较重要了,因为两
次迭代之间是提供变更的机会,周期太长,变更机会就可能失去;周期太短,会发生频繁变
更,而且分析、设计、编码、测试这些工作都不容易做到位。综合考虑,对于一个复杂项目,
迭代周期选择 4 周还是有道理的。
六 、 误解
误解一 :敏捷对人的要求很高
很多人在尝试实施敏捷时说:敏捷对人的要求太高了,我们没有这样的条件,我们没有
这样的人,因此我们没法敏捷。可是,敏捷对人的要求真的那么高么? 软件归根到底还是
一种创造性活动,开发人员的技术水平和个人能力对软件的质量还是起着决定性的作用,各
种过程与方法只是帮助开发人员、测试人员等角色能够更好的合作,从而产生更高的生产力。
不管用什么方法,开发人员的水平永远都是一个主要的因素。
从另一个角度来看:过程和方法究竟能帮开发人员多大忙?对于技术水平较低的开发人
员,敏捷方法和传统方法对他的帮助是差不多的,因此看不到显着的效果,甚至有些时候还
有反效果;而随着开发人员技术水平的提高,敏捷方法能够解开对人的束缚,鼓励创新,效
果也会越来越显着。
敏捷对人的要求并不高,而且会帮助你培养各种所需的能力,当然前提是你处在真正敏
捷的环境中。
误解二 :敏捷没有文档 , 也不做设计
这个误解从 XP 开始就没有停止过,XP 鼓励“在非到必要且意义重大时不写文档”。这
里面提到的“必要且意义重大”是一个判断标准,并不是所有的文档都不写。例如,用户手册
是不是“必要且意义重大”?这取决于客户的要求,如果客户不需要,那就不用写,如果客户需
要,就一定要写;再如,架构设计文档要不要写?复杂要写,不复杂不用写。通常架构设计
只需要比较简单的文档,对于有些项目,一幅简单的 UML 图就够了。因此,写不写,怎么
写,都要根据这个文档到底有多大意义,产出和投入的比例,以及项目的具体情况决定。实
际操作时可以让项目组所有人员表决决定,尽量避免由某一个人(比如 lead)来决定。
至于设计,XP 奉行的是持续设计,并不是不设计。这实际上是将设计工作分摊到了每
天的日常工作中,不断的设计、改善(重构),使得设计一直保持灵活可靠。至于编码前的
预先设计,Kent Beck 等人确实实行着不做任何预先设计的开发方式,但是对于我们这些“非
大师”级开发人员,必要的预先设计还是需要的,只是不要太多,不要太细,要有将来会彻
底颠覆的准备。
误解三 : 敏捷好 , 其他方法不好
有些人一提到敏捷就大呼好,只要是敏捷的实践就什么都好,而提到 CMMI 等方法就
大呼不好,不管是什么只要沾上边就哪里都不好,似乎敏捷和其他方法是完全对立的。牛顿
说过,我是站在了巨人的肩膀上。敏捷同样也吸取了其他方法论的优点,也是站在了巨人的
肩膀上,敏捷依然保持了很多历史悠久的实践和原则,只是表现方式不同罢了。
从另一个方面来看,方法本没有好环,好与坏取决于是否适合解决你的问题。每一种方
法都有他最善于解决的问题和最佳的发挥环境,在需求稳定、软件复杂度相对不高的时代,
瀑布模型也可以工作的很好,而敏捷恰好适用于变化快风险高的项目 - 这恰恰是现在很多
项目的共性。
因此选择一个方法或过程,并不是根据它是否敏捷,而应根据它是否适合。而要了解一
个东西是否适合,还是要尝试之后才知道,任何没有经过实践检验的东西都不可信。
误解四 :敏捷就是 ****XP ( 极限编程 ), 就是 ****Scrum
XP 和 Scrum 只是众多敏捷方法中的两种,还有很多其他的敏捷方法。龙生九子各个
不同,敏捷的这些方法看起来差别也是很大的,可是他们之所以被称为敏捷方法,就是因为
他们背后的理念和原则都是相同的,这个原则就是《敏捷宣言》。学习敏捷不仅仅要学习实
践,还要理解实践后的原则,不仅要理解怎么做,还要理解为什么这么做,以及什么时候不
要这么做。
即使将 XP 或 Scrum 完全的应用的你的项目中,也未见得就能成功,适合别人的东西
未必就适合你。敏捷的这些实践和方法给了我们一个起点,但绝对不是终点,最适合你的方
式还要由你自己在实际工作中探索和寻找。
误解五 :敏捷很好 , 因此我要制定标准, 所有项目都要遵循着个标准
没有哪两个项目是一样的,客户是不一样的,人员是不一样的,需求是不一样的,甚至
没有什么可能是一样的。不一样的环境和问题,用同样的方法解决,是不可能解决的好的。
方法是为人服务的,应该为项目团队找到最适合他们的方法,而不是先确定方法,再让团队
适应这个方法。因此也不存在适合所有项目的统一的方法。任何企图统一所有项目过程的方
法都是不正确的。
同时,对于同一个团队,随着项目的进行,对需求理解的深入,对技术理解的深入,一
开始适合项目的过程和方法也会渐渐的不适合。这时候也需要团队对过程进行及时的调整,
保证项目的质量和效率。敏捷是动态的,而非静止不变的,因为这个世界本身就是变化的,
在变化的世界使用不变的方法,是不现实的。银弹从来就没有过,在有限的将来也不会存在。