敏捷开发(Agile development)

2019-08-12 16:45:52 浏览数 (1)

敏捷开发是一种以人为核心、迭代、循序渐进的开发方法。在敏捷开发中,软件项目的构建被切分成多个子项目,各个子项目的成果都经过测试,具备集成和可运行的特征。换言之,就是把一个大项目分为多个相互联系,但也可独立运行的小项目,并分别完成,在此过程中软件一直处于可使用状态。

Test-Driven Development,测试驱动开发。

  它是敏捷开发的最重要的部分。在ThoughtWorks,我们实现任何一个功能都是从测试开始,首先对业务需求进行分析,分解为一个一个的Story,记录在Story Card上。然后两个人同时坐在电脑前面,一个人依照Story,从业务需求的角度来编写测试代码,另一个人看着他并且进行思考,如果有不同的意见就会提出来进行讨论,直到达成共识,这样写出来的测试代码就真实反映了业务功能需求。接着由另一个人控制键盘,编写该测试代码的实现。如果没有测试代码,就不能编写功能的实现代码。先写测试代码,能够让开发人员明确目标,就是让测试通过。

Continuous Integration,持续集成。

  在以往的软件开发过程中,集成是一件很痛苦的事情,通常很长时间才会做一次集成,这样的话,会引发很多问题,比如 build未通过或者单元测试失败。敏捷开发中提倡持续集成,一天之内集成十几次甚至几十次,如此频繁的集成能尽量减少冲突,由于集成很频繁,每一次集成的改变也很少,即使集成失败也容易定位错误。一次集成要做哪些事情呢?它至少包括:获得所有源代码、编译源代码、运行所有测试,包括单元测试、功能测试等;确认编译和测试是否通过,最后发送报告。当然也会做一些其它的任务,比如说代码分析、测试覆盖率分析等等。在我们公司里,开发人员的桌上有一个火山灯用来标志集成的状态,如果是黄灯,表示正在集成;如果是绿灯,表示上一次集成通过,开发人员在这时候获得的代码是可用而可靠的;如果显示为红灯,就要小心了,上一次集成未通过,需要尽快定位失败原因从而让灯变绿。在持续集成上,我们公司使用的是自己开发的产品CruiseControl。

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,可调整计划。

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

项目的敏捷开发方法

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

敏捷开发小组主要的工作方式可以归纳为:作为一个整体工作; 按短迭代周期工作; 每次迭代交付一些成果; 关注业务优先级; 检查与调整。下图是典型的敏捷过程总图,下面介绍其有关的特点。

1、敏捷小组作为一个整体工作

  项目取得成功的关键在于,所有项目参与者都把自己看成朝向一个共同目标前进的团队的一员。“扔过去不管”的心理不是属于敏捷开发。设计师和架构师不会把程序设计“扔”给编码人员;编码人员也不会把只经过部分测试的代码“扔”给测试人员,一个成功的敏捷开发小组应该具有“我们一起参与其中的思想”, “帮助他人完成目标”这个理念是敏捷开发的根本管理文化。当然,尽管强调一个整体,小组中应该有一定的角色分配,各种敏捷开发方法角色的起名方案可能不同,但愿则基本上是一样的。第一个角色是产品所有者,他的主要职责包括:确认小组成员都在追求一个共同的目标前景;确定功能的优先等级,以便总是处理最有价值的功能;作出可以使项目的投入产生良好回报的决定。产品所有者通常是公司的市场部门或者产品管理部门的人员,在开发内部使用的软件的时候,产品所有者可能是用户、用户的上级、分析师,也可能是为项目提供资金的人。

  2、敏捷小组按短迭代周期工作

