4/13/2009

几种比较常见的敏捷编程方法

◆极限编程(XP)
这种方法强调的是适应性,而不是可预测性。它最适合这种场合: 公司并不确切知道自己需要什么样的最终产品。这种方法最先由Kent Beck采用。

◆Scrum
这种方法强调的是重新开始迭代过程,而不是企图补救问题。它最适合这种场合: 公司在使用新工具,以及应用软件在开发过程中几乎肯定会变化。1993年,Jeff Sutherland在Easel Corporation最先使用了Scrum方法。

◆自适应软件开发(ASD)
这种方法强调的是速度和灵活性。它最适合这种场合: 公司需要应用软件能够迅速见效,还能随客户使用需求的增长而灵活变化。这种方法的发明者是Jim Highsmith。

◆动态系统开发方法(DSDM)
这种方法最初来源于强调用户参与的快速应用软件开发(RAD)技术。它最适合于在开发人员不是非常了解环境的情况。1990年,DSDM联合会在英国发明了这种方法,旨在综合编程最佳实践方面的经验。

◆功能驱动开发(FDD)
这种方法强调的是可预测性以及遵守开发最佳实践。它最适合以下场合: 开发团队必须开发具有特定功能及可读性高于正常水平的应用软件。1997年,Jeff De Luca最早发明了这种方法,旨在满足当时一家新加坡大银行的需求。

敏捷开发的观点总结与体会

敏捷的三个要素是迭代开发、坦诚合作和自适应性。
迭代开发:把功能进行小粒度的分割,采用迭代和增量式的开发方法,时间段是按周而不是按月进行度量。频每交付使用,而不是等待项目开发完成一次性提交。这样也就能有比较明显的阶段性成果,可以按周交付新功能。这对于Web应用程序尤其适合。持续性的更新,可使用户有新鲜感,提高其访问频度和使用次数。也有助于开发人员根据用户的反馈数据,应对需求的变更,及时做出响应与改进。
  坦诚合作:以我来说,做为开发人员,合作应该主要是有两类:一类是与开发人员的合作,另一类是与业务人员。与业务人员的合作很容易理解,能做到一起紧密工作,可使得产品更能切合实际的需求。而不是作完需求分析后,就将他们一脚踢开,直至产品交付。以往所做项目都不算大,几个人而已,合作也是分模块分别开发再整合。所以与开发人员的合作体会还不是很深,没看出敏捷开发有什么明显的改善。 自适应性:这一点让我有耳目一新的感觉。其实像Web2.0这类互联网应用,现实不断发展与变化,需求也在不断改变,未来状态难以预测,也就很难提前用一个文档来规范所有的开发行为。自适应方法就是不断变化的现实情况,来及时作出改变。这也就需要信任开发人员的能力,给其更多的活动空间。相信对于一个合格的开发人员,这也会有助于调动其主观能动性,以更加积极的态度来参与开发。软件开发更象是拍一场电影,而不是建楼房。项目经理是导演,剧本是已定的。但在拍摄中,是要调动出演员的表演才能,而不是指挥一群木偶。
