极限编程(XP) 基础

在软件项目中,过程与技术对项目结果只有次要影响,首要影响是人。如果想要项目取得成功,我们就必须组建起具有合作精神的自组织的团队,而极限编程便是众多实现这个目标的可行方法之一,极限编程方法论可以说是敏捷联盟中最鲜艳的一面旗帜,也是被研究、尝试、应用、赞扬、批判最多的一种方法论,也是相对来说最成熟的一种。

与很多敏捷实践一样,极限编程方法也是由一组价值观原则和实践构成的方法论体系,极限编程提倡沟通、反馈、简单、勇气、尊重的价值观,他提倡可持续的开发速度、自动化测试、有效沟通、共享工作空间、现场客户代表等实践方法。大家常见的主要有十三种主要的实践方法,一般会以下面这种图形方式来展现。


image

完整团队/客户现场参与

XP项目的所有参与者(开发人员、客户、测试人员等)一起工作在一个开放的场所中,他们是同一个团队的成员。这个场所的墙壁上随意悬挂着大幅的、显著的图表以及其他一些显示他们进度的东西,以便彼此可以方便的知晓对方所面临的问题,并能共同去解决。

为了保证开发出来的结果与客户的预期一致,XP 认为最好的方法就是将客户请到开发现场,在XP项目中,应该时刻保证客户负责业务决策,开发团队负责技术决策。因此,在项目中有客户在现场参与用户故事编写及过程讨论,并做出相应的业务决策,对于 XP 项目而言有着十分重要的意义。千万不要认为客户在现场会带来更多需求变更而拒绝让客户充分参与,作为一名有经验的开发人员,绝对不会对现场客户的价值产生任何怀疑,如果实在不具备客户现场参与项目的条件也需要开发团队应该和客户能够随时沟通,可以是面谈,可以是在线聊天,可以是电话,当然面谈是必不可少的。其中的关键是当开发人员需要客户做出业务决策是,需要进一步了解业务细节时能够随时找到相应的客户。

计划游戏

计划游戏的主要思想就是先快速地制定一份概要的计划,然后随着项目细节的不断清晰,再逐步完善这份计划。计划游戏产生的结果是一套用户故事及后续的一两次迭代的概要计划。

“客户负责业务决策,开发团队负责技术决策”是计划游戏获得成功的前提条件。也就是说,系统的范围、下一次迭代的发布时间、用户故事的优先级应该由客户决定;而每个用户故事所需的开发时间、不同技术的成本、如何组建团队、每个用户故事的风险,以及具体的开发顺序应该由开发团队决定。

计划游戏的一般过程是:首先客户和开发人员坐在同一间屋子里,每个人都准备一支笔、一些用于记录用户故事的纸片,最好再准备一个白板,就可以开始了:

1. 客户编写故事

由客户谈论系统应该完成什么功能,然后用通俗的自然语言,使用自己的语汇,将其写在卡片上,这也就是用户故事,初次实践一般可以采用三段式方式编写,详细可以参考《用户故事与敏捷方法》。

2. 开发人员进行估算

首先客户按优先级将用户故事排序,比如可以按照必须要有、希望有、如果有更好三类,然后开发人员对每个用户故事进行估算(可以采用计划扑克等方式),先从高优先级开始估算。如果在估算的时候,感到有一些故事太大,不容易进行估算,无法在一个迭代内完成,那么就应该对其进行分解,拆成多个小故事。

3. 确定迭代的周期

接下来就是确定本次迭代的时间周期,这可以根据实际的情况进行确定,一般推荐迭代周期是 1~4 周。确定了迭代周期之后结合参与的开发人数,算出可以完成的工作量总数。然后根据估算的结果,与客户协商,根据优先级挑出足够本迭代完成的用户故事,形成迭代计划。

小规模频繁发布

XP 方法论秉承的是“持续集成,小步快走”的哲学,也就是说每一次发布的版本应该尽可能的小,而且需要确保每个版本有足够的商业价值,值得发布。由于小型发布可以使得集成更频繁,客户获得的中间结果也越频繁,反馈也就越频繁,客户就能够实时地了解项目的进展情况,从而提出更多的意见,以便在下一次迭代中计划进去。以实现更高的客户满意度。

标准代码/编码规范

编码标准是一个“雅俗共享”的最佳实践,不管是代表重型方法论的 RUP,PSP,还是代表敏捷方法论的 XP,都认为开发团队应该拥有一个统一的编码标准。XP 方法论认为拥有编码标准可以避免团队在一些与开发进度无关的细节问题上发生争论,而且会给重构、结对编程带来很大麻烦。试想如果有人将你上次写的代码的变量命名法做了修改,下次你需要再改这部分代码时,会是一种什么感觉呢?

