Agile敏捷开发

Wiki: http://en.wikipedia.org/wiki/Agile_software_development

在按照我的理解方式审查了软件开发的生命周期后,我得出一个结论:实际上满足工程设计标准的惟一软件文档,就是源代码清单。

-- Jack Reeves

简介

2001年,为了解决许多公司的软件团队陷入不断增长的过程泥潭,一批业界专家一起概括出了一些可以让软件开发团队具有快速工作、响应变化能力的价值观和原则,他们称自己为敏捷联盟。敏捷开发过程的方法很多,主要有:SCRUM,Crystal,特征驱动软件开发(FeatureDrivenDevelopment,简称FDD),自适应软件开发(AdaptiveSoftwareDevelopment,简称ASD),以及最重要的极限编程(eXtremeProgramming,简称XP)。极限编程(XP)是于1998年由Smalltalk社群中的大师级人物KentBeck首先倡导的。

极限编程

  设计和编程都是人的活动。忘记这一点,将会失去一切。
-- Bjarne Stroustrup

极限编程(XP)是敏捷方法中最著名的一个。它是由一系列简单却互相依赖的实践组成。这些实践结合在一起形成了一个胜于部分结合的整体。

下面是极限编程的有效实践:
  1. 完整团队 XP项目的所有参与者(开发人员、客户、测试人员等)一起工作在一个开放的场所中,他们是同一个团队的成员。这个场所的墙壁上随意悬挂着大幅的、显著的图表以及其他一些显示他们进度的东西。
  2. 计划游戏计划是持续的、循序渐进的。每2周,开发人员就为下2周估算候选特性的成本,而客户则根据成本和商务价值来选择要实现的特性。
  3. 客户测试作为选择每个所期望的特性的一部分,客户可以根据脚本语言来定义出自动验收测试来表明该特性可以工作。
  4. 简单设计团队保持设计恰好和当前的系统功能相匹配。它通过了所有的测试,不包含任何重复,表达出了编写者想表达的所有东西,并且包含尽可能少的代码。
  5. 结对编程所有的产品软件都是由两个程序员、并排坐在一起在同一台机器上构建的。
  6. 测试驱动开发编写单元测试是一个验证行为,更是一个设计行为。同样,它更是一种编写文档的行为。编写单元测试避免了相当数量的反馈循环,尤其是功功能能验证方面的反馈循环。程序员以非常短的循环周期工作,他们先增加一个失败的测试,然后使之通过。
  7. 改进设计随时利用重构方法改进已经腐化的代码,保持代码尽可能的干净、具有表达力。
  8. 持续集成团队总是使系统完整地被集成。一个人拆入(Check in)后,其它所有人责任代码集成。
  9. 集体代码所有权任何结对的程序员都可以在任何时候改进任何代码。没有程序员对任何一个特定的模块或技术单独负责,每个人都可以参与任何其它方面的开发。
  10. 编码标准 系统中所有的代码看起来就好像是被单独一人编写的。
  11. 隐喻 将整个系统联系在一起的全局视图;它是系统的未来影像,是它使得所有单独模块的位置和外观变得明显直观。如果模块的外观与整个隐喻不符,那么你就知道该模块是错误的。
  12. 可持续的速度 团队只有持久才有获胜的希望。他们以能够长期维持的速度努力工作,他们保存精力,他们把项目看作是马拉松长跑,而不是全速短跑。 极限编程是一组简单、具体的实践,这些实践结合在形成了一个敏捷开发过程。极限编程是一种优良的、通用的软件开发方法,项目团队可以拿来直接采用,也可以增加一些实践,或者对其中的一些实践进行修改后再采用。

 敏捷开发  人与人之间的交互是复杂的,并且其效果从来都是难以预期的,但却是工作中最重要的方面。

-- Tom DeMacro和Timothy Lister

敏捷软件开发宣言:

  • 个体和交互     胜过 过程和工具
  • 可以工作的软件 胜过 面面俱到的文档
  • 客户合作       胜过 合同谈判
  • 响应变化       胜过 遵循计划

虽然右项也有价值,但是我们认为左项具有更大的价值。

  • 我们最优先要做的是通过尽早的、持续的交付有价值的软件来使客户满意。
  • 即使到了开发的后期,也欢迎改变需求。敏捷过程利用变化来为客户创造竞争优势。
  • 经常性地交付可以工作的软件,交付的间隔可以从几个星期到几个月,交付的时间间隔越短越好。
  • 在整个项目开发期间,业务人员和开发人员必须天天都在一起工作。
  • 围绕被激励起来的个体来构建项目。给他们提供所需的环境和支持,并且信任他们能够完成工作。
  • 在团队内部,最具有效果并富有效率的传递信息的方法,就是面对面的交谈。
  • 工作的软件是首要的进度度量标准。
  • 敏捷过程提倡可持续的开发速度。责任人、开发者和用户应该能够保持一个长期的、恒定的开发速度。
  • 不断地关注优秀的技能和好的设计会增强敏捷能力。
  • 简单是最根本的。
  • 最好的构架、需求和设计出于自组织团队。
  • 每隔一定时间,团队会在如何才能更有效地工作方面进行反省,然后相应地对自己的行为进行调整。