认识的几个误区:1. 敏捷是“一个”过程
敏捷不是一个过程,是一类过程的统称,它们有一个共性,就是符合敏捷价值观,遵循敏捷的原则。敏捷的价值观如下:* 个体和交互 胜过 过程和工具* 可以工作的软件 胜过 面面俱到的文* 客户合作 胜过 合同谈判* 响应变化 胜过 遵循计划
由价值观引出的12条敏捷原则:1 我们最优先要做的是通过尽早的、持续的交付有价值的软件来使客户满意。2 即使到了开发的后期,也欢迎改变需求。敏捷过程利用变化来为客户创造竞争优势。3 经常性地交付可以工作的软件,交付的间隔可以从几个星期到几个月,交付的时间间隔越短越好。4 在整个项目开发期间,业务人员和开发人员必须天天都在一起工作。5 围绕被激励起来的个体来构建项目。给他们提供所需的环境和支持,并且信任他们能够完成工作。6 在团队内部,最具有效果并且富有效率的传递信息的方法,就是面对面的交谈。7 工作的软件是首要的进度度量标准。8 敏捷过程提倡可持续的开发速度。责任人、开发者和用户应该能够保持一个长期的、恒定的开发速度。9 不断地关注优秀的技能和好的设计会增强敏捷能力。10 简单——使未完成的工作最大化的艺术——是根本的。11 最好的构架、需求和设计出自于自组织的团队。12 每隔一定时间,团队会在如何才能更有效地工作方面进行反省,然后相应地对自己的行为进行调整。 建立敏捷联盟的17位大师所创立的敏捷方法包括:极限编程,Scrum,特征驱动开发,动态系统开发方法,自适应软件开发,水晶方法,实用编程方法。这些方法统称为敏捷方法。
其实每个人都可以从敏捷宣言和原则出发,明确问题,找出一些解决方法,形成自己的过程。我觉得国内的软件环境这么复杂,程序员的自主精神又这么强,敏捷方法应该是在中国首先提出才对,只是国人都有唯标准唯规范至上的心理定式,即使找出好办法,也觉得不规范,没有深入形成理论,无法提升高度,始终是跟着鬼子屁股后面走,我想这也是国外软件行业不成熟的表现之一吧。 2. 敏捷仅仅是一个软件过程如果仅仅从软件过程的角度去认识敏捷实施敏捷,效果不会太好。敏捷相对以前的软件工程最大的革新之处在于把人的作用提高到了过程至上,正如敏捷宣言的第一条“个体和交互胜过过程和工具”所说的。涉及到人的问题,就已经不再是过程所能覆盖的了,就到了企业管理的层面上了,包括企业的价值观和文化。这也是敏捷在国内实施的最大障碍:把客户当作合作伙伴而不是对手,从客户角度出发去想问题,充分的跟客户沟通,而不是出了问题推诿责任。目标是让软件实现客户的价值,而不是收钱就完事儿。把人的能动性调动起来,给动力而不是给压力。要实用而不是要规范。让开发人员理解并实施,体验到敏捷的好处,而不是盲目机械地实施规范。没有绝对的权威,每个人都有可取之处。3. 迭代就是敏捷,UP属于敏捷。看到这么多人都把UP归入敏捷,我都开始怀疑是不是自己搞错了。但是在我的印象中:UP是重型的过程,虽然引入了迭代,但是其原则和价值观与敏捷是不同的。敏捷注重的是反馈,迭代周期尽量的短,重在客户的参与,通过客户的参与,获取持续的反馈,不断调整使整个项目走在正确的方向上。同时也给客户一个感受和思考的机会,因为对于大多数客户而言,目标是明确的(不排除有些客户目标也不明确),但是具体怎么做,开始时是没有想法的,只有看到具体的东西的时候,才知道“噢,原来可以这样,那我想把这里调整一下”。4. 敏捷是彻底革命的。敏捷,特别是XP,让人有耳目一新的感觉,觉得以前的所有软件工程理论,设计方法都可以抛弃掉了,推翻一切,从头再来。抱着这种想法实施敏捷,那就错了,敏捷不是“石头里蹦出个孙大圣”,以前的软件过程中也有敏捷的影子,只是没有像敏捷一样上升到价值观和原则的高度,比如快速原型法。敏捷是在对已有的软件过程方法的改进,抛弃的是传统软件工程低效的外表,以往的软件过程中很多技巧都是很实用的。实施敏捷应该以现有的软件过程为基础,从敏捷宣言和原则出发,利用敏捷的方法来改善过程。5. 敏捷是反文档的。文档只是为了达成目标的一种手段,如果这种手段是低效的,那就换一种手段。可是完全抛弃了文档,怎样解决沟通的问题?难道你想每次沟通都完全用手比划,用嘴说,跟不同的人重复表述同样的想法,那样更是低效的。应该清楚文档的本质是把知识显性化。在一个项目中存在很多需要沟通的知识,知识具备两种形态,显性的和隐性的,传统的观念是尽量把隐性知识显性化,即文档化,而忽略了这其中的代价(特别是更新同步文档的代价)。因此,在实施敏捷的时候,需要在团队内明确哪些知识是必须显性的,这些知识可以通过文档交流。哪些知识是可以隐性的,这些知识则完全可以通过口头的方式进行交流,以达到沟通的最佳效率。文档不是目的,有效沟通才是目的。6. 为了敏捷而敏捷“嗯,敏捷这么好,我们也敏捷吧”,可能很多人会有这种想法。忘了以前是在哪儿看的大师采访录:Q:“我们现有的过程很好,不知道怎么用敏捷改进?”A:“既然很好,那就不要用敏捷”。做什么事情都要有明确目标的,敏捷虽好,得看你需不需要,能不能解决你现在头疼的问题,如果不是,那就不
要给自己找麻烦了。7. 敏捷是CMM的反义词在桂林会议的讨论中,很多人把CMM作为敏捷的反义词,我觉得这不是很合适。CMM只是一种衡量软件成熟度的标准,并非过程,和敏捷不是一类概念。如果要给敏捷找一个反义词,我觉得传统的瀑布式开发应该更合适一些。并且,我认为,如果CMM还能继续流行下去的话,应该会有公司可以用敏捷改善的过程通过CMM认证。8. 敏捷是自由的,无约束的。
敏捷强调的是自组织团队,发挥人的能动性,以动力代替压力,让人有绝对自由的错觉。但是应该清楚,凡是都是要讲究一个平衡,人也是两面的,消极的一面和积极的一面同时并存,绝对的自由会放纵人消极的一面。敏捷并非是绝对自由,无约束的。作为管理者,有一个职责,就是引导团队成员用自己积极的一面去压制消极的一面,不能放任团队中出现搭便车的现象,否则将打击整个团队的士气。如果实在无效,那就只能将其排除出团队了,这个惩罚够有约束力吧?9. 重做就是重构
重做不等于重构,很多场合这两个概念是混淆的。但是在敏捷中,重构的一个特征是必须可控的。当对系统结构进行大的调整时,如果没有测试驱动辅助的话,那么可控性就会很差,这不能叫做重构。

