极限编程简介
极限编程是以简单、沟通、反馈、勇气和尊重为价值观的软件工程方法学,是敏捷软件开发中应用最为广泛和最富有成效的几种方法学之一。如同其他敏捷方法学,极限编程和传统方法学的本质不同在于它更强调可适应性而不是可预测性。极限编程的支持者认为软件需求的不断变化是很自然的现象,是软件项目开发中不可避免的、也是应该欣然接受的现象;他们相信,和传统的在项目起始阶段定义好所有需求再费尽心思的控制变化的方法相比,有能力在项目周期的任何阶段去适应变化,将是更加现实更加有效的方法。
极限编程为管理人员和开发人员开出了一剂指导日常实践的良方;这个实践意味着接受并鼓励某些特别的有价值的方法。支持者相信,这些在传统的软件工程中看来是“极端的”实践,将会使开发过程比传统方法更加好的响应用户需求,因此更加敏捷,更好的构建出高质量软件。它的工作原理是将整个团队聚集在一起,进行简单的实践,并提供足够的反馈,使团队能够看到他们的现状,并根据他们的独特情况调整实践。
创始者是肯特·贝克、沃德·坎宁安和罗恩·杰弗里斯,作为几种流行的敏捷框架之一,它已经被证明在世界各地不同规模和行业的多数公司都非常成功。
发展历史
Kent Beck在克莱斯勒综合薪酬系统(C3)工资项目中开发了极端编程。Beck于1996年3月成为C3项目负责人。他开始完善项目中使用的开发方法论,并写了一本关于该方法论的书(《极限编程解释》,1999年10月出版)。在《极限编程解释》第二版(2004年11月)中,即在第一版五年后,Beck添加了更多的价值观和实践,并区分了基础实践和必需实践。
许多极限编程实践已经存在了一段时间;该方法将“最佳实践”提升到了极致。例如,早在20世纪60年代初,美国国家航空航天局的水星计划就采用了“在每次微增量之前先测试开发、规划和编写测试的做法”。为了缩短总的开发时间,一些正式的测试文档(如验收测试)与准备测试的软件并行开发。在程序员编写软件并将其与硬件集成之前,NASA独立的测试小组可以根据正式要求和逻辑限制编写测试程序。XP将这一概念发挥到了极致,编写了自动化测试(有时在软件模块内部),即使是软件编码的小部分也能验证其操作,而不仅仅是测试更大的功能。
价值观
沟通,极限程序员经常与他们的客户和程序员同事交流。每个人都是团队的一分子,每天面对面交流,并且将在从需求到代码的所有方面进行合作,共同创造最佳解决方案。
简单,团队保持自己的设计简洁明了,做恰好满足需要和要求做的事情,致力于投资价值的最大化。通过采取简单的步骤来实现团队的目标,减轻失败带来的影响。创造我们引以为豪的东西,并以合理的成本长期维护它。
反馈,团队通过从第一天开始测试软件来获得反馈。团队将通过交付可工作的软件认真对待每一次迭代承诺,尽早展示软件,然后经常仔细聆听反馈,并据此做出任何需要的更改。团队将讨论每个项目,并使我们的流程适应它,而不是背道而驰。
尊重,作为一名有价值的团队成员,每个人都给予并感受到了应有的尊重。每个人都贡献价值,哪怕只是热情。开发人员尊重客户的专业知识,反之亦然。管理层也尊重团队对自己的工作承担责任和获得权力的权利。通过尽早将系统交付给客户,并根据建议实施更改。每一次小小的成功都加深了他们对每一位团队成员独特贡献的尊重。
勇气,有了以上的基础,团队能够勇敢地响应不断变化的需求和技术,也将能够说出有关进度和估算的真相,不会为失败记录借口,大家共同聚焦于为成功而计划。团队无所畏惧,因为没有一个人是单兵作战。一旦变化发生,团队会立即适应。
极限编程项目过程全貌
极限编程核心实践
完整的团队
XP项目的所有贡献者都是这个团队的成员并且坐在一起工作。
该团队必须包括一名业务代表,即“客户”,负责提供需求、设定优先级并指导项目。客户或她的助手最好是一个真正的终端用户,熟知对应的业务领域并且知道具体需求。团队当然会有程序员,也可能包括测试人员,他们帮助客户定义客户验收测试。分析师可以充当客户的助手,帮助定义需求。通常还会有一位教练,他帮助团队保持在正轨上运行,并引导整个极限编程的过程。可能会有一名经理,负责提供资源、处理外部沟通、协调活动。
注意,这些角色都不必定专属于某个人:XP团队中的每个人都可以尽其所能做出贡献。最好的团队没有专家,只有具备特殊技能的普通贡献者。
规划游戏
XP规划解决了软件开发中的两个关键问题:预测截止日期将完成什么,以及确定下一步要做什么。这里的重点是指导项目,比准确预测需要什么和需要多长时间要简单得多。
XP中有两个关键的规划步骤,用于解决这两个问题:
发布计划(release planning)。客户向程序员展示所需的功能,程序员估算它们的复杂度。客户基于成本估算以及功能的重要性制定项目计划。最初的发布计划必然是不精确的:在团队开始工作之前我们不知道它们会以多快的速度进行,同时优先级和早期的估算都不是真正可靠的。同时,即使第一个发布计划的准确度足以支持决策,XP团队也会基于实际情况定期修改发布计划。
迭代规划(Iteration Planning)。XP团队在两周的“迭代”中构建软件,在每次迭代结束时交付运行可用的软件。在迭代规划过程中,客户将展示未来两周所需的功能。程序员将它们分解为任务,并估计它们的成本(颗粒度比发布计划中更详细)。根据过往迭代中完成的工作量,团队将针对当前迭代中要纳入的工作签署承诺。
这些规划步骤非常简单,但每隔几周总体的进度情况就完全展示出来,它们为客户提供了非常好的信息和出色的管控节奏。
在XP中没有“百分之九十完成”:一个功能故事要么已经完成,要么就是还没有完成。这种对可见性的关注产生了两种很好的结果:一方面,基于这样的可见性,如果进度不符合预期,客户就可以取消项目。另一方面,足够透明的进度为将来要完成什么提供更可靠的决策,以至于XP项目往往能以更少的压力和负担交付更多需求。
客户测试
作为展示每个所需功能的一部分,XP客户定义了一个或多个自动验收测试,以表明该功能是可工作的。团队构建这些测试,并使用它们向自己和客户证明该功能正确地被实现。自动化很重要,因为当项目的时间紧迫,常规的手动测试就会被跳过,团队因此妥协了质量,这就像夜晚最黑的时候关灯一样。
优秀的XP团队对待客户测试的方式与对待程序员测试的方式相同:一旦测试运行,团队就会保持测试正确地运行。这意味着系统只会改进,始终向前推进,从不倒退。
轻量发布
XP团队通过两种重要方式实践轻量发布:
首先,团队发布在运行中并且经过测试的软件,在每次迭代中交付客户选择的业务价值。客户可以将此软件用于无论是支持评估还是向最终用户发布(强烈建议)等任何目的。最重要的方面是,在每次迭代结束时客户都可以有一个看得见摸得着的软件,这使一切保持透明和真实。
其次,XP团队也会尽可能高频次地发布给终端用户。为了保证高频次发布的高质量,持续集成、用户测试和测试驱动开发等几个比较关键的实践,可以有效提升发布质量。
简约设计
XP团队构建简约但始终合乎需求的设计。从简单出发,随着程序员的测试增加,设计会不断改进,并且在产品开发过程中保持这种状态。XP团队使设计完全符合系统的当前设定的功能。没有浪费的行为,并且软件总是为下一次演进保持就绪的状态。
在XP中,设计不是一次性的,也不是提前就准备好的,而是贯穿项目始终的一项工作。发布计划和迭代计划活动中都有设计环节,此外,在整个项目过程中,团队还通过重构进行快速设计和设计修订。像极限编程这样的增量迭代交付,在整个开发过程中都非常注重设计。
结对编程
在XP过程中所有产出的软件都是由两个程序员并排坐在同一台机器上构建的。这种做法确保所有生产环境的代码至少由一名其他程序员审查,最直接的结果就是产生更好的设计、更好的测试和更好的代码。
让两个程序员做“一个程序员的工作”可能看起来效率很低,但事实恰恰相反。一项结对编程的研究表明在同等工时下,结对可以比两个程序员单独工作产生更好的代码。不仅平衡了后期修复质量所消耗的工时,同时也保护了用户体验。
结对除了提供更好的代码和测试外,还可以在整个团队中促进知识流通。随着结对对象的轮换,每个人都能从别人的专业知识中获益。程序员通过学习以提高他们的技能,从而对团队和公司更有价值。结对,即使是XP之外,对每个人来说都是一个巨大的收获。
测试驱动开发
极限编程痴迷于反馈,在软件开发中,良好的反馈需要良好的测试。不同于传统的开发过程:开发代码->编写测试->运行测试;
测试驱动开发的实践遵循以下路径:
编写失败的自动化测试->运行失败的测试->开发代码使测试通过->运行测试->重复。
优秀的XP团队实践“测试驱动开发”,在很短的时间周期内添加测试代码,然后使其工作,这样团队几乎毫不费力地生成了测试覆盖率接近100%的代码。这意味着程序员可以立即得到关于他们工作成果的反馈,并且这些测试也为软件设计的改进提供了宝贵的支持。
重构
极限编程专注于在每一次迭代中都提供业务价值。为了在整个项目中实现这一点,软件必须经过精心设计。重构过程的重点是消除重复,提高代码的“内聚性”,同时降低“耦合性”。至少三十年来,高内聚性和低耦合性一直被认为是设计良好的代码的标志。
XP团队从一个好的、简约的设计开始,并且总是有一个又好又简约的软件设计。这使他们能够保持自己的开发速度,并且随着项目向前推进通常会提高速度。
当然,重构得到了全面测试的有力支持,以确保随着设计的演进,没有任何东西被破坏。因此,客户测试和程序员测试是一个关键的使能因素。XP的各个实践是相互支持的:它们在一起组合比单独实施更强大。
持续集成
极限编程团队始终保持系统完全地集成,开发人员应该每隔几个小时将代码集成并提交到代码库中。在任何情况下,永远不要将更改保留超过一天。持续集成通常可以避免碎片化的开发工作,每个人都需要使用最新版本,而不应该基于导致集成问题的过时代码进行更改。
持续集成类似是一种“现在付一点钱,或晚点给更多钱”的行为。也就是说,如果你在整个项目中持续、高频地进行小规模集成,就不会在项目快截止的时候才发现需要花几周来集成系统代码,然后花不可预知的时间来修复层出不穷的缺陷,我们称之为“集成地狱”。
其精要在于,确保系统始终在最新版本中工作。
代码共有
在极限编程项目中,鼓励每个人为项目的各个部分贡献新的想法。任何开发人员都可以更改任何一行代码来添加功能、修复错误、改进设计或重构,而没有人会成为变更的瓶颈。这意味着所有代码都得到了更多人的关注,从而提高了代码质量并减少缺陷。
在实践中,集体共有实际上比让一个人专属负责某个模块更具有可靠性,尤其是人员随时可能离开项目。除了提升代码质量外,结对编程实践还可以在整个团队中传播知识。
编码标准
XP团队遵循一个通用的编码标准,因此系统中的所有代码看起来都像是由同一个非常有能力的个人编写的。这里要强调的是,标准的具体内容并不重要:重要的是所有的代码风格看起来都很相似,以一致的模式和风格进行编码,以便每个人都能阅读每个人的代码,保持系统始终运行和集成。
系统隐喻
极限编程团队开发了一个关于程序如何工作的共同愿景,我们称之为“隐喻”。这是对程序是怎样工作的简单比喻,比如作为对基于代理的信息检索系统的描述,其隐喻可以为“这个程序就像一个蜂巢,出去寻找花粉,然后把它带回蜂巢”。
系统隐喻本身就是对一个具有特定目标的简单设计,其目的是能够向新人不通过倾倒大量项目文件的方式解释系统。所以首先其本身应该有能帮助新人快速做出贡献的信息结构,其次是使命名类和方法要保持一致。
有时,可能没有一个足够诗意的隐喻,但是在任何情况下,无论有没有生动的图像,XP团队都会使用一个通用的名称系统,以确保每个人都了解系统是如何工作的,以及在哪里可以找到你想要的功能,或者找到你要添加的功能的正确位置。
可持续的速度
极限编程团队将长期在一起工作,并以一个能够长久持续的速度努力工作。现在人们很清楚,死亡行军式地推进项目既没有生产效益,也没有生产出高质量的软件。加班会耗尽团队的精神和动力。当你的团队变得疲惫和士气低落时,无论继续工作多少小时,他们“完成”的工作都会减少,而不是增加。今天的过度工作偷走了未来的发展进步。尤其是当你的团队本月工作量增加,下个月工作量减少时,你无法制定符合实际的计划。与其强迫人们做超出人类可能的事情,不如召开发布计划会议来改变项目范围或时间。
可持续的节奏有助于你规划发布和迭代,防止你陷入死亡行军。找到你的团队在整个项目中保持一致的完美速度,每个团队都不一样。
这个流程图显示了极限编程(XP)推荐的反馈循环或沟通渠道——在任何敏捷项目中都应该有很多。这些通信信道按照粒度和频率的螺旋排列。在适当的粒度内进行沟通是很重要的,不要因为在错误的观众面前过于铺陈详细而浪费沟通的带宽。
如何实施极限编程
开始实施极限编程(XP)最直接的方法是使用一个新项目。
从用几个星期收集用户故事开始,并针对看似有风险的事情制定探针解决方案。
然后,安排一次发布计划会议。邀请客户(最终使用产品而不是付款的人)、开发人员和管理者创建一个大家都同意的时间表。
最后,通过迭代规划会议开始迭代开发。这样就可以开始了。
但是通常情况下,项目只有在遇到麻烦后才开始寻找像XP这样的新方法。在这种情况下,启动XP的最佳方法是仔细研究当前的软件方法,找出是什么让你慢下来了,然后先用XP的方式解决此问题。
例如,如果开发进展到1/4的时候,发现需求规范变得完全无用,那么请与你的客户聚在一起,编写用户故事。
如果你处于因不断变化的需求导致需要经常重建计划的糟糕境遇,那么每隔几次迭代就尝试一次简易可行的发布计划会议。(不过,首先需要用户故事。)尝试迭代开发做刚刚好规划编程任务的模式。
如果你最大的问题是生产环境中的缺陷数量,那么尝试自动化验收测试。使用此测试套件进行回归和验收测试。
如果您最大的问题是集成错误,那么尝试自动化的单元测试。在将任何新代码发布到代码库之前,要求所有单元测试都百分百通过。
如果需要进行大面积的更改,而瓶颈是系统中的核心类的负责人是某位成员,那么就尝试代码集体共有(此前还需要单元测试。),让每个人在需要的时候对核心类进行更改。
你可以继续按照这样的方式实施,直到没有问题为止。然后尽可能添加剩余的实践方法。头几个实践落实起来可能会看起来很容易,因为你正在用一点点额外的努力来解决一个大问题。但是有些关键点在落实部分XP规则和全部XP规则之间,它需要坚持不懈才能看到效果。
当问题得到了解决,项目也重新在控制之中。此时放弃新的工作方式,回到熟悉的舒适区似乎很好,但继续实践下去最终会有回报。极限编程团队将变得比想象的更有效率,同时在某个时刻,大家会发现XP规则看起来不再是规则。
这种爬山式的方法在结对编程中尤其适用,且回报非常大。XP的项目组并不安静;似乎总有人在谈论问题和解决方案。人们四处走动,为了推动编程互相询问问题并与业务伙伴进行交易。人们自发地聚在一起解决棘手的问题,然后又散开。极限编程鼓励这种互动,提供一个会议区域,并设置工作空间,使结对的两个人可以轻松地一起工作,整个工作区域应为开放空间,以鼓励团队沟通。
极限编程的规则
计划活动
- 要写好用户故事
- 发布计划活动创建发布规划
- 高频小规模发布
- 项目被按迭代划分
- 迭代计划活动开启每个迭代
管理
- 给团队提供一个固定的开放式工作空间
- 设定可持续的步调
- 每天进行站会
- 项目速度被衡量
- 定期轮换岗位
- 当极限编程出问题时及时修复
设计
- 保持简洁
- 选择一个系统隐喻
- 在设计环节使用CRC(Class, Responsibilities, and Collaboration)卡片
- 创建探针解决方案以降低风险
- 早期不增加功能
- 随时随地可以重构
编码
- 用户保持在线
- 编码需要符合标准
- 先编写单元测试
- 所有的生产代码都是结对编写
- 一次仅仅集成一个结对小组代码
- 频繁集成
- 设立专属集成设备
- 代码集体所有
测试
- 所有的编码都需要有单元测试
- 所有代码通过单元测试方可发布
- 缺陷产生时便创建对应的测试
- 频繁运行验收测试并且公开结果
本文编者:钟润杰(Roger)
参考文献:
https://ronjeffries.com/xprog/what-is-extreme-programming/
http://www.extremeprogramming.org/
https://www.agilealliance.org/glossary/xp/
https://ootips.org/xp.html
https://xp123.com/articles/