当软件开发需求的变化而变化时,软件设计会出现坏味道,当软件中出现下面任何一种气味时,表明软件正在腐化。

  • 僵化性: 很难对系统进行改动,因为每个改动都会迫使许多对系统其他部分的其它改动。
  • 脆弱性: 对系统的改动会导致系统中和改动的地方在概念上无关的许多地方出现问题。
  • 牢固性: 很难解开系统的纠结,使之成为一些可在其他系统中重用的组件。
  • 粘滞性: 做正确的事情比做错误的事情要困难。
  • 不必要的复杂性: 设计中包含有不具任何直接好处的基础结构。
  • 不必要的重复性: 设计中包含有重复的结构,而该重复的结构本可以使用单一的抽象进行统一。
  • 晦涩性: 很难阅读、理解。没有很好地表现出意图。

敏捷团队依靠变化来获取活力。团队几乎不进行预先设计,因此,不需要一个成熟的初始设计。他们更愿意保持设计尽可能的干净、简单,并使用许多单元测试和验收测试作为支援。这保持了设计的灵活性、易于理解性。团队利用这种灵活性,持续地改进设计,以便于每次迭代结束生成的系统都具有最适合于那次迭代中需求的设计。为了改变上面软件设计中的腐化味,敏捷开发采取了以下面向对象的设计原则来加以避免,这些原则如下:

  • 单一职责原则(SRP)

    就一个类而言,应该仅有一个引起它变化的原因。

    开放-封闭原则(OCP)

软件实体应该是可以扩展的,但是不可修改。Liskov替换原则(LSP)

子类型必须能够替换掉它们的基类型。依赖倒置原则(DIP)

抽象不应该依赖于细节。细节应该依赖于抽象。接口隔离原则(ISP)

不应该强迫客户依赖于它们不用的方法。接口属于客户,不属于它所在的类层次结构。重用发布等价原则(REP)

重用的粒度就是发布的粒度。共同封闭原则(CCP)

包中的所有类对于同一类性质的变化应该是共同封闭的。一个变化若对一个包产生影响,则将对该包中的所有类产生影响,而对于其他的包不造成任何影响。共同重用原则(CRP)

一个包中的所有类应该是共同重用的。如果重用了包中的一个类,那么就要重用包中的所有类。无环依赖原则(ADP)

在包的依赖关系图中不允许存在环。稳定依赖原则(SDP)

朝着稳定的方向进行依赖。稳定抽象原则(SAP)

包的抽象程度应该和其稳定程度一致。

上述中的包的概念是:包可以用作包容一组类的容器,通过把类组织成包,我们可以在更高层次的抽象上来理解设计,我们也可以通过包来管理软件的开发和发布。目的就是根据一些原则对应用程序中的类进行划分,然后把那些划分后的类分配到包中。

下面举一个简单的设计问题方面的模式与原则应用的示例:

问题:

选择设计运行在简易台灯中的软件,台灯由一个开关和一盏灯组成。你可以询问开关开着还是关着,也可以让灯打开或关闭。

解决方案一:

下面图1是一种最简单的解决方案,Switch对象可以轮询真实开关的状态,并且可以发送相应的turnOn和turnOff消息给Light。

解决方案二:

上面这个设计违反了两个设计原则:依赖倒置原则(DIP)和开放封闭原则(OCP),DIP原则告诉我们要优先依赖于抽象类,而Switch依赖了具体类Light,对OCP的违反是在任何需要Switch的地方都要带上Light,这样就不能容易扩展Switch去管理除Light外的其他对象。为了解决这个方案,可以采用ABSTRACTSERVER模式,在Switch和Light之间引入一个接口,这样就使得Switch能够控制任何实现了这个接口的东西,这也就满足了DIP和OCP原则。如下面图2所示:

解决方案三:

上面图2所示解决方案,违返了单一职责原则(SRP),它把Switch和Light绑定在一起,而它们可能会因为不同的原因而改变。这种问题可以采用ADAPTER模式来解决,适配器从Switchable派生并委托给Light,问题就被优美的解决了,现在,Switch就可以控制任何能够被打开或者关闭的对象。但是这也需要会出时间和空间上的代价来换取。如下面图3所示:

  敏捷设计是一个过程,不是一个事件。它是一个持续的应用原则、模式以及实践来改进软件的结构和可读性的过程。它致力于保持系统设计在任何时间都尽可能得简单、干净和富有表现力。

敏捷开发实践迭代实施流程

