[书摘]《敏捷软件开发: 原则、模式与实践》第一部分:敏捷开发
面向对象设计的原则
- 单一职责
- 开放-封闭
- Liskov替换原则
- 依赖倒置原则
- 接口隔离原则
- 重用发布等价原则
- 共同封闭原则
- 共同重用原则
- 无环依赖原则
- 稳定以来原则
- 稳定抽象原则
人的重要性
-
交付产品的关键因素是人,而不是过程。(敏捷 Agile)
-
人与人之间的交互式复杂的,并且其效果从来都是难以预期,但却是工作中最为重要的方面。
------ Tom DeMacro 和 Timothy Lister《人件》 -
有凝聚力的团队将具有最强大的软件开发力量。
敏捷软件开发宣言
我们一直在实践中探寻更好的软件开发方法,身体力行的同时也帮助他人。由此我们建立了如下价值观:
个体和互动 高于 流程和工具
工作的软件 高于 详尽的文档
客户合作 高于 合同谈判
响应变化 高于 遵循计划
也就是说,尽管右项有其价值,我们更重视左项的价值。
-
个体和互动 高于 流程和工具
- 合作、沟通以及交互能力要比单纯的编程能力更重要。
- 适合的工具也很重要:编译器、IDE、源码控制系统(git?)
- 首先致力于构建团队,然后再让团队基于需要来配置环境。
-
工作的软件 高于 详尽的文档
- 文档应当是短小并且主题突出的。应该仅论述系统的高层结构和概括的设计原理。
- 给新成员知识传递最好的文档是代码和团队。
-
客户合作 高于 合同谈判
- 成功的项目需要有序、频繁的客户反馈
- 让软件的客户和开发团队密切地一起工作,并经常地提供反馈。
-
响应变化 高于 遵循计划
- 确保计划是灵活的并且易于适应商务和技术方面的变化。
- 较好的计划策略:
- 为下两周做详细的计划
- 为下三个月做粗略的计划
- 再以后就做极为粗糙的计划
敏捷宣言12条原则
敏捷实践12 条原则,它们是敏捷实践区别于重型过程的特征所在。
- 我们最优先要做的是通过尽早的、持续的交付有价值的软件来使客户满意。
- 即使到了开发的后期,也欢迎改变需求。敏捷过程利用变化来为客户创造竞争优势。
- 经常性地交付可以工作的软件,交付的间隔可以从几个星期到几个月,交付的时间间隔越短越好。
- 在整个项目开发期间,商务人员和开发人员必须天天都工作在一起。
- 围绕被激励起来的个体来构建项目。给他们提供所需的环境和支持,并且信任他们能够完成工作。
- 在团队内部,最具有效果并且富有效率的传递信息的方法,就是面对面的交谈。
- 工作的软件是首要的进度度量标准。
- 敏捷过程提倡可持续的开发速度。责任人、开发者和用户应该能够保持一个长期的、恒定的开发速度。
- 不断地关注优秀的技能和好的设计会增强敏捷能力。
- 简单——使未完成的工作最大化的艺术——是根本的。
- 最好的构架、需求和设计出自于自组织的团队。
- 每隔一定时间,团队会在如何才能更有效地工作方面进行反省,然后相应地对自己的行为进行调整。
极限编程实践
极限编程(eXtreme Programming,简称XP)是敏捷方法中最著名的一个。它由一系列简单却互相以来的实践组成。这些实践结合在一起形成了一个胜于部分结合的整体。
-
客户作为团队成员。
-
用户素材
- 它是一个计划工具,客户可以使用它并根据它的优先级和估算代价来安排实现该需求的实践。
-
短交付周期
-
验收测试
- 可以以客户指定的验收测的形式来捕获有关用户素材的细节。
-
结队编程
- 所有产品代码都是由结队的程序员使用同一台电脑共同完成的。
-
测试驱动的开发方法
- 编写所有产品代码的目的都是为了使失败的单元测试能够通过。面向对象设计的原则在进行这种解除耦合方面具有巨大的帮助作用。
-
集体所有权
- 没有程序员对任何一个特定的模块或技术单独负责,每个人都参与各个方面的工作。
-
持续集成
- XP团队每天会进行多次系统构建,他们会重新创建整个系统。
-
可持续的开发速度
- XP团队必须要以一种可持续的速度前进,必须要有意识地保持稳定、适中的速度。
- XP的规则是不允许团队加班工作。在版本发布前的一个星期是该规则的惟一例外。
-
开放的工作空间
- 在充满积极讨论的屋里工作,生产率非但不会降低,反而会成倍地提高。
-
计划游戏
- 计划游戏的本质是划分业务人员和开发人员之间的职责。业务人员(客户)决定特性的重要性,开发人员决定实现一个特性所花费的代价。
-
简单的设计
-
重构
- 重构就是在不改变代码行为的前提下,对其进行一系列小的改造,旨在改进系统结构的实践活动。
- 每个改造都是微不足道的,但是这些所有的改造迭加在一起,就形成了对系统设计和架构显著的改进。
- 每次重构进行完后,必须运行单元测试,保证重构没有造成任何破坏,然后再去做下一次重构。而且,重构是持续进行的。
-
隐喻
- 隐喻是将整个系统联系在一起的全局视图,它是系统的未来景象,是它使所有单独模块的位置和外观变得明显直观。
-
结论
- 极限变成是一组简单、具体的实践,这些实践结合在一起形成了一个敏捷开发过程。
计划
-
初始探索
- 在项目开始时,开发人员和客户会尽量确定出所有真正重要的用户素材。
- 随着项目进展,客户会不断编写新的用户素材。
- 素材的编写会一直持续到项目完成。
- 开发人员共同对这些素材进行估算。估算是相对的,不是绝对的。
-
探究、分解和速度
- 任何过大的用户素材都应该分解成小一点的部分。任何过小的用户素材都应该和其它小的素材合并。
- 当分割或合并一个用户素材后,应该对其重新进行估算。
- 对一个用户素材进行分解或者合并的主要原因为了使其大小适于被准确地估算。
- 速度因子将用户素材的估算点数乘以速度得到实现该用户素材的实际开发时间。
- 计算团队的开发速度。花费几天时间去原型化一到两个用户素材来了解团队的速度。
-
发布计划
- 客户挑选在该发布中她们想要实现的素材,并大致确定这些素材的实现顺序。
- 客户不能选择与当前开发速度不符的更多的素材。
- 当开发速度变得更准确一点时,可以再对发布计划进行调整。
-
迭代计划
- 迭代期间用户素材的实现顺序属于技术决策范畴。
- 一旦迭代开始,客户就不能再改变该迭代期内需要实现的用户素材。
- 即使没有完成所有的用户素材,迭代也要在预先指定的日期结束。
- 通过速度反馈计算来保持计划与团队实际状况相同步。
-
任务计划
- 在新的迭代开始时,开发人员和客户共同制定计划。
开发人员把用户素材分解成开发任务,一个任务就是一个开发人员能够在4~16小时(半天~两天)之内实现的功能。
开发人员在客户的帮助下对这些用户素材进行分析,并尽可能完全地列举出所有的任务。- 迭代中点
在迭代进行到一般的时候,本次迭代中所安排的半数用户素材应该被完成。
如果没有完成,那么团队应该设法重新分配没有完成的任务和职责,以保证在迭代结束时能够完成所有的用户素材。
目标是要完成用户素材,而不仅仅是任务。
在迭代的中点,希望看到拥有一半素材点数的完整的用户素材被完成。 -
迭代
- 每两周,本次迭代结束,下次迭代开始。
- 在每次迭代结束时,会给客户演示当前可运行的程序。
- 要求客户对项目程序的外观、感觉和性能进行评价。
- 客户会以新的用户素材的方式提供反馈。
-
结论
- 通过一次次的迭代和发布,项目进入了一种可以预测的、舒适的开发节奏。
- 开发人员看到的是基于他们自己估算并且由他们自己度量的开发速度控制的合理的计划。
- 管理人员从每次迭代中获取数据,他们使用这些数据来控制和管理项目。
- 使用敏捷方法并不意味着涉众就可以得到他们想要的。它只不过意味着他们能够控制着团队以最小的代价获得最大的商业价值。
测试
-
编写单元测试是一种验证行为,也是一种设计行为,更是一种编写文档的行为。
-
测试驱动的开发方法
- 程序中的每一项功能都有对应的测试来验证他的操作的正确性。
- 编写测试可以使开发人员使用不同的观察点。
- 迫使开发人员把程序设计为可测试的。
- 测试可以作为一种无价的文档。
测试就像一套范例,它帮助其他程序员了解如何使用代码。
单元测试是可编译、可运行的有关系统内部结构的文档。它始终保持最新,不会和产品程序不同步。
-
测试促使模块之间隔离
-
意外获得的解耦合
-
验收测试的功能
验收测试是用来验证系统满足客户需求的黑盒测试。
为了使系统具有可测试性,就必须要在很高的系统构架层面对系统进行解耦合。 -
结论
- 验证是编写测试的好处之一。
- 测试时文档的形式,简单易懂,准确可靠。
- 测试还能够对架构和设计进行影响。
重构
-
重构的目的是使每一个软件模块都具有下列三项职责:
- 第一个职责是每一个软件模块运行起来所完成的功能。
- 第二个职责是每一个软件模块要应对变化。
- 第三个职责是每一个软件模块要和阅读它的人进行沟通。
-
原则和模式可以帮助开发人员创建更加灵活和具有适应性的软件模块。
-
但是要使软件模块易于阅读和修改,就不仅需要原则和模式,还需要纪律约束和开发人员创造美的激情。
-
一般方法名是一个动词短语,类名是一个名词短语。
-
多个细小的重构之后,要再全部读一遍产品代码。
因为重构的都是代码片断,最后再读一遍可以看看把这些片断结合在一起是否是一个具有可读性的整体。
-
重构和单元测试密不可分。
每次小碎步的重构之后,都要确保产品代码能正确通过单元测试。
-
为重构投入的时间和随后为自己和他人节省的努力相比起来是非常少的。
-
用重构来保持代码的清洁。
一次编程实践
- 让程序遵循原则的事情,可以稍后交给重构做。而不需要在最初的设计阶段就很小心的让程序遵循原则。
- 先使程序更易读。再继续向程序中添加更多功能。
- 不仅产品代码需要重构,测试代码也需要重构。
- 通过重构,尽量使产品代码的结构更像易读的伪代码。
- 最好的设计是首先编写测试,然后一小步一小步前进时逐渐形成的。