敏捷软件开发宣言
我们正在通过亲身实践以及帮助他们实践,揭示更好的软件开发方法。通过这项工作,我们认为:
- 个体和交互 胜过 过程和工具
- 可以工作的软件 胜过 面面俱到的文档
- 客户合作 胜过 合同谈判
- 响应变化 胜过 遵循计划
虽然右项也具有价值,但我们认为左项具有更大的价值。
敏捷宣言遵循的原则
我们遵循以下原则:
- 我们最优先要做的是通过尽早的、持续的交付价值的软件来使客户满意。
- 即使到了开发的后期,也欢迎改变需求。敏捷过程利用变化来为客户创造竞争优势。
- 经常性地交付可以工作的软件,交付的间隔可以从几个星期到几个月,交付的时间间隔越短越好。
- 在整个项目开发期间,业务人员和开发人员必须天天都在一起工作。
- 围绕被激励起来的个体来构建项目。给他们提供所需的环境和支持,并且信任他们能够完成工作。
- 在团队内部,最具有效果并且富有效率的传递信息的方法,就是面对面的交谈。
- 工作的软件是首要的进度度量标准。
- 敏捷过程提倡可持续的开发速度。责任人、开发者和用户应该能够保持一个长期的、恒定的开发速度。
- 不断地关注优秀的技能和好的设计会增强敏捷能力。
- 简单——使未完成的工作最大化的艺术——是根本的。
- 最好的架构、需求和设计出自于自组织的团队。
- 每隔一定时间,团队会和如何才能更有效地工作方面进行反省,然后相应地对自己的行为进行调整。
面向对象设计的原则
- SRP 单一职责原则
就一个类而言,应该仅有一个引起它变化的原因。 - OCP 开放-封闭原则
软件实体(类、模块、函数等)应该是可以扩展的,但是不可修改。 - LSP Liskov替换原则
子类型必须能够替换掉他们的基类型。 - DIP 依赖倒置原则
抽象不应该依赖于细节。细节应该依赖于抽象。 - ISP 接口隔离原则
不应该强迫客户依赖于它们不用的方法。接口属于客户,不属于它所在的类层次结构。 - REP 重用发布等价原则
重用的粒度就是发布的粒度。 - CCP 共同封闭原则
包中的所有类对于同一类性质的变化应该是共同封闭的。一个变化若对一个包产生影响,则将对该包中的所有类产生影响,而对于其他的包不造成任何影响。 - CRP 共同重用原则
一个包中的所有类应该是共同重用的。如果重用了包中的一个类,那么就要重用包中的所有类。 - ADP 无环依赖原则
在包的依赖关系图中不允许存在环。 - SDP 稳定依赖原则
朝着稳定的方向进行依赖。 - SAP 稳定抽象原则
包的抽象程度应该和其稳定程度一致。
极限编程实践
- 完整团队
XP项目的所有参与者(开发人员、业务分析师、测试人员等等)一起工作再一个开放的场所中,他们是同一个团队的成员,这个场所的墙壁上随意悬挂着大幅的显著的图表以及其他一些显示他们进度的东西。 - 计划游戏
计划是持续的、循序渐进的。每2周,开发人员就为下2周估算候选特性的成本,而客户则根据成本和商务价值来选择要实现的特性。 - 客户测试
作为选择每个所期望的特性的一部分,客户定义出自动验收测试来表明该特性可以工作。 - 简单设计
团队保持设计恰好和当前的系统功能相匹配,它通过了所有的测试,不包含任何重复,表达出了编写者想表达的所有东西,并且包含尽可能少的代码。 - 结对编程
所有的产品软件都是由两个程序员、并排坐在一起在同一台机器上构建的。 - 测试驱动开发
程序员以非常短的循环周期工作,他们先增加一个失败的测试,然后使之通过。 - 改进设计
随时改进糟糕的代码。保持代码尽可能的干净、具有表达力。 - 持续集成
团队总是使系统完整地被集成。 - 集体代码所有权
任何结对的程序员都可以在任何时候改进任何代码。 - 编码标准
系统中所有的代码看起来就好像是被单独一个——非常值得胜任的——人编写的。 - 隐喻
团队提出一个程序工作原理的公共景像。 - 可持续的速度
团队只有持久才有获胜的希望,他们以能够长期维持的速度努力工作。他们保存精力,他们把项目看作马拉松长跑,而不是全速短跑。
第I部分 敏捷开发
- 人与人之间的交互是复杂的,并且其效果从来都难以预期,但却是工作中最为重要的方面。《人件》,第5页。P2
- 过程和方法对于项目的结果只有次要的影响。首要的影响是人。如果想要项目取得成功,就必须构建起具有合作精神的、自组织的团队。P2
第1章 敏捷实践
- 直到迫切需要并且意义重大时,才来编制文档。P4
- 告诉开发团队想要的东西,然后期望开发团队消失一段时间后就能够交付一个满足需要的系统来,这对于公司的管理者来说是具有诱惑力的。然而,这种操作模式将导致低劣的质量和失败。P4
- 成功的项目需要有序、频繁的客户反馈。不是依赖于合同或者关于工作的陈述,而是让软件的客户和开发团队密切地在一起工作,并尽量经常地提供反馈。P4
- 较好的做计划的策略是:为下两周做详细的计划,为下三个月做粗略的计划,再以后就做极为粗糙的计划。P5
- 初期交付的系统中所包含的功能越少,最终交付的系统的质量就越高。交付得越频繁,最终产品的质量就越高P6
- 敏捷项目通过度量当前软件满足客户需求的数量来度量开发进度。它们不是根据所处的开发阶段、已经编写的文档的多少或者已经创建的基础结构代码的数量来度量开发进度的。P7
- 敏捷项目不是50米短跑;而是马拉松长跑。团队不是以全速启动并试图在项目开发期间维持那个速度;相反,他们以快速但是可持续的速度行进。P7
- 高的产品质量是获取高的开发速度的关键。保持软件尽可能的简洁、健壮是快速开发软件的途径。P7
第2章 极限编程概述
- 用户故事:了解需要只需要做到能够估算它的程度就够了。在离真正实现需求还很早时就去捕获该需求的特定细节,很可能会导致做无用功以及对需求不成熟的关注。P10
- 迭代计划:开发人员通过度量在以前的迭代中所完成的工作量来为本次迭代设定预算。只要估算成本的总量不超过预算,客户就可以为本次迭代选择任意数量的用户故事。P10
- 发布计划:XP团队通常会创建一个计划来规划随后大约6次迭代的内容,这就是所谓的发布计划。P10
- 验收测试:通过自动化的验收测试来验收功能能。P11
- 结对编程:结对编程极大地促进知识再团队中的传播,在紧要关头,其他团队成员就能够代替所需要的专家。P11
- 测试驱动的开发方法:编写所有产品代码的目的都是为了使失败的单元测试能够通过。P12
- 集体所有权:没有程序员对任何一个特定模块或技术单独负责。P12
- 持续集成:XP团队使用非阻塞的源代码控制工作。P12
- 可持续的开发速度:XP的规则是不允许团队加班工作。P13
- 开放的工作空间:团队再一个开放的房间中一起工作,房间中有一些桌子,每张桌子上摆放了两到三台工作站,每台工作站前有给结对编程的人员预备的两把椅子,墙壁上挂满了状态图表、任务明细表、UML图等等。P13
- 在充满积极讨论的屋子里工作,生产率非但不会降低,反而会成倍地提高。P13
- 计划游戏:计划游戏的本质是划分业务人员和开发人员之间的职责。业务人员(客户)决定特性的重要性,开发人员决定实现一个特性所花费的代价。P13
- 简单设计:考虑能够工作的最简单的事情;你将不需要它;一次,并且只有一次。P14
- 重构:代码往往会腐化。随着我们添加一个又一个的特性,处理一个又一个的错误,代码的结构会逐渐退化。如果对此置之不理的话,这种退化最终会导致纠结不清,难以维护的混乱代码。P15
- 隐喻:隐喻通常可以归结为一个名字系统。这些名字提供了一个系统组成元素的词汇表,并且有助于定义它们之间关系。P15
第3章 计划
- 当你能够度量你所说的,并且能够用数字去表达它时,就表示你了解它;若你不能度量它,不能用数字去表达它,那么说明你的知识就是匮乏的、不能令人满意的。P17
- 通过一个称为速度(velocity)的因子,就可以将用户故事的估算点数乘以速度得到实现该用户故事的实际时间。P18
- 初始探究、分解和速度:花费几天时间去原型化一到两个用户股市来了解团队的速度就足够了,这样的一个原型化过程称为探究(spike)。P18
- 发布计划:选择那些最先完成的故事,客户不能选择与当前开发速度不符的更多的故事。此类选择属于商务决策范畴,让业务人员来选定那些会给他们带来最大利益的故事。开发人员和客户对项目的首次发布时间达成一致,通常也就是2~4个月后的事情。P18
- 迭代计划:合计所有已经完成的故事的估算值,然后计算出本次迭代的开发速度,这个速度会被用于计算下一次的迭代。P19
- 任务计划:开发可以签订任何类型的任务,这样做的好处是开发人员对整项目了解得越多,那么团队就会越健康、越有知识。P19
- 迭代中点:如果迭代中安排的半数故事未完成,那么团队会设法重新分配没有完成的任务和职责,以保证再迭代结束时能够完成所有的故事。P19
- 客户演示:在每次迭代结束时,会给客户演示当前可运行的程序,要求客户对项目程序的外观、感觉和性能进行评价。P20
- 通过一次次的迭代和发布,项目进入了一种可以预测的、舒适的开发节奏。每个人都知道将要做什么,以及何时去做。P20
第4章 测试
- 编写单元测试是一种验证行为,更是一种设计行为。同样,它更是一种编写文档的行为。编写单元测试避免了相当数量的反馈循环,尤其是功能验证方面的反馈循环。P21
- 通过程序调用者的有利视角去观察我们将要编写的程序;此外,通过首先编写测试,我们就迫使自己把程序设计为可测试的。把程序设计为易于调用和可测试的,是非常重要的。为了成为易于调用和可测试的,程序必须和它的周边环境解耦,这样,首先编写测试迫使我们解除软件中的耦合;另一个重要效果,测试可以作为一种无价的文档形式。测试就像一套范例,它帮助其他程序员了解如何使用代码。这份文档是可编译、可运行的。它保持最新,它不会撒谎。P21
- 单元测试是必须的,但是不够充分。单元测试是用来验证系统中个别机制的白盒测试。验收测试是用来验证系统满足客户需求的黑盒测试。是关于一项特性(feature)的最终文档。P25
第5章 重构
- 每一个软件模块都具有三项职责。第一个职责是它运行起来所完成的功能,这也是该模块得以存在的原因。第二个职责是它要应对变化。几乎所有的模块在它们的生命周期中都要变化,开发者有责任保证这种改变应该尽可能地简单。一个难以改变的模块是拙劣的,即使能够工作,也需要对它进行修正。第三个职责是要和阅读它的人进行沟通。对该模块不熟悉的开发人员应该能够比较容易地阅读并理解它。一个无法进行沟通的模块也是拙劣的,同样需要对它进行修正。P28
第6章 一次编程实践
- 易于理解所以才易于维护。P75
第II部分 敏捷设计
第7章 什么是敏捷设计
- 设计的臭味——腐化软件的气味。P80
- 僵化性(Rigidity):很难对系统进行改动,因为每个改动都会迫使许多对系统其他部分的其他改动。
- 脆弱性(Fragility):对系统的改动会导致系统中和改动的地方再概念上无关的许多地方出现问题。
- 牢固性(Immobility):很难解开系统的纠结,使之成为一些可在其他系统中重用的组件。
- 粘滞性(Viscosity):做正确的事情比做错误的事情要困难。
- 不必要的复杂性(Needless Complexity):设计中包含有不具任何直接好处的基础结构。
- 不必要的重复(Needless Repetition):设计中包含有重复的结构,而该重复的结构本可以使用单一的抽象进行统一。
- 晦涩性(Opacity):很难阅读、理解。没有很好地表现出意图。
- 敏捷设计是一个过程,不是一个事件。它是一个持续的应用原则、模式以及实践来改进软件的结构和可读性的过程。它致力于保持系统设计在任何时间都尽可能很简单、干净以及富有表现力。P86
第8章 单一职责原则(SRP)
- 就一个类而言,应该仅有一个引起它变化的原因。P88
- 职责:在SRP中,我们把职责定义为“变化的原因”。P89
- 软件设计真正要做的许多内容,就是发现职责并把那些职责相互分离。P91
第9章 开发—封闭原则(OCP)
- 开放—封闭原则(OCP):软件实体(类、模块、函数等等)应该是可以扩展的,但是不可修改的。P92
第10章 Liskov替换原则(LSP)
- Liskov替换原则(LSP):子类型(subtype)必须能够替换掉它们的基类型(base type)。
第11章 依赖倒置原则(DIP)
- 依赖倒置原则(DIP):高层模块不应该依赖于低层模块,二者都应该依赖于抽象;抽象不应该依赖于细节,细节应该依赖于抽象。P116
第12章 接口隔离原则(ISP)
- 接口隔离原则(ISP):不应该强迫客户依赖于它们不用的方法。P125