敏捷开发过程中容易出现的问题有时在敏捷开发中,反而不觉得有多敏捷,进度一拖再拖,问题一个接着一个,让我觉得我们是在进行慌乱开发为什么会这样?
  杀手一: 管理者的执行力不够
  据我观察,目前项目中,开发者或者说参与人的状态是混乱的,或者说是慌乱的。那问题在哪里呢?是我们的工作流程出了问题?不应该啊。我们在项目启动前已经定了一个看似美好的流程啊,而且是经过参与人讨论一致通过的。那么问题在哪里呢?昨天,一位产品专员在跟进项目时没有按照流程走,当我跟他讲起那个美好的流程的时候,他竟然说我不知道有这个流程啊! 问题出现了,原来是沟通、传达出了问题。同样的问题也出现在了另一位产品经理上,我们聊起进度时,他讲到似乎觉得目前的进度不可控,和他探讨不可控的原因(我很开心他愿意和我交流,也很感谢他能给我这个机会发表我对项目管理方面的看法,因为我曾被其他的产品er伤害多次),我说他的执行力不够,然后给了他一些如果是我我会怎样怎样之类的建议,希望能对他以及我们的项目有所帮助。
  解决办法:加大执行力,今日事今日毕,这是必须的。
杀手二:无法预测的风险
  这个问题还是原于我和那位产品经理的谈话,我们在分析进度不可控的原因时,他提到了这样一个问题:当他跟踪开发人员的进度,并询问为什么没有按照进度进行时,得到的回答是我开始没有想到有这么多 。OK,问题出来了,为什么没有想到有这么多?项目开始前的进度计划是开发人员自己定的,那么在项目开始前,他应该是给自己预留了一些机动的、预备性的风险时间吧,难道他没有么?我们不知道。那如果我现在问抛开你没想到的那些,你开始想到的东西是按进度进行的么?恐怕得到的回答也未必是令人满意的吧,那么难道这句没有想到难道是个托辞么?希望不是。
  解决办法:充分意识到项目中可能会存在的风险因素,在制定计划时预留一定的时间,如果在项目进行中出现了没有想到的问题,根据其重要性,考虑压后解决,要在计划的时间内把计划的事情完成好,并为后续解决问题争取更多的时间。
杀手三:团队的做事风格
  这个问题应该是因团而异的,so,我只讲我不喜欢的风格。
  1、我们抛开以前的……现在开始……
  这可以说是作为个人来讲在目前的开发过程中最讨厌的一句话, 这句话意味着凡事不求原因,只求结果,也许这是敏捷开发带来的恶果(可怜的敏捷开发-_-),但更多的原因应该是做事的风格问题,我极厌恶这种不问原因的做法。请放心,如果你的团队在开发过程中出现了这句话,他一定会出现第二次、第三次。。。。请耐心等待
  解决办法:发现问题,及时找到产生问题的原因,制定相应的解决办法,并在后续的开发过程中尽量避免发生同样的问题。
  个人觉得好的开发过程应该是这样的:
  1、有一个优化的工作流程
  2、有一个良好的项目计划(包括风险的预测)
  3、有一个良好的做事风格
  4、有一个执行力强的头头
  5、有一个平稳的心态,不要慌
