在敏捷方法中,极限编程(XP:eXtreme Programming)是其中最著名的一个,它由一系列简单却互相依赖的实践组成。。。
本篇博客,对极限编程做一个简述,以及个人的一些理解,主要从以下几点进行。。。
客户作为团队成员
良性计划
简单设计
结对编程
持续集成
TDD和UAT
重构
隐喻
一、客户作为团队成员
关键词:面对面沟通
首先明确一点,这里的客户不仅仅指为我们产品付费或使用产品的外部客户,它还包括公司内部的业务部门,有合作关系的甲方、第三方等。
XP团队中的客户是指:定义产品特性并对其进行排列优先级的人或者团体,即今天我们俗称的产品、业务分析师、项目经理等一类人。
它所追求的是“客户”和开发人员在同一个环境中工作。这里的环境由小到大可以是:同一个房间——距离在100米内——更远;距离越远,客户越难以融入到团队中来。
在XP中,面对面沟通,是最有效最简洁的交流方式!
二、良性计划
1、初始计划
关键词:确定重要的需求,快速响应,工时预估
项目开始时,开发人员和“客户”应尽量确定出真正重要的需求,而不是所有的需求。因为随着项目进展,需求也处在随时或大或小的变更中。
只需要确定真正重要的需求,保持开发方向正确即可,这样也方便对变更的快速响应和调整。
在“客户”不断编写变更需求的时候,开发人员也应该对需求进行预估。工时预估是相对的,而不是绝对的,应流出一定的缓冲时间。
如果需求太大,那么就需要对其进行拆分,直至可以相对准确的进行工时预估和详细的开发设计为止。
2、发布计划
关键词:需求可替换,随时调整
知道了开发速度后,“客户”即可知道需求的实现成本(包括人力、时间等资源)、商业价值、优先级别。
在开发过程中,可以根据具体的开发进度、实现难易程度而不断调整需求的优先级,甚至进行需求替换,即:优先级。
初始可能对优先级等情况的判断不是很准确,但随着开发进度不断精确,预估调整也可以不断精确。
3、迭代计划
关键词:每次迭代做什么?
在XP中,一般的迭代周期为1-2周,迭代周期内需求的实现顺序取决于技术决策范畴,应采用最具技术意义的顺序来实现这些需求,可以串行也可以并行开发。
确定迭代后,正在开发的需求则不应被更改,还未开发的需求可以根据具体情况进行调整。
4、任务计划
关键词:开发和“客户”达成一致约定
每次新的迭代开始时,开发人员应和“客户”共同约定任务计划。开发人员对需求进行任务拆分,“客户”对需求进行初始的优先级调整排列。
计划的方式可以采用任务列表、便笺、白板标示等方式,每完成一项,则应对其进行标注,对任务进度随时更新。
三、简单设计
关键词:关于XP的三条指导原则
1、考虑能够工作的最简单的事情
尽可能寻找能实现当前需求的最简单的设计,多考虑不同的方案,然后选择一种我们可以实际得到和最简单的解决方案。
2、你将不需要它
只有在确定真的需要引入某些基础结构(比如数据库、通信服务框架)性价比更高时,再去引入它们。
3、有且只有一次
在面向对象编程原则中,有一个叫做“共同重用原则”,即消除重复的代码。
简单来说就是将重复或相似度较高的代码变成函数,封装成一个统一的抽象集合,然后在使用时调用即可(这也将进一步减少代码间的耦合)。
四、结对编程
关键词:编码标准、共同所有权
在XP中,结对编程指的是由2个开发人员公用一台电脑,一个人进行编码,另一个进行观察并寻找代码中的错误和可以改进的地方,两个人进行频繁的角色互换。
结对关系每天至少进行一次,且团队中每个成员都应和其他成员一起工作参与。
这样做的好处是:知识在团队中的传播、不同成员参与不同的工作、可替代性较低(研究表明这样不但不会降低开发效率,切会大大减少缺陷率)。
PS:这样的开发方式现在已经很少了,但个人觉得其演变至今,更像是由开发人员独立完成单元测试代码编写和功能代码编写,这样说有点拗口,换种方式:一个人身兼开发和测试开发2个岗位职责。
编码标准:在XP中,团队开发人员都遵循着相对比较统一的编码标准(大家可以脑补一下最近阿里提出的java开发规约)。
共同所有权:在XP中,团队中每个人都拥有check out任何模块并对其进行修改的权力,每个人并不是独立的,都不会被限制在自己的专业领域。
五、持续集成
关键词:持续集成、可持续的开发速度
持续集成:开发人员每天都会进行多次的check in和check out并进行merge,使用非阻塞的源代码控制工具。
每天进行多次系统构建(关于这点,可以参考《Google软件测试之道》中第一章第四节的内容)。
可持续的开发速度:软件开发不是百米短跑,而是一场马拉松。为了完成快速开发,团队成员必须以一种有节奏的可持续的速度前进。
六、TDD和UAT
关键词:TDD(测试驱动开发)、UAT(验收测试)
首先需要明白一点:编写单元测试是一种验证行为,更是一种设计行为。它的优点是:避免了相当数量的反馈循环,尤其是功能测试时候的反馈循环(即测试-提缺陷-修复-验证)的行为。
TDD:即测试驱动开发方法。在XP中,采用这种方法,它有一下几种特点:
1、测试先行:在编写功能代码之前先设计测试方案和测试代码;需要明白的一点是:程序中的每一项功能都有测试来验证它的操作正确性。
2、心中有数:首先编写测试代码的好处是:迫使我们从不同角度考虑代码设计,而不是只关注功能实现(同时考虑接口正确性、异常、边界等情况)。
3、可测试的程序:先编写测试代码,迫使自己设计的程序是可测试、易于调用的,这样做的优点是:迫使程序和周边环境解耦。
4、无价的文档:编写的测试代码可以作为一种无价的文档,范例,帮助其他开发成员了解如何设计、使用代码。
注:这里的文档是可编译可运行的,且保持最新的版本。
总结:为了使功能代码能够通过测试,迫使开发人员去做有目的的编程;为了做到心中有数,开发人员必须使得程序模块之间进行隔离,降低耦合;
为了模块隔离,降低耦合,迫使我们以对程序最有利的方式进行解耦合,即改善了设计。
UAT:即验收测试。是用来验证系统是否满足它所声称的具有其功能的黑盒测试方法。
验收测试是关于系统特性的最终文档。单元测试作为可编译可运行的系统内部结构的文档,验收测试是有关系统特性的可编译执行的文档。
七、重构
关键词:实现功能、应对变化、易于阅读和修改
在Martin Fowler大神的名著《重构》一书中,他把重构定义为:在不改变代码外在行为的前提下对代码进行修改,以改进代码内部结构的过程。
每个软件程序都应具有三项职责:
1、可运行且能够完成所有的功能。
2、应对变化:软件是由生命周期的,在它们的生命周期中都是在不断变化的,开发者有责任保证这种变化应尽可能的简单。
3、易于阅读和修改:易于阅读和修改的软件才能更加灵活和具有适应性。
从以上三点来说,重构后的程序读起来应比之前好很多,工作的也应该更好。程序应该变得更易理解和修改,且程序结构各部分之间互相隔离。
举个例子:
重构好比用餐结束后对厨房和厨具的清理工作。第一次没有清理,用餐可能更快点,但由于没有对其进行清理,第二次做饭,你需要做的准备工作时间就更长一点,这样会促使你放弃清理工作。
如果你总是跳过清理工作,确实可以使你很快用完餐,但脏乱在一天天积累。最终你需要话费大量的时间和精力,甚至代价去做清理,以使得它们适合与烹饪。
但是,饭每天都需要吃,忽略清洁工作并不能真正加快做饭用餐的速度。
PS:从这个例子可以明白,重构是必须且经常进行的!
八、隐喻
关键词:务实主义、全局考虑
隐喻(metaphore),是XP中最难理解的一个特性,XP本质来说都是奉行务实主义。
简单来说,所谓的隐喻,即从整个系统范畴来进行全局考虑,它是系统的未来景象,它使得所有单独模块的位置和特性变得更明显、直观。
如果某个模块和整个系统对比显得格格不入,那么你就应该明白,这个模块存在问题。
隐喻也可以理解为一个总体的系统总称,其特质应该是明显的,直观的(可参考《Google软件测试之道》一书中第三章第3.2.1节的Google——ACC指导原则中的特质一词)。
以上即关于敏捷方法中的XP(极限编程)的简述,当然,具体的一些内容需要在实践中不断理解。