从4月中旬开始,我们部门进行了破天荒有史以来第一次敏捷项目实践,两周的时间虽然 不长,但是整个团队感觉无论从技术上,还是沟通与合 

作上,都有很大收获。当然,还有很多我们事先没有想到的纰漏和问题,经过与团队每个成员的面谈,我为后续的迭代整理出了下列的优化流程。

说明:

◇在下面的流程中着重迭代开始的规划和迭代中,开发团队与测试团队的协作过程,对PO的review会议和回顾会议没有做详细阐述

◇本流程仅针对我们目前特有的项目,有些特征不具有一般性。

◇其中使用到的一些缩略用语

PM:项目经理/项目负责人/项目协调人

US/us:userstory

PB:productbacklog

PO:ProductOwner

1.PM根据上个迭代的结果,对已有的PB做修正,添加需要修正的BUG,未完成的us等,并提交给PO作为参考

2.PO根据PB和自己的业务需求,并根据优先级顺序,提出本次迭代希望完成的us和PB;并对这些us和PB的细节部分进行整理

3.PO将整理后的us和PB提交给PM

4.PM提前一天将po提交的文档作为planningmeeting会议提纲的一部分,分发给项目团队

5.项目团队成员仔细研究PO的需求,并记录自己针对业务需求和逻辑的想法或疑问

6.PRODUCTPLANNING会议

a)参与者:PO,PM,开发团队、测试团队

b)过程

i.项目团队对PO提出的需求进行讨论,并由会议记录人记录每个us的细节

ii.涉及到某个业务细节,讨论的时间不超过5分钟,并且最终拍板权在PO手中

c)会后

i.由会议记录人负责,将本次迭代涉及到的us其描述和相关细节,直接建立在部门内部的wiki中

记录形式:所有的us按照迭代的周期不同放在不同的page中,每个us以panel相包裹

7.ITERATIONPLANNING会议

a)参与者:PO(可选),PM,开发团队、测试团队

b)过程

i.根据us和记录的PB,对本次迭代的任务进行拆分和估算

ii.要考虑各个任务之间的前后逻辑关系,以确定优先顺序

注意:估算时,应该把DEBUG的时间也要考虑在内

iii.如果估算的时间超过了本次迭代的可用时间,那么PM找PO进行协调,请求放弃不能完成的US和PB

c)会后

i.会议记录人负责将会议中最后确定的任务分配情况提交给PM

ii.PM在jira中建立任务并分配到人

使用us作为jira中的COMPONENT

同时使用us作为一个task的名称,将与该us相关的任务作为subtask作为ustask的子问题

8.DBA可以开始考虑在数据库中进行建表等操作了

9.ITERATIONDESIGN会议

a)参与者:PM,开发团队、测试团队

b)过程

i.根据本次迭代要完成的任务,开发团队与测试团队确定每个us和PB要验收测试所涉及到的代码接口

ii.开发团队使用类图、顺序图等uml工具,对代码中的一些接口和调用方法进行名称的定义

iii.可以使用照相手机等工具,把白板上绘制的简要图表拍摄下来,并上传至部门的wiki中

10.PM准备一个项目变更日志,用来记录迭代中,某时间点发生的变化,包括下列内容

a)数据库字段的变化

b)us的细节的补充

c)......

注意:对该日志的访问必须方便和直观

下面进入开发阶段

11.开发团队

a)采用tdd的方式,完成各自的任务

b)每当一个任务中的细小任务完成,并确认在本地编译无错误,而且单元测试都可以通过后,才允许上传到ci服务器

c)上传完成后,开发人员要注意即时监控ci服务器的反应,如果有问题,马上进行解决

d)当开发人员确认自己的任务完成后,对应的subtask可以解决,并且记录工作实际完成时间

e)每个任务的完成,都有可能触发一次CODEREVIEW的过程

i.如果发现问题,或者需要对代码进行重构,在完成后,负责人要修正任务的实际工作完成时间

f)团队针对一项任务的CODEREVIEW结束,并且负责人修改完成后,该负责人可以针对自己剩余商未开始的任务,调整估算的时间,

12.测试团队

a)负责维护测试库

b)并且要根据与开发团队定义好接口,撰写针对每个us的自动化测试脚本,准备自动化测试的TESTSUITE

13.PM

a)当一个us相关的任务都完成后,PM修改jira中的ustask的状态,变更为"等待集成测试",并通知相关的开发人员和测试组马上对

该us进行集成测试,并在测试完成后,马上进入修正阶段

14.在这个过程中,如果任何人发现US有任何不完整的地方,都应马上与PM和PO进行协调和沟通,如果需要马上补漏的,发现者应该对wiki中

的相关us进行补充。如果不需要在本次迭代中进行考虑,那么PM应该记录到项目变更日志中