常见程序开发人员的一些常见通病:
[*]消极:不愿意修改bug,不愿意改代码以满足用户新提出的需求[*]焦虑:担心刚刚修改的代码会破坏已有功能,对下一个版本能否正常工作毫无信心,梦到测试人员报告其大量bug[*]易怒:经常对测试mm发火,私下里诅咒客户,抱怨别人弄坏了自己的程序[*]神经质:系统偶尔出现奇怪行为就胡乱猜测,改了不该改的地方导致更多奇怪现象出现[*]那段日子简直不堪回首,是对程序员身心的双重折磨![*]需求变化频繁:敏捷的口号就是"拥抱变化",有单元测试作保障,让变化来的更多些吧
建议:
勇气:单元测试是自动化的回归测试,她让我对自己的代码充满自信,每一个测试就像攀岩者钉在峭壁上的一个楔子,没有了程序衰退的担心,于是我可以大胆的重构、积极的拥抱变化;快速反馈:每写一段代码,我都可以在几秒钟之内看到他的运行效果,免去了打包、部署、重起server以及在一堆日志里找结果的工作,开发的效率极大提高;
测试驱动设计:通过编写测试可以准确的理解需求、发现问题、发现接口,在不知不觉间做出最合理的设计;文档:测试是最好的详细设计文档,不会过时、可运行。
从瀑布模型向增量开发模型转变,那么如何才能在转变的

Test-Driven Development,测试驱动开发,它是敏捷开发的最重要的部分。在ThoughtWorks,我们实现任何一个功能都是从测试开始,首先对业务需求 进行分析,分解为一个一个的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,关于这个话题,钱钱同学有一篇很有名的文章对它进行介绍,名为Pair Programming (结对编程)。Stand up,站立会议。每天早上,项目组的所有成员都会站立进行一次会议,由于是站立的,所以时间不会很长,一般来说是15-20分钟。会议的内容并不是需求分 析、任务分配等,而是每个人都回答三个问题:1. 你昨天做了什么?2. 你今天要做什么? 3. 你遇到了哪些困难?站立会议让团队进行交流,彼此相互熟悉工作内容,如果有人曾经遇到过和你类似的问题,那么在站立会议后,他就会和你进行讨论。

Frequent Releases,小版本发布。在敏捷开发中,不会出现这种情况,拿到需求以后就闭门造车,直到最后才将产品交付给客户,而是尽量多的产品发布,一般以 周、月为单位。这样,客户每隔一段时间就会拿到发布的产品进行试用,而我们可以从客户那得到更多的反馈来改进产品。正因为发布频繁,每一个版本新增的功能 简单,不需要复杂的设计,这样文档和设计就在很大程度上简化了。又因为简单设计,没有复杂的架构,所以客户有新的需求或者需求进行变动,也能很快的适应。

Minimal Documentation,较少的文档。其实敏捷开发中并不是没有文档,而是有大量的文档,即测试。这些测试代码真实的反应了客户的需求以及系统API 的用法,如果有新人加入团队,最快的熟悉项目的方法就是给他看测试代码,而比一边看着文档一边进行debug要高效。如果用书面文档或者注释,某天代码变 化了,需要对这些文档进行更新。一旦忘记更新文档,就会出现代码和文档不匹配的情况,这更加会让人迷惑。而在敏捷中并不会出现,因为只有测试变化了,代码 才会变化,测试是真实反应代码的。 这时有人会问:代码不写注释行吗?一般来说好的代码不是需要大量的注释吗?其实简单可读的代码才是好的代码,既然简单可读了,别人一看就能够看懂,这时候 根本不需要对代码进行任何注释。若你觉得这段代码不加注释的话别人可能看不懂,就表示设计还不够简单,需要对它进行重构。

Collaborative Focus,以合作为中心,表现为代码共享。在敏捷开发中,代码是归团队所有而不是哪些模块的代码属于哪些人,每个人都有权利获得系统任何一部分的代码然 后修改它,如果有人看到某些代码不爽的话,那他能够对这部分代码重构而不需要征求代码作者的同意,很可能也不知道是谁写的这部分代码。这样每个人都能熟悉 系统的代码,即使团队的人员变动,也没有风险。

Customer Engagement ,现场客户。敏捷开发中,客户是与开发团队一起工作的,团队到客户现场进行开发或者邀请客户到团队公司里来开发。如果开发过程中有什么问题或者产品经过一个迭代后,能够以最快速度得到客户的反馈。

Automated Testing ,自动化测试。为了减小人力或者重复劳动,所有的测试包括单元测试、功能测试或集成测试等都是自动化的,这对QA人员提出了更高的要求。他们要熟悉开发语 言、自动化测试工具,能够编写自动化测试脚本或者用工具录制。我们公司在自动化测试上做了大量的工作,包括Selenium开源项目。

Adaptive Planning,可调整计划。敏捷开发中计划是可调整的,并不是像以往的开发过程中,需求分析->概要设计->详细设计->开发- >测试->交付,每一个阶段都是有计划的进行,一个阶段结束便开始下一个阶段。而敏捷开发中只有一次一次的迭代,小版本的发布,根据客户反馈 随时作出相应的调整和变化。

敏捷开发过程与传统的开发过程有很大不同,在这过程中,团队是有激情有活力的,能够适应更大的变化,做出更高质量的软件。