在敏捷项目中,总体上并没有什么上游阶段、下游阶段,你可以根据需要定义开发过程在初始阶段可以有一个简短的分析、建模、设计,但只要项目真正开始,每次迭代都会做同样的工作(分析、设计、编码、测试。等等)。迭代是受时间框限制的,也就是说即使放弃一些功能,也必须结束迭代。时间框一般很短,大部分是 2~4周,在 Scrum中采用的是 30个日历天,也就是 4 周。迭代的时间长度一般是固定的,但也有报告说,有的小组在迭代开始的时候选择合适的时间长度。

  3、敏捷小组每次迭代交付一些成果

  比选择特定迭代长度更重要的,是开发小组在一次迭代中要把一个以上的不太精确的需求声明,经过分析、设计、编码、测试,变成可交付的软件(称之为功能增量)。当然并不需要把每次迭代的结果交付给用户,但目标是可以交付,这就意味着每次迭代都会增加一些小功能,但增加的每个功能都要达到发布质量。每次迭代结束的时候让产品达到可交付状态十分重要,但这并不意味着要完成发布的全部工作,因为迭代的结果并不是真正发布产品。假定一个小组需要在发布产品之前对软硬件进行为期两个月的“平均无故障时间”(MTBF)测试,他们不可能缩短这两个月的时间,但这个小组仍然是按照 4 周迭代,除了MTBF测试,其它都达到了发布状态。

  4、敏捷小组关注业务优先级

  敏捷开发小组从两个方面显示出他们对业务优先级的关注。首先,他们按照产品所有者制定的顺序交付功能,而产品所有者一般会按照组织在项目上的投资回报最大化的方式来确定优先级,并且把它组织到产品发布中去。要达到这个目的,需要综合考虑开发小组的能力,以及所需功能的优先级来建立发布计划。在编写功能的时候,需要使工能的依赖性最小化。如果开发一个功能必须依赖其它 3 个功能,那产品所有者这就很难确定功能优先级。功能完全没有依赖是不太可能的,但把功能依赖性控制在最低程度还是相当可行的。

  5、敏捷小组检查与调整

  任何项目开始的时候所建立的计划,仅仅是一个当前的猜测。有很多事情可以让这样的计划失效:项目成员的增减,某种技术比预期的更好或更差,用户改变了想法,竞争者迫使我们做出不同的反应,等等。对此,敏捷小组不是害怕这种变化,而是把这种变化看成使最终软件更好地反映实际需要的一个机会。每次新迭代开始,敏捷小组都会结合上一次迭代中获得新知识做出相应调整。如果认为一些因素可能会影响计划的准确性,也可能更改计划。比如发现某项工作比预计的更耗费时间,可能就会调整进展速度。也许,用户看到交付的产品后改变了想法,这就产生反馈,比如他发现他更希望有另一项功能,或者某个功能并不像先前看得那么重。通过先期发布增加更多的用户希望的功能,或者减少某些低价值功能,就可以增加产品的价值。迭代开发是在变与不变中寻求平衡,在迭代开始的时候寻求变,而在迭代开发期间不能改变,以期集中精力完成已经确定的工作。由于一次迭代的时间并不长,所以就使稳定性和易变性得到很好的平衡。在两次迭代期间改变优先级甚至功能本身,对于项目投资最大化是有益处的。从这个观点来看,迭代周期的长度选择就比较重要了,因为两次迭代之间是提供变更的机会,周期太长,变更机会就可能失去;周期太短,会发生频繁变更,而且分析、设计、编码、测试这些工作都不容易做到位。综合考虑,对于一个复杂项目,迭代周期选择4周还是有道理的。

  MIT Sloan Management Review(麻省理工学院项目管理评论)所刊载的一篇为时两年对成功软件项目的研究报告,报告指出了软件项目获得成功的共同因素,排在首位的是迭代开发,而不是瀑布过程。其它的因素是:

  1、至少每天把新代码合并到整个系统,并且通过测试,对设计变更做出快速反应。

  2、开发团队具备运作多个产品的工作经验。

  3、很早就致力于构建和提供内聚的架构。

  从这个报告中所透露出的信息告诉我们,认真研究敏捷过程对软件项目的成功是非常有意义的,它的意义在于:

  1)给开发小组的自组织提供了机会

  经典项目管理就好比一个具备中央调度服务的航空管理系统,这个系统是自治的,而且是封闭的,但现实中更庞大的系统,似乎并不属于中央调度控制系统,但也同样也是有效的。假如我们开车到某个地方,我们可以任意选择所需要的路线,我们甚至不需要准确计算停车,只要我们遵守交通法规,驾驶员可以临时根据路况改变某个转弯点,在驾驶游戏规则的框架内,依照自身最大利益做出决策。成千上万的驾驶者,并不需要中央控制和调度服务,人们仅仅在简单的交通法规的框架内,就可以完成综合起来看是更庞大的目标,很多事情从管理的角度只要抓住关键点,并不需要多么复杂的规则,往往会更有效。随着系统复杂度的提高,中央控制和调度系统面临崩溃。仔细研究交通系统的特点,我们会发现这样的系统中独立的个体在一组适当的规则下运行,并不需要设计每个个体临时变更的方案,而每个个体只需要知道目标和大致的状况,他们完全可以利用自己的聪明才智来决定自己的行为。

  2)缩短了反馈通道

  敏捷过程有效运作的另一个原因是,它极大的缩短了用户与开发者、预测目标与实施状况、投资与回报之间的反馈回路。在面对不断变化的市场、业务过程以及不断发展的技术状态的时候,便需要有一种方法在比较短的时间内发展完善。事实上,所有的过程改进都不同程度的使用着戴明循环,以研究问题、测试解决方案、评估结果,进而根据已知的事实来进行改进,这就称之为基于事实的决策模式,我们都知道,这比前端预测的决策方式更加有效。

  3)易于集思广益

  敏捷过程能有效应用的另一个原因在于,它可以就一个问题集思广益。我们的经验告诉我们当一个问题发生的时候,总有某些人员知道问题所在,但他的观点却遭到忽视。例如航天飞机在起飞阶段发生爆炸,事后分析出了各种原因,但这种调查也提供给我们一个惊人的事实,就是部分工程师早就意识到这些潜在问题,却无法说服他人重视这个担忧。对这些事实的深入思考,促使我们研究我们应该采取何种管理系统,使前线工作人员的经验、观点及担忧得到充分的重视呢?

0 人点赞