书名及作者声明:《超越传统的软件开发-极限编程的幻想与真实》 雷剑文 陈振冲 李明树 编著
这篇笔记写于两年前,当时是为了完成老师的作业去读的这本书,现在再看看还是会有另外一种收获。
这本书是在我读完软件工艺之后紧接着读的,软件工艺给我打开了一扇窗,或者说带我走出了井底,让我看到了更广阔的世界,极限编程则是我探索这个陌生世界的的一个对象。新鲜的东西总是令人好奇,但又总是让人摸不着头脑,因为它在不断颠覆你的传统思想。举一个最简单了例子,但就是这个简单的例子让我的大脑当机了好一会,我们大家都非常熟悉的软件开发过程:设计-编码-测试,极限编程里完全颠覆了这一过程:测试-编码-设计。第一眼看上去是那么的不和谐,没有一点逻辑可言,但就是这么不合逻辑的过程它却领导了一种全新的软件开发过程,当你深入了解它之后你就会觉的“哦!软件就应该这样开发”。下面就我从这本书当中学到的东西做一下总结。
软件与模型
软件开发模型在早期用到最多的是瀑布模型,这是很经典的开发模型,但现在很多书都拿其当做反面教材,瀑布模型有很多缺点被批的体无完肤。极限编程作为一种新的开发模式被炒得很热,他有很多优优点是瀑布模型所不具备的,在理论上极限编程完全打败了瀑布模型。回到现实再来看一下,我们发现仍有许多人使用瀑布模型,原因很有趣,人们往往情愿选择“可接受的失败”也不愿尝试“冒险的成功”。还有一种模型叫做能力成熟度模型(Carnegie Maturity Model,CMM),它是由卡内基·梅隆大学软件工程学院提出的对软件过程的管理、改进预评估的模型。CMM模型主要分为5个等级,分别为初始级、可重复级、定义级、管理级和优化级,每一等级内又有许多指标,这些指标也叫做关键过程域(Key Process Area,KPA)。这一模型划分的等级是对软件开发团队的配置要求,只有当团队达到了次一级的要求才能升级到更高一级,每高一级都体现了团队开发能力的提高。
这里再看一下几个有趣的概念:一、足够好的软件,这个概念在软件工艺当中也被提到了,这里有一次的看到了,我就写一下我对足够好软件的理解。我认为足够好的软件就是客户对你的软件满意,举个例子,一个文字处理软件,具有丰富的功能,当用户使用时出现了一些错误,但是不会对用户的数据造成破坏,这样用户还是对你的软件满意,因为他需要的功能你都有,即使有时出现错误,但还是能够接受,所以对开发者来说就不用花费太多的功夫在修复这些漏洞上,这就是一个足够好的软件。二、雾件,一种已经被大肆宣传但还没有生产出来的新软件,不管报纸、杂志上的评论是如何的热闹和激烈,这个产品却不会在未来的六个月内发布。
概述极限编程
极限编程是一个高度迭代的过程,有较多的反馈对环境和需求变化做出调整,同时极限编程强调一小版本形式来开发系统,由此使用户可以很快的使用户使用一个较小的系统,然后不断增加此系统的功能。极限编程的团队一般比较小(8-10人)。极限编程拥有4个价值,5个原则,4个活动和12个实践。
极限编程为何优于传统开发模式
我们都知道传统的软件开发对于需求的变化是最头痛的,因为它总是牵一发而动全身,极限编程拥抱变化,它很好的解决了这一点。我们来看一下它是如何做到的,首先极限编程是一个高度迭代的过程,通过一次或几次的迭代就可以发布软件的一个新版本,用户从软件的第一个版本就开始体验了,程序员与体验过的用户交流就可也很明确的知道用户的想法,这样不断通过发布新版本来完善软件就能很好的减小需求变更所带来的麻烦。其次,我们再看一下传统的开发模式客户与程序员的沟通都是通过系统分析师提供的大量文档来实现的。这样的过程非常低效,采用极限编程模式的程序员与客户的沟通是直接的。这样做的好处是简化了沟通程序,减少了因中间媒介所造成的信息失真。客户和程序员是极限编程的主要角色,也代表了极限编程的核心精神,即人重于过程。
极限编程的价值
沟通、简单、反馈和勇气是极限编程的4个价值,一个高迭代的过程必须要体现这四个价值,实际上极限编程也是由这4个价值所驱动的。
● 沟通,不仅仅子程序员和客户的直接交谈,更主要的是要求程序员要通过直接交谈而了解客户真正想要什么。
● 简单,程序员只需要以尽量简单的措施完成一直的工作即可,不需要考虑以后是否要对系统扩展,因为高度迭代的过程常常有反馈。
● 反馈,和沟通是相互联系的,反馈越充分,沟通也就越容易。
● 勇气,程序员要有勇气丢掉以前的工作而重新来。
极限编程的原则
五个基本原则为:快速反馈、假定简单、递增改变、拥抱变化、质量产品。这些原则对软件开发有指导作用。
● 快速反馈,开发人员通过短的迭代周期,得到反馈信息,并迅速检查他们前面的工作是否满足客户的需求。
● 假定简单,将系统开发中的每个问题以尽量简单的方法来解决。
● 递增改变,用一系列的小改变开解决一个大问题。
● 拥抱变化,解决紧迫问题的一种包容策略。
● 质量产品,产品质量必须得到保证,不能因为其他的原因而放弃产品的质量。
极限编程的活动
极限编程的活动是最让人不可思议的地方,由于我们学过传统的软件开发过程,可能是先入为主的观念使得我们在理解极限编程活动方面有点困难,但是在这里我们要打破常规思维,只有这样才能真正掌握极限编程的精髓。下面看一下极限编程的活动。
● 聆听,极限编程不是靠文档驱动的,所以沟通对于极限编程小组的成员特别重要。
● 测试,极限编程的开发者在编写代码前,需要先编写测试用例,这要求开发者在思维方式上有所改变。
● 编码,极限编程的重点始终是编码,许多实践都是为了提高代码的质量。
● 设计,这一点是极限编程里最有创意的了,编码结束后才进行设计。
极限编程的实践
极限编程的12个实践是最重要的环节
● 小版本,极限编程在一个或几个迭代周期结束后就向客户提供一个版本,通过频繁的发布小版本,编程人员可以从客户处获得更多的反馈信息。
● 规划游戏,极限编程不像传统的开发模式那样需要详细的需求,他的需求仅是从客户那里得来的一个小任务,我们称之为用户故事。用户首先编写故事,然后由程序员来估计每个故事的开发时间,用户得到程序员反馈的开发时间后来确定每个故事开发的优先级,最后由程序员合理分配故事的开发工作。
● 现场客户,由于极限编程是一个高速迭代的的开发过程,程序员需要实时的与客户进行交流,所以必须要有现场客户,现场客户除了负责参与规划游戏,还要负责编写验收测试。
● 隐喻,用共同的词汇来说明系统是如何运行的,方便开发人员的沟通。
● 简单设计,第三次出现,原理在前面已经解释过了。
● 重构,在不改变程序行为的前提下队员代码进行改进和简化。
● 测试驱动开发,要求程序员对完成的每一段代码都要编写相应的自动化测试用例。
● 结对编程,指两个程序员坐在同一台电脑前,合作完成同一个编程工作,包括:设计、算法、编码和测试。两个人中一个为审视者,一个为执行者,这两个角色按一定的时间不断交替。
● 代码共有,指代码在任何时候都不是有某个人独自占有和维护,任何时候任何人都有权修改代码。这样可以保证项目的稳定性,不会因为一个程序员的离开而扰乱进度。
● 编码标准,这应该是任何开发团队都要要求的。
● 每周40小时工作制,极限编程不赞成长时间工作。
敏捷软件开发
敏捷软件方法寻求迅速建立软件途径并适应不断变化的用户需求。下面看一下敏捷软件开发宣言:
● 个体和交互胜过过程和工具
● 可以工作的软件胜过面面俱到的文档
● 客户合作胜过合同谈判
● 响应变化胜过遵循计划
极限编程和Scrum属于敏捷软件开发的代表。Scrum实践不像其他的软件模型一样,并没有设计、编码、软件质量等。Scrum强调程序员的自我组织,Scrum团队有30天的Sprint时间,这30天时间Scrum团队有完全的支配权力,他们可也选择开发模式,例如可以以极限编程的方式组织开发,但到30天结束的时候必须完成预期的任务。从上面我们可以看出Scrum就像一张包装纸一样,它可以封装其他开发模式的实践,所以说Scrum与许多开发模式相互兼容。
分析结对编程
结对编程在极限编程里面是最受争议的,反对者并不比支持者少。从书中了解到曾经有三人分别做过结对编程和单人编程生产力的比较,其中有两人的实验表明结对编程生产力高于单人编程,另外那组实验刚好得出了相反的结果,从实验中我们不能得出什么有力的证据表明那种方式生产力更高,所以不能通过实验的方式来证明。到现在为止没有没有一个定论到底结对好还是不结对好。所以在这一点上是仁者见仁,智者见智。我个人保持中立,我认为在一个团队当中如果大家都支持结对编程,结对之后可以相互取长补短,这种情况下还是结对编程比较好,如果团队当中都是一些独立特性的人,不习惯两人共享一台计算机,合作之后有矛盾,不能产生默契的话还是不要强行组织结对编程。
分析重构
在极限编程中,重构的目的是使程序的内部结构更加明确、合理、简单、高重用性。简而言之,就是增加代码的可读性和可维护性。重构不等于优化,这里稍微区别一下,优化的目的是要提高代码的执行效率,要提高程序的性能,但优化之后的代码可读性和可维护性不一定提高,反而还有可能降低。在极限编程中,重构和测试驱动开发是一起工作的,在测试之前要有许多自动化的单元测试用例,能随时执行来检查重构后程序行为不变性。另外,重构要依赖于自动化工具(例如,测试驱动开发的工具,或重构浏览器)。
分析测试驱动开发
研究报告显示,软件测试的花费占用软件开发成本的50%,这样的比例在重要用途的软件里会更高一些(例如,航天系统),由此可见软件测试在整个软件开发中占有多么重要的地位。我们看一下减少软件测试会给我们带来什么,首先是软件质量的下降;其次可以缩短软件开发时间,这对于时间要求比较近的项目是件好事;最后,还可以显著的减少软件开发成本。从上面三条可以看出第一条是用户所不希望看到的,最后两条是开发者的追求,在这个客户至上的时代,我们不能做或者要尽量少做让用户不满意的事。
测试驱动开发是指在编写执行代码之前,我们先编写自动单元测试用例,这些单元测试用例作为程序的一部分。测试驱动开发有5个相互作用的迭代步骤:
1) 快速加入一条单元测试用例来指定一条将要编写的功能。
2) 运行所有测试用例包括步骤1)中新增的测试用例,并目睹用例的失败结果,因为其对应的代码还没有编写。
3) 编写代码或者修改代码使其可以通过新的测试。
4) 运行所有的代码并确认他们完全通过。
5) 重构或者删除重复代码。
从上面的5个步骤来看,整个测试驱动开发里有两个规定。第一,在还没有一个失败的自动测试用例前,不要编写任何代码。第二,一直保持所有测试用例的通过率是100%。
测试用例开发的相关工具包括:用来自动化单元测试的Xunit系列,模拟真正的对象行为的模仿对象(Mock Object),可以追踪已测试代码的Jprobe,能够查找还没有给测试用例覆盖其编码的Jester,还有协助重构的RefactorIT,Transmongrify及Xrefactory等。
总结
极限编程发展了这么多年,到现在已经相当成熟了。但这种超越传统的软件开发过程到现在还是受到很大的争议,反对它的人并不比支持的人少,从他们反对和支持的理由来看都有一定的道理。我们要如何判断一个事物的好坏这完全取决于我们的心理因素,心理因素的差异会使我们使用同一种方法却得到完全不同的结果。所以对于极限编程的许多争议在于此-人们认识事物的偏见。总之,极限编程作为一种独特的软件开发过程他有许多优点值得我们去尝试,但要灵活。
别人都采用相同的方法解决问题,若自己运用别的方法,一旦失败,便会受到严厉的批评,反过来,如果大家都采用相同的方法,即使失败也是可以接受的。