敏捷软件开发(原则、模式与实践

关键字: 敏捷 软件 开发 原则 模式 实践

《敏捷软件开发(原则、模式与实践)》
(美)Robert C.Martin 著
        邓辉 译
        孟岩 审

笔记

笔记摘录:Eleven

第一部分 敏捷开发

第1章 敏捷实践
    
    教堂尖顶上的风标,即使由钢铁制成,如果不懂得顺应风势的艺术,一样会被暴风立即摧毁。
                                                ——海因里希.海涅(1797-1856,德国诗人)

1 敏捷联盟宣言(The Manifesto of Agile Alliance)
我们正在通过亲身实践以及帮助他人实践,揭示更好的软件开发方法,通过这项工作,我们认为:
    个体和交互     胜过    过程和工具
    可以工作的软件 胜过    面面俱到的文档
    客户合作        胜过 合同谈判
    响应变化        胜过    遵循计划

1.1 个体和交互胜过过程和工具
    人是获得成功的最为重要的因素。
    一个优秀的团队成员未必就是一个一流的程序员,一个由平均水平程序员组成的团队,如果具有良好的沟通能力,将要比那些虽然拥有一批高水平程序员但是缺乏沟通和料流的团队更有可能获得成功。
    合适的工具对成功来说是重要的,但是其作用不可被过分夸大,敏捷方法建议从小的工具开始,尝试一个工具,直到发现它无法适用时才去更换它。例如:如果开始的时候没有迫切要求使用庞大的、高性能的数据库,那么就可以先使用文件来取代。  
    记住,团队的构建要比环境的构建重要得多。一个项目中,一个你该首先致力于构建团队,然后再让团队基于需要来配置环境。

1.2 可以工作的软件胜过面面俱到的文档
    没有文档的软件是一种灾难,然而过多的文档比没有文档更糟,会浪费时间和精力,如果文档和代码不能同步,文档会造成更多的代价和误导。
    对于团队来说,编写并维护一份系统原理和结构方面的文档将总是一个好主意,但是必须短小而且主题突出,“短小”的意思是说,最多有一二十页。“主题突出”是说应该仅论述系统的高层结构和概括的设计原理。
    在给新的团队成员传授知识方面,最好的两份文档是代码和团队。(代码是惟一没有二义性的信息源),在团队的头脑中,保存着时常变化的系统脉络图(road map)。人和人之间的交互是把这份脉络图传授给他人的最快、最有效的方式。
    Martin文档第一定律(Martin's first law of document):直到迫切需要并且意义重大时,才编制文档。

1.3 客户合作胜过合同谈判
    成功的项目需要有序、频繁的客户反馈。作者认为小嗯木成功的关键在于和客户之间真诚的写作,并且合同指导了这种写作,而不是试图去规定项目范围的细节和固定成本下的进度。

1.4 响应变化胜过遵循计划
    响应变化的能力常常决定这一个软件项目的成败。当我们构建计划时,应该确保计划是灵活的并且易于适应商务和技术方面的变化。
    作者认为较好的做计划的策略是:为下两周做详细的计划,为下三个月做粗略的计划,再以后就做极为粗糙的计划。我们应该清楚地知道下两周要完成的任务,粗略地了解一下以后三个月要实现的需求。至于系统一年后将要做什么,有一个模糊的想法就行了。(这样的计划仅仅支配了几周的时间,计划的其余部分仍然保持着灵活性)

2 原则
(1) 我们最有限要做的是通过尽早的、持续的交付有价值的软件来使客户满意
(2) 即使到了开发的后期,也欢迎改变需求。敏捷过程利用变化来为客户创造竞争优势。
(3) 经常性地交付可以工作的软件,交付的间隔可以从几周到几个月,交付的时间间隔越短越好。
(4) 在整个项目开发期间,业务人员和开发人员必须每天都一起工作。
(5) 围绕被激励起来的个人来构建项目。给他们提供所需要的环境和支持,并且信任他们能够完成工作。
    在敏捷项目中,人被认为是项目取得成功的最重要的因素。所有其他的因素——过程、环境、管理等——都被认为是次要的。当它们对于人有负面的影响时,就要对它们进行改变。
(6) 在团队内部,最具有效果并且富有效率的传递信息的方法,就是面对面的交谈。
(7) 工作的软件是首要的进度度量标准。
(8) 敏捷过程提倡可持续的开发速度。责任人、开发者和用户应该能够保持一个长期的、恒定的开发速度。
(9) 不断地关注优秀的技能和良好的设计会增强敏捷能力。
(10) 简单——使未完成的工作最大化的艺术——是根本。
(11) 最好的架构、需求设计出自于组织的团队。
    对于敏捷团队来说,人物不是从外部分配给单个团队成员,而是分配给整个团队,然后再由团队来确定完成任务的最好方法。
(12) 每隔一段时间,团队会在如何才能更有效地工作方面进行反省,然后相应地对自己的行为进行调整。

3 结论
敏捷过程:SCRUM,CRYSTAL,特征驱动软件开发(Feature Driven Development,简称FDD),自适应软件开发(Adaptive Software Development,简称ADP),以及最重要的极限编程(eXtreme Programming,简称XP)。



第2章 极限编程概述

    作为开发人员,我们应该记住,XP并非惟一选择。
                                    ——Pete MaBreen

1 极限编程实践
极限编程(eXtreme Programming,简称XP)是敏捷方法中最著名的一个。它由一系列简单却互相以来的实践组成。这些实践结合在一起形成了一个胜于部分结合的整体。

1.1 客户作为团队成员
    XP团队中的客户是指定义产品的特性并排列这些特性优先级的人或者团体。在XP项目中,无论谁是客户,他们都是能够和团队一起工作的团队成员。
    最好的情况是客户和开发人员在同一个房间中工作,次一点的情况是客户和开发人员之间的距离在100米内,距离越大,客户就越难成为真正的团队成员,作者认为,如果确实无法和客户在一起工作,那么就去寻找能够在一起工作、愿意并能够代替真正客户的人。

1.2 用户素材
    为了进行项目计划,必须要知道和项目需求有关的内容,但是却无须知道得太多。对于做计划而言,了解需求只需要做到能够估算它的程度就足够了。
    需求的特定细节很可能会随实践而改变。因此,在离真正实现需求还很早的时候就去捕获该需求的特定细节,很可能会导致做无用功以及对需求不成熟的关注。
    用户素材(user stories,当然,在这里我更喜欢称其为用户故事)就是正在进行的关于需求谈话的助记符。它是一个计划工具,客户可以使用它并根据它的优先级和估算代价来安排实现该需求的实践。

1.3 短交付周期
    XP项目每两周交付一次可以工作的软件。每两周的迭代(interaction,也可成为成哦故你服周期或循环周期)都实现了涉众的一些需求,在每次迭代结束时会给涉众演示迭代生成的系统,以得到他们的反馈。
迭代计划:每次迭代通常耗时两周。是一次较小的交付,可能会被加入到产品中,也可能不会。它由客户根据开发人员确定的预算而选择一些用户素材组成。
        一旦迭代开始,客户就统一不再修改当次迭代中用户素材的定义和优先级别,迭代期间,开发人员可以自由地将用户素材分解成为任务(task),并根据最具技术和商务意义的顺序来开发这些任务。
发布计划:XP团队通常会创建一个计划来规划随后大约6次迭代的内容,也就是所谓的发布计划。一次发布通常需要3个月的工作。它表示了一次较大的交付,通常此次交付会被加入到产品中。
        发布计划是由一组客户根据开发人员给出的预算所选择的、排好优先级别的用户素材组成。
        发布计划不是一成不变的,客户可以随时改变计划的内容,他可以取消用户素材,编写新的用户素材,或者改变用户素材的优先级别。(这里我个人认为并不是可以随时进行更改,而应当是说在未来2周也就是迭代计划中所用到的用户素材是不可以进行更改的,而之后的都是可以根据用户需要进行更改或者其他操作)

1.4 验收测试
    可以以客户指定的验收测试(Acceptance Tests)的形式来捕获有关用户素材的细节。用户素材的验收测试是在就要实现该用户素材之前或实现该用户素材的同时进行编写的。(可以看出,和一般的功能测试或者单元测试并不相同)
    验收测试使用能够让它们自动并且反复运行的某种脚本语言编写,这些测试共同来验证系统按照客户指定的行为运转。
    客户可以借助于QA来开发验收测试工具,并编写验收测试。
    一点通过一项验收测试,那么就加入到已通过的验收测试集中,并决不允许该测试再次失败。这个验收测试集每天会被多次运行,每当系统被创建时,都需要运行这个验收测试集,如果一项验收测试失败,那么系统创建宣告失败。因此,一项需求一旦被实现,就再不会遭到破坏。系统从一种工作状态变迁到另一种工作状态,期间,系统的不能工作状态时间决不允许超过几个小时。

1.5 结队编程
    所有产品(production)代码都是由结队的程序员使用同一台电脑共同完成的。结队人员中的一位控制键盘并输入代码,另一位观察输入的代码并寻找着代码中的错误和可以改进的地方。两个人强烈地(intensely)进行着交互,他们都全身心地投入到软件的编写中。
    结队变成的代码是由两人共同设计、共同编写的,两人功劳均等。
    结队的关系每天至少改变一次,以便于每个程序员在一天中可以在两个不同的结队中工作。在一个迭代期间,每个团队成员应该和所有其他的团队成员在一起工作过,并且他们应该参与了本次迭代中所涉及的每项工作。
    这样可以促进知识在团队中的传播。
    Laurie Willianms和Nosek的研究表明,结队非但不会降低开发团队的效率,而且会大大减少缺陷率。

1.6 测试驱动的开发方法
    编写所有产品代码的目的都是为了使失败的单元测试能够通过。首先编写一个单元测试,由于它要测试的功能还不存在,因此它会运行失败,然后,编写代码使测试通过。而且这样的方式非常利于重构。而且这样一种方式可以激发程序员去解除各个模块之间的耦合,这样能够独立地对它们进行测试。面向对象设计的原则在进行这种解除耦合方面具有巨大的帮助作用。

1.7 集体所有权
    结队编程中的每一对都具有拆出(check out)任何模块并对它进行改进的权力。没有程序员对任何一个特定的模块或技术单独负责,每个人都参与GUI方面的工作;每个人都参与中间件方面的工作;每个人都参与数据库方面的工作。没有人比其他人在一个模块或者技术上具有更多的权威。

1.8 持续集成
    XP团队每天会进行多次系统构建,他们会重新创建整个系统。

1.9 可持续的开发速度
    XP团队必须要以一种可持续的速度前进,必须要有意识地保持稳定、适中的速度。
    XP的规则是不允许团队加班工作。在版本发布前的一个星期是该规则的惟一例外。如果发布目标就在眼前并且可以一蹴而就,则允许加班。

1.10 开放的工作空间
    密歇根大学的一项研究表明,在“充满积极讨论的屋子(war room)”里工作,生产率非但不会降低,反而会成倍地提高。

1.11 计划游戏
    计划游戏(planning game)的本质是划分业务人员和开发人员之间的职责。业务人员(客户)决定特性(feature)的重要性,开发人员决定实现一个特性所花费的代价。在每次发布和每次迭代的开始,开发人员基于在最近一次迭代或者最近一次发布中他们所完成的工作量,为客户提供一个预算。客户选择那些所需的成本合计起来不超过该预算的用户素材。

1.12 简单的设计
    XP团队使他们的设计尽可能地简单、具有表现力(expressive)。此外,他们仅仅关注于计划在本次迭代中要完成的用户素材。他们不会考虑那些未来的用户素材。这意味着XP团队的工作可能不会从基础结构开始,只有当出现一个用户素材迫切需要基础结构时,他们才会引入该基础结构。
三条XP知道原则(mantras):
(1) 考虑能工作的最简单的事情
(2) 你将不需要它
(3) 一次,并且只有一次

1.13 重构(refactoring)
    重构就是在不改变代码行为的前提下,对其进行一系列小的改造(transformation),旨在改进系统结构的实践活动。每个改造都是微不足道的,但是这些所有的改造迭加在一起,就形成了对系统设计和架构显著的改进。(也就是只要认为可以进行改进的地方,就必须毫不犹豫地去进行改进)
    每次重构进行完后,必须运行单元测试,保证重构没有造成任何破坏,然后再去做下一次重构。而且,重构是持续进行的。

1.14 隐喻
    隐喻(metaphore)是所有XP实践中最难理解的一个。隐喻是将整个系统联系在一起的全局视图,它是系统的未来景象,是它使所有单独模块的位置和外观(shape)变得明显直观。

2 结论
    极限变成是一组简单、具体的实践,这些实践结合在一起形成了一个敏捷开发过程。



第3章 计划

    当你能够度量你所说的,并且能够用数字去表达它时,就表示你了解了它;若你不能度量它,不能用数字去表达它,那么说明你的知识就是匮乏的、不能令人满意的。
                                                                                            ——凯尔文勋爵(英国物理学家),1883

1 初始探索
    在项目开始时,开发人员和客户会尽量确定出所有真正重要的用户素材。然而,他们不会试图去确定所有的用户素材。随着项目的进展,客户会不断编写新的用户素材。素材的编写会一直持续到项目完成。(这里应该主要是由于需求伴随着项目的进展发生着变化,因此才会这样的吧)
    开发人员共同对这些用户素材继续估算。估算是相对的,不是绝对的。我们在记录素材的卡片上写一些“点数”表示实现这个素材的相对时间,我们无法确定每个点数代表的时间,但是我们知道8个点的素材所需要的时间应该是4个点的两倍。
    任何过大的素材都应该被分解成小一点的部分,任何过小的素材都应该和其他小的素材进行合并。
    为知道用户素材的绝对大小,需要一个成为速度(velocity)的因子。
    伴随项目的进展,由于可以度量每次迭代中已经产正的用户素材点数,所以速度的度量会越来越准确。通常,去原型化一到两个用户素材来了解团队的速度就足够了,这样的一个原型化的过程成为探究(spike)。

2 发布计划
    用户素材实现顺序的选择不是单纯依据优先级进行的,一些重要的但是实现起来代价高昂的素材可能会被推迟实现,而会先去实现一些不那么重要的,但是代价要低廉得多的素材。此类选择属于商务(business)决策范畴。让业务人员来选定那些会给他们带来最大利益的素材。
    当开发速度变得准确的时候,可以对发布计划进行相应的调整。

3 迭代计划
    在选择用户素材的时候,觉不允许客户选择与当前开发速度不符的更多的素材。
    迭代期间用户素材的实现顺序属于技术决策范畴,开发人员采用最具技术意义的顺序来实现这些素材。
    和前面提到的一样,一旦迭代开始,客户就不能再改变该迭代期内需要实现的素材。
    即使没有完成所有的素材,迭代也要在先前指定的日期结束。开发人员会合计所有已经完成的素材的估算值,然后计算本次迭代的开发速度,这个速度会被用于下次迭代。规则很简单:每次迭代做计划时采用的开发速度就是前一次迭代中测算出的开发速度。

4 任务计划
    在新的迭代开始时,开发人员和客户共同制定计划。开发人员把素材分解成开发任务,一个人物就是一个开发人员能够在4-16个小时内实现的一些功能。
    每个开发人员都知道在最近一次迭代中完成的任务点数,这个数字可以作为下一次迭代中的个人预算。
    任务的选择一直到所有的任务都被分配出去,或者所有的开发人员都已经用完了他们的预算时为止。如果任务还没有分配完毕,那么会互相协商,开发人员将基于各自的特长交换相应的任务。如果还是有多余任务,那么就将考虑要求客户从本次迭代中去掉一些任务或者素材。如果所有的任务都已经被分配,并且开发人员仍然具有预算空间去完成更多的任务,那么他们将会向客户要求更多的素材。
    在迭代进行到一半的时候,团队必须召开会议查看所完成的素材(并非是任务,因为任务完成了一半,素材却都没有完成的情况,是毫无意义的)数量,应该是一半的素材都被完成,如果没有,那么团队应该设法重新分配没有完成的任务和职责,以保证在迭代结束时能够完成所有的素材。

5 迭代
    每次迭代结束时,会给客户演示客户演示当前可运行的程序。客户将会根据他们看到的反馈新的用户素材。

6 结论
    通过一次次迭代和发布,项目进入了一种可以预测的、舒适的开发节奏。
    使用敏捷方法并不意味着涉众就可以得到他们想要的。它不过意味着他们将能够控制着团队以最小的代价获得最大的商业价值。

 

第4章 测试

            烈火验真金,逆境磨意志。
                        ——卢修斯.塞尼加(公元前4-公元65)

1 测试驱动的开发方法
    测试驱动的方法对于我们正在编写的软件的设计有积极的影响:
    (1) 程序中的每一项功能都有测试来验证它的操作的正确性。
    (2) 首先编写测试可以迫使我们使用不同的观察点,可以设计出便于调用的软件
    (3) 通过首先编写测试,可以迫使自己把程序设计为可测试的,迫使我们解除软件中的耦合(force us to decouple the software)
    (4) 测试可以作为一种无价的文档形式
    我们相信,只要按照测试所暗示的结构去编写程序,就能通过测试,这种方法成为有意图的编程(intentional programming)。
    测试促使模块之间隔离和解耦合
   
2 验收测试
    对于验证工具来说,单元测试是必要的,但是不够充分。单元测试用来验证系统的小的组成单元应该按照所期望的工作方式,但是它们没有验证系统作为一个整体时工作的正确性。单元测试是用来验证系统中个别机制的白盒测试(white-box tests)。验收测试是用来验证系统满足客户需要的黑盒测试(black-box tests)。
    验收测试由不了解系统内部机制的人编写。客户可以直接或者和一些技术人员(比如QA等)一起来编写验收测试。验收测试是程序,因此是可以运行的。然而,通常使用专为应用程序的客户创建的脚本语言来编写验收测试。  在这里不能由系统代码编写人员来编写验收测试!
    验收测试是关于一项特性(feature)的最终文档。  单元测试作为可编译、运行的有关系统内部结构的文档,而验收测试是有关系统特性的可编译、执行的文档。
    此外,首先编写验收测试的行为对于系统的架构方面具有深远的影响。为了使系统具有可测试行,就必须要在很高的系统架构层面对系统进行解耦合。
    验收测试可以促使你在大的方面做出优良的系统架构决策。
    创建一个验收测试框架(framework)看起来是件困难的任务。然而,如果仅仅创建框架中对单个迭代包含的特性进行验收测试所需要的那部分,就会发现并不困难。你还会发现所花费的努力是值得的。  在这里可以看到,每次迭代都需要进行验收测试,而且这样的工作量也不会太大。
    我们还没有编写任何代码,也没有进行任何设计。这是开始考虑验收测试的的最好时机,揭示意图编程再一次成为有用的工具。我们应该以我们认为验收测试应该的样子去编写它们,然后可以构建脚本语言,并根据脚本语言的结构来构造所将要开发的系统。   (这一点是非常值得我们在项目开发过程中借鉴的,当没有开始对系统进行设计和代码编写的时候就优先对系统进行验收测试的考虑和用脚本语言来构造验收测试,这样就可以迫使我们去让我们即将设计和开发的系统按照我们所构想的验证测试来实现代码的编写,对于设计和架构都是非常有帮助的!)
    为使系统验证便于编写并易于改变。把它们放置在一个配置管理工具中,并且把它们保存起来以便于随时可以运行它们。因此,采用简单的文本文件来编写验收测试应该比较合理。

3 结论
    单元测试和验收测试都是一种文档形式,那样的文档是可以编译和执行的;因此,它是准确和可靠的。此外,编写测试所使用的语言是明确的,并且它们的观看者使这些语言非常易读。程序员能够阅读单元测试,因此单元测试是使用程序员编程的语言编写的。客户能够阅读验收测试,因为验收测试是使用客户自己设计的语言编写的。
    也许,测试最重要的好处就是它对架构和设计的影响(也的确如此)。为了使一个模块或者应用程序具有可测试性,就必须要对它进行解耦合。越是具有可测试性,耦合关系就越弱。全面地考虑验收测试和单元测试的行为对软件的结构具有深远的正面影响。



第5章 重构
   
            大千世界中,惟一缺乏的就是人类的注意力。
                            ——凯文.凯利(“新经济”的首席预言家之一),连线杂志

    在Martin Fowler的名著《重构》一书中,他把重构(Refactoring)定以为:“……在不改变代码外在行为的前提下对代码做出修改,以改进代码的内部结构的过程。”
    每个软件模块都有三项职责。第一个职责是它运行起来所完成的功能。这也是该模块得以完成的原因。第二个职责是它要应对变化。几乎所有的模块在它们的生命周其中都要变化。开发者有责任保证这种改变应该尽可能地简单。第三个职责是要和阅读它的人进行沟通。对该模块不熟悉的开发人员应该能够比较容易地阅读并理解它。

1 素数产生程序:一个简单的重构示例
    例子略

2 结论
    重构后的程序读起来比一开始要好得多,程序工作得也更好一些。程序可以变得更容易被理解,且程序结构的各部分之间互相隔离,这也使它更容易更改。
    重构的目的,是为了每天清洁你的代码。我们想通过最小的努力就能够对我们的系统进行扩展和修改,要想具有这种能力,最重要的就是要保持代码的清洁。



第6章 一次编程实践

        设计和编程都是人的活动,忘记了这一点,将会失去一切。
                                ——Bjarne Stroustrup, 1991   
   
    在本章中作者给出了一次编程实践,一个保龄球的程序,用一个实例给出了结队编程的详细情景,比较经典!
   




第二部分 敏捷设计

    在敏捷团队中,全局视图和软件一起演化。在每次迭代中,团队改进系统设计,使设计尽可能适合于当前系统。团队不会花费许多实践去预测未来的需求和需要,也不会试图在今天就构建一些基础结构去制成那些他们认为明天才会需要的特性。他们更愿意关注当前的系统结构,并使它尽可能地好。

    拙劣的设计症状定义:
    僵化性(Rigidity):设计难于改变
    脆弱性(Fragility):设计易于遭到破坏
    牢固性(Immobility):设计难于重用
    粘滞性(Viscosity):难以做正确的事情
    不必要的复杂性(Needless Complexity):过分设计
    不必要的重复(Neddless Repetition):滥用鼠标
    晦涩性(Opacity):混乱的表达

    一些面向对象设计原则:
    单一职责原则(The Single Responsibility Principle,简称SRP)
    开放-封闭原则(The Open-Close Principle,简称OCP)
    Liskov替换原则(The Liskov Substitution Principle,简称LSP)
    依赖倒置原则(The Dependency Inversion Principle,简称DIP)
    接口隔离原则(The Interface Segregation Interface,简称ISP)

    敏捷团队应用这些原则来除去臭味。当没有臭味时,他们不会应用这些原则。仅仅因为是一个原则就无条件的去遵守它的做法是错误的。这些于原则不是可以随意在系统中到处喷洒的香水。过分遵循这些原则会导致不必要的复杂性(Needless Complexity)的设计臭味。

第7章 什么是敏捷设计

        “在按照我的理解方式审查了软件开发的生命周期后,我得出一个结论:实际上满足工程设计标准的惟一软件文档,就是源代码清单。”
                                                                                            ——Jack Reeves

1 设计的臭味——腐化软件的气味
(1)僵化性 僵化性是指难以对软件进行改动,即使简单的改动。如果单一的改动会导致有依赖关系的模块中俄连锁改动,那么设计就是僵化的。必须要改动的模块越多,设计就越僵化。
(2)脆弱性 脆弱性是指,在进行一个改动时,程序的许多地方就可能出现问题。常常是,出现新问题的地方与改动的地方并没有概念上的关联。要修正这些问题就会引出更多的问题,从而使开发团队就像一只不停追逐自己尾巴的狗。   呵呵,这个形容真的很贴切
(3)牢固性 牢固性是指,设计中包含了对其他系统有用的部分,但是要把这些部分从系统中分离出来所需要的努力和风险是巨大的。这是一件令人遗憾的事,但是确实非常常见的事情。
(4)粘滞性 粘滞性有两种表现形式:软件的粘滞性和环境的粘滞性。
        当那些可以保持系统设计的方法比那些生硬手法更难应用的时候,就表明设计具有高的粘滞性。
        当开发环境迟钝、低效时,就会产生环境的粘滞性。
        无论项目具有哪种粘滞性,都很难保持项目中的软件设计。我们希望创建易于保持设计的系统和项目环境。
(5)不必要的复杂性 如果设计中包含有当前没有用的组成部分,它就包含不必要的复杂性。
(6)不必要的重复 剪切和粘贴也许是有用的文本编辑操作,但是它们却是灾难性的代码编辑操作。
    当同样的代码以稍微不同的形式一再出现时谬表示开发人员忽视了抽象。对于它们来说,发现所有的重复并通过适当的抽象去消除它们的做法可能没有高的优先级别,但是这样做非常有助于使系统更加易于理解和维护。
(7)晦涩性 晦涩性是指模块难以理解。
        为防止这种情况的发生,开发人员必须要站在代码阅读者的位置,共同努力对它们的代码进行重构,这样代码的阅读者就可以理解代码。可以被其他人进行评审。

    大作数软件项目中最不稳定的东西就是需求。需求处在一个持续变动的状态之中。这是我们作为开发人员必须得接受的事实!我们生存在一个需求不断变化的世界中,我们的工作是要保证我们的软件能够经受得住那些变化。如果我们软件的设计由于需求变化而退化,那么我们就不是敏捷的。
    敏捷团队不是在一开始设计该模块时就试图预测程序将如何变化。相反,他们是以最简单的方法编写的。直到需求最终确实变化时,他们才修改模块的设计,使之对该种变化保持弹性。
    简单而言,敏捷开发人员知道要做什么,是因为:
    (1)他们遵循敏捷实践去开发问题;
    (2)他们应用设计原则去诊断问题;
    (3)他们应用适当的设计模式去解决问题。
    软件开发的这三个方面间的互相作用就是设计。

    敏捷开发人员致力于保持设计尽可能地适当、干净。设计必须要保持干净、简单,并且由于源代码是设计最重要的表示,所以它同样要保持干净。职业特性要求我们,作为软件开发人员,不能忍受代码腐化。

2 结论
    敏捷设计是一个过程,不是一个事件。它是一个持续的应用原则、模式以及实践来改进软件的结构和可读性的过程。它致力于保持系统设计在任何实践都尽可能得简单、干净以富有表现力。



第8章 单一职责原则(SRP)

        只有佛自己应当担负起公布玄妙秘密的职责。
                            ——E.Cobham Brewer, 1810-1897
                                        《英语典故字典》,1898

    这条原则曾经在Tom DeMaro和Meilir Page-Jones的著作中描述过,并称之为内聚性(cohesion)。他们把内聚性定义为:一个模块的组成元素之间的功能相关性。

1 单一职责原则   
    就一个类而言,应该仅有一个引起它变化的原因。
    每一个职责都是变化的一个轴线(an axis of change)。当需求变化时,该变化会反映为类的职责的变化,如果一个类承担了多余一个的职责,那么引起它变化的原因就会有多个。 如果一个类承担的职责过多,就等于把这些职责耦合在了一起。一个值得的变化可能会削弱或者一直这个类完成其他职责的能力。这种耦合会导致脆弱的(fragile)设计,当变化发生时,设计会遭受到意想不到的破坏。
    在SRP中,我们把职责定义为“变化的原因”(a reason for change)。如果你能够想到多余一个的动机去改变一个类,那么就具有多于一个的职责。

2 结论
    SRP是所有原则中最简单的之一,也是最难正确运用的之一。我们会自然地把职责结合在一起。软件设计真正要做的许多内容,就是发现职责并把那些职责互相分离。事实上,我们将要论述的其余原则都会以这样或那样的方式回到这个问题上。

你可能感兴趣的:(设计模式,软件测试,XP,单元测试,敏捷开发)