在敏捷方法中,极限编程(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(极限编程)的简述,当然,具体的一些内容需要在实践中不断理解。