不过,XP 方法论的编码标准的目的不是创建一个事无巨细的规则表,而是只要能够提供一个确保代码清晰,便于交流的指导方针。

如果你的团队已经拥有编码标准,就可以直接使用它,并在过程中进行完善。如果还没有,那么大家可以先进行编码,然后在过程中逐步总结出编码规则,边做边形成。当然除了这种文字规范以外,还可以采用一些如自动格式化代码工具之类的方法进行代码规范。事实上,你只需要很好地贯彻执行其他的实践并且进行沟通,编码标准会很容易地浮现出来。

共同拥有代码

由于 XP 方法论鼓励团队进行结对编程,而且认为结对编程的组合应该动态地搭配,根据任务的不同、专业技能的不同进行最优组合。由于每个人都肯定会遇到不同的代码,所以代码的所有制就不再适合于私有,因为那样会给修改工作带来巨大的不便。

也就是说,团队中的每个成员都拥有对代码进行改进的权利,每个人都拥有全部代码,也都需要对全部代码负责。同时,XP 强调代码是谁破坏的,就应该由谁来修复。

由于在 XP 过程中,有一些与之匹配的最佳实践,因此你并无须担心采用集体代码所有制会让你的代码变得越来越乱:

  1. 由于在 XP 项目中,集成工作是一件经常性得工作,因此当有人修改代码而带来了集成的问题,会在很快的时间内被发现。
  2. 由于每一个类都会有一个测试代码,因此不论谁修改了代码,都需要运行这个测试代码,这样偶然性的破坏发生的概率将很小。
  3. 由于每一个代码的修改就是通过了结对的两个程序员共同思考,因此通常做出的修改都是对系统有益的。
  4. 由于大家都坚持了相同的编码标准,因此代码的可读性、可修改性都会比较好,而且还能够避免由于命名法、缩进等小问题引发经常性得代码修改。

集成代码所有制是 XP 与其他敏捷方法的一个较大不同,也是从另一个侧面体现了 XP 中蕴含的很深厚的编码情节。

持续集成

在前面谈到小型发布、重构、结对编程、集体代码所有制等最佳实践的时候,我们多次看到“持续集成”的字眼,可以说持续集成是对这些最佳实践的基本支撑条件。

可能大家会对持续集成与小型发布代表的意思混淆不清,其实小型发布是指在开发周期经常发布中间版本,而持续集成的含义则是要求 XP 团队每天尽可能多次地做代码集成,每次都在确保系统运行的单元测试通过之后进行。

这样,就可以及早地暴露、消除由于重构、集体代码所有制所引入的错误,从而减少解决问题的痛苦。要在开发过程中做到持续集成并不容易,首先需要养成这个习惯。而且集成工作往往是十分枯燥、烦琐的,因此适当地引入每日集成工具是十分必要的。XP 建议大家首先使用配置管理服务器将代码管理起来,然后使用Jenkins等工具搭建持续集成环境。

隐喻

相对而言,隐喻这一个最佳实践是极限编程实践中最模糊的一个,也比较令人费解。总结而言,隐喻主要还是一种沟通技巧,用于提高沟通效率和沟通效果,常常用于四个方面。

  1. 寻求共识:也就是鼓励开发人员在寻求问题共识时,可以借用一些沟通双方都比较熟悉的事物来做类比,从而帮助大家更好地理解解决方案的关键结构,也就是更好地理解系统是什么、能做什么。
  2. 发明共享词汇:通过隐喻,有助于提出一个用来表示对象、对象间的关系通用名称。例如,策略模式(用来表示可以实现多种不同策略的设计模式)、工厂模式(用来表示可以按需“生产”出所需类得设计模式)等。
  3. 创新的武器:有的时候,可以借助其他东西来找到解决问题的新途径。例如:“我们可以将工作流看做一个生产线”。
  4. 描述体系结构:体系结构是比较抽象的,引入隐喻能够大大减轻理解的复杂度。例如管道体系结构就是指两个构件之间通过一条传递消息的“管道”进行通信。

当然,如果能够找到合适的隐喻是十分快乐的,但并不是每种情况都可以找到恰当的隐喻,你也没有必要强求

保持流动性/稳定可持续的速度

这是最让开发人员开心的、管理者反对的一个最佳实践了,在996已成为好多公司常态的国内环境下尤其如此,加班、再加班早已成为开发人员的家常便饭,也是管理者最常使用的一种策略,而 XP 方法论认为,加班最终会扼杀团队的积极性,最终导致项目失败,这也充分体现了 XP 方法关注人的因素比关注过程的因素更多一些。

Kent Beck 认为开发人员即使能够工作更长的时间,他们也不该这样做,因为这样做会使他们更容易厌倦编程工作,从而产生一些影响他们效能的其他问题。因此,每周工作 40 小时是一种顺势行为,是一种规律。其实对于开发人员和管理者来说,违反这种规律是不值得的。