15.开发人员仍然要坚持每日立会,每日立会后,PM更新BURNDOWNCHART

16.项目中用到的一些特殊的技术,可以考虑在某日立会之后,用半个小时左右的时间,该技术的掌握者向整个团队分享该知识

进入迭代收尾阶段

17.所有的us都已经完成(测试团队完成验收测试,开发团队修正完毕并且无误)

18.POREVIEW会议

19.团队回顾会议

上面的任务分析过程中,每个分拆出来的任务,我认为都应该有对应的us,理由如下: 

◇如果没有,那么这个任务对于PO的业务价值在哪里体现呢?

◇在任务分析时,发现了某些隐藏的而又是必须完成的任务,那就说明,还有隐藏的us没有发现。这就需要找PO进行沟通,看这些隐藏的任务是否对其有价

值,如果有的话,那么就分析隐藏的us,并根据当前迭代的任务完成和分配情况,进行本迭代应完成的任务和us的调整

◇没有对应的us,没有与PO讨论,PO可能在将来经过缜密的思考后,提出的要求,目前的解决方案可能不能够满足,就增大了返工的几率

◇没有对应的us,测试组没有参与,那么一些验收测试的细节就很难得到充分的发掘;

◇除此之外,还有可能造成系统切分的粒度过粗,从而增加了这些没有us的功能代码和与其相关的功能代码之间的耦合度,由此可能带来的一系列后果:

◆针对这些无us的代码,没有自动化验收测试的脚本;测试组需要等到与这些代码相关的us的功能代码提交后再进行测试,从进度上讲,会延迟测试组

和开发人员的协同合作的时间,并延迟一些问题的暴露时机(我们都知道:问题暴露的时机越早,解决起来成本越低)。

◆针对这些无us的代码,大家的关注度和思维的缜密性可能不如有us的代码,那么在这对这些代码做tdd和debug的时候,投入相对较小,出现

纰漏的几率就变大了。当我们在开发或调试与其相关的代码的时候,对于发生的问题的定位,这些代码就会造成一定的困扰 

Agile

敏捷开发

Backlog

一项工作

Build

值软件编译构建好的一个可运行的版本

Burndown chart:

用来显示当前还剩下多少工作未完成的图形化工具。通常以时间为横轴,本次迭代要完成的工作为纵轴。

Code Review

代码审核,通常由非代码编写者完成。

Daily Scrum Meeting:

每日Scrum会议。每天15分钟的每日例会,每个人回答三个问题:上次例会到现在我完成了哪些工作;在下次例会前我将完成哪些工作;有没有什么事情阻碍了我的工作。

In Progress:

进行中

Product Backlog:

产品功能特性列表,主要由产品责任人负责维护并定义优先级。

Product Backlog Item:

产品功能特性列表中的条目,每个条目就是一个工作单元,大小必须限制在团队可以在一个迭代内完成,同时一个工作单元可以被分解成许多任务。

Product Owner:

产品责任人。负责确定Backlog中各条目的优先级,同时解决所有关于需求的问题。

Safari

苹果操作系统上的浏览器

Scrum

Scrum一词来自英式橄榄球,它把软件开发团队比作橄榄球队。Scrum是当今流行的敏捷开发方法之一。

Scrum Master

负责管理每日Scrum流程的人,是Product Owner和Team之间的桥梁,推动双方的合作,负责为Team成员解决障碍和问题,保证他们工作的进行。相当于传统项目的项目经理或主管。

代表Scrum的一次迭代,周期通常是30天。期间不能给Team增加额外的需求,确保迭代结束时能够获得预期的结果。

Sprint Planning Meeting:迭代开始之前的计划会议,由Team与Product Owner之间商讨本次迭代的目标,决定本次迭代要完成哪些工作。

Sprint Review Meeting:

Sprint评审会议。在迭代结束时召开,Team展示这个迭代中完成的功能,一般是以Demo本迭代中完成的功能的形式来展示。

Sprint Retrospective Meeting:   

Sprint回顾会议。在一个迭代的评审会议之后召开,由Team与ScrumMaster共同讨论这个迭代中哪些地方做得比较好,哪些地方需要改进。使团队持续成长。

Stakeholders:

利益相关者。项目成败对他们影响不大的一类人,参与提出产品的需求,积极提出反馈意见。

Sprint:

Task

任务

Team:

跨功能的Scrum团队,人数限制在5-9人,可能包括的角色有开发人员、架构师、测试人员、UI设计师等。是一个自组织的团队,他们自己决定如何最好地满足用户需求,并承担责任。

User Story:

用户故事(情景),从用户的角度,对系统的某个功能模块所做的简短描述。

wiki:

维基百科,是一种开放和共享的在线文档编辑系统,任何人都可以在系统中编辑修改文档。最早的应用是在线开放式的百科全书,现在广泛应用于各种文档系统。

相关推荐