团队只有持久才有获胜的希望。他们以能够长期维持的速度努力工作,他们保存精力,他们把项目看作是马拉松长跑,而不是全速短跑。

重构

重构时一种对代码进行改进而不影响功能实现的技术,XP 需要开发人员在闻到代码的坏味道时,有重构代码的勇气。重构的目的是降低变化引发的风险,使得代码优化更加容易。通常重构发生在两种情况之下。

实现某个特性之前:尝试改变现有的代码结构,以使得实现新的特性更加容易。
实现某个特性之后:检查刚刚写完的代码后,认真检查一下,看是否能够进行简化。

在《重构》一书中,作者 Martin Fowler 提示我们:在考虑重构时,应该要养成编写并经常运行测试代码的习惯;要先编写代码,再进行重构;把每一次增加功能都当做一次重构的好时机;将每一个纠正错误当做一次重构的重要时机。同时,该书中也列出大量需要重构的情况和重构方法。

简单设计

强调简单设计的价值观,引出了简单性假设原则,落到实处就是“简单设计”实践。这个实践看上去似乎很容易理解,但却又经常被误解,许多批评者就指责 XP 忽略设计是不正确的。其实,XP 的简单设计实践并不是要忽略设计,而且认为设计不应该在编码之前一次性完成,因为那样只能建立在“情况不会发生变化”或者“我们可以预见所有的变化”之类的谎言的基础上的。

Kent Beck 概念中简单设计是这样的:

  1. 能够通过所有的测试程序。
  2. 没有包括任何重复的代码。
  3. 清楚地表现了程序员赋予的所有意图。
  4. 包括尽可能少的类和方法
  5. 他认为要想保持设计简单的系统,需要具备简单思考的能力,拥有理解代码和修改的勇气,以及为了消除代码的“坏味道”而定期重构的习惯。

那么如何开始进行简单的设计呢?XP 实践者们也总结也一些具体的、可操作的思考方法。

  1. 首先写测试代码:具体将在后面详细描述。
  2. 保持每个类只负责一件事:SRP(单一职责原则)是面向对象设计的基础原则之一。
  3. 使用 Demeter(迪米特)法则:迪米特法则,也称为 LoD 法则、最少知识原则。也就是指一个对象应当对其他对象尽可能少地了解。用隐喻的方法来解释的话就是“只与你直接的朋友通信”、“不要和陌生人说话”。

结对编程

这个是国内公司最难接受的一个实践方法,至少目前我还没见过几个会大规模应用的公司。国外公司这方面的尝试相对会多一些,长期以来的研究结果表明:结对编程的效率确实比单独编程更高。往往一开始会牺牲一些速度,但慢慢的,开发速度会逐渐加快,究其原因,主要是结对编程大打降低了沟通的成本,提供了工作的质量。

测试驱动开发

当我第一次看到“测试先行”这个概念的时候,我也不太理解,也不知道如何下手,后来参加培训时候老师举了个例子,工匠砌墙时候:先拉上一根水平线,砌每一块砖时,都与这跟水平线进行比较,使得每一块砖都保持水平。

而在软件开发过程中,我们不仅我们没有采用工匠一的工作方法,甚至有的时候程序员会以“开发工作太紧张”为理由,而忽略测试工作。但这样却导致了一个恶性循环,越是没有空编写测试程序,代码的效率与质量越差,花在找 Bug、解决 Bug 的时间也越来越多,实际产能大打降低。由于产能降低了,因此时间更紧张,压力更大。你想想,为什么不拉上一根水平线呢?难道,我们不能够将后面浪费的时间花在单元测试上,使得我们的程序一开始就更健壮,更加易于修改吗?不过,编写测试程序当然要比拉一条水平线难道多,所以我们需要引入“自动化测试工具”,免费的 xUnit 测试框架就是你最佳的选择。

  1. 当所有的测试都通过的时候,你再也不会担心所写的代码今后会“暗箭伤人”,那种感觉是相当棒的。
  2. 当你的客户看到所有的测试都通过的时候,会对程序充满前所未有的信心。
  3. 当你需要进行重构时,测试代码会给你带来更大的勇气,因为你要测试是否重构成功只需要一个按钮。

测试先行是 XP 方法论中一个十分重要的最佳实践,并且其中所蕴含的知识与方法也十分丰富。

极限编程早在20多年前就已经由Kent Beck在国外开始推广,经过了广泛的实际项目的验证,建议每个开发人员应该去尝试学习和了解这个已经有二十年历史的专门给程序员准备的方法学,学会之后再决定是否适用于你的工作场景。

你可能感兴趣的:(极限编程(XP) 基础)