面对现实,超越自己
逆水行舟,不进则退
posts - 269,comments - 32,trackbacks - 0
来源于《敏捷软件开发——原则、模式与实践》

常见的设计的臭味——腐化软件的气味

l         僵化性(Rigidity):很难对系统进行改动,因为每个改动都会迫使许多对系统其他部分的其他改动。

l         脆弱性(Fragility):对系统的改动会导致系统中和改动的地方在概念上无关的许多地方出现问题。

l         牢固性(Immobility):很难解开系统的纠结,使之成为一些可在其他系统中重用的组件。

l         粘滞性(Viscosity):做正确的事情比做错误的事情要困难。

l         不必要的复杂性(Needless Complexity):设计中包含有不具任何直接好处的基础结构。

l         不必要的重复(Needless Repetition):设计中包含有重复的结构,而该重复的结构本可以使用单一的抽象进行统一。

l         晦涩性(Opacity):很难阅读、理解。没有很好的表现出意图。

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

敏捷软件开发宣言:

我们正在通过亲身实践以及帮助他人实践,揭示更好的软件开发方法。通过这项工作,我们认为:
个体和交互 胜过 过程和工具
可以工作的软件 胜过 面面俱到的文档
客户合作 胜过 合同谈判
响应变化 胜过 遵循计划
虽然右项也具有价值,但我们认为左项具有更大的价值。
敏捷开发强调以人为中心,而不是以过程为中心,强调尽可能的沟通(与客户,与团队成员),尽可能地以最简单的设计解决问题(从而能够拥抱变化)。

敏捷宣言遵循的原则
我们遵循以下原则:

 

1。我们最优先要做的是通过尽早的、持续的交付有价值的软件来使客户满意。

   规划迭代故事时必须按照优先级安排,为客户先提供最有价值的功能。通过频繁迭代能与客户形成早期的良好合作,及时反馈提高产品质量。敏捷小组关注完成和交 付具有用户价值的功能,而不是孤立的任务。以前我们都用需求规格说明书或者用例来编写详细的需求,敏捷使用用户故事来罗列需求。用户故事是一种表示需求的 轻量级技术,它没有

固定的形式和强制性的语法。但是有一些固定的形式可以用来参考还是比较有益的。敏捷估算中使用了这个模板:“作为【用户的类型】,我希 望可以【能力】以便【业务价值】“。使用基于用户故事的需求分析方法时,仍可能需要原型和编写文档,只是工作重点更多的转移到了口头交流。

 

2。即使到了开发的后期,也欢迎改变需求。敏捷过程利用变化来为客户创造竞争优势。

  敏捷过程参与者不怕变化,他们认为改变需求是好事情,因为这些改变意味着我们更了解市场需求。
  
3。经常性的交付可以工作的软件,交付的间隔可以从几周到几个月,交付的时间间隔越短越好。

   迭代是受实践框限制的,意味着即使放弃一些功能也必须按时结束迭代。只要我们可以保证交付的软件可以很好的工作,那么交付时间越短,我们和客户协作就越 紧密,对产品质量就更有益。虽然我们多次迭代,但并不是每次迭代的结果都需要交付给用户,敏捷开发的目标是让他们可以交付。这意味着开发小组在每次迭代中 都会增加一些功能,增加的每个功能都是经过编码、测试,达到了可发布的质量标准的。
  另外敏捷开发项目中对开发阶段没有什么重要的分割,没有先期的需求阶段,然后是分析阶段,架构设计阶段,编码测试阶段等,在项目真正开始后,每次迭代中都会同时进

行所有的上述阶段工作。
 
4。在整个项目开发期间,业务人员和开发人员必须天天都在一起工作。

  软件项目不会依照之前设定的计划原路执行,中间对业务的理解、软件的解决方案肯定会存在偏差,所以客户、需求人员、开发人员以及涉众之间必须进行有意义的、频繁 

的交互,这样就可以在早期及时的发现并解决问题。
 
5。围绕被激励起来的人个来构建项目。给他们提供所需要的环境和支持,并且信任他们能够完成工作。

  业务和技术是引起不确定的二个主要方面,人是第三个方面。而业务和技术又必须由人来执行,所以能够激励人来解决这些问题是解决不确定性的关键。只要个人的目标和团

队的目标一致,我们就需要鼓舞起每个人的积极性,以个人为中心构建项目,提供所需的环境、支持与信任。

 

6。在团队内部,最具有效果并且富有效率的传递信息的方法,就是面对面的交谈。

  在十几或者二十几个人组成的大团队中,文档是一种比较合适的传递知识和交流的途径。而敏捷团队一般不会很多人(大团队实施敏捷时也会分成多个小的敏捷团队),所以

大量的文档交流其实并不是很经济的做法。此时面对面的交谈反而更快速有效。
 
7、可工作的软件是首要进度度量标准。

   一般的工作都比较容易衡量任务进展,比如让你去搬运1吨的石头,我只要去称一下你已经搬运的石头重量就知道你完成多少了。而对于软件来说,在软件没有编 码、测试完

成之前,我们都不能因为代码编写了多少行,测试用例跑了多少个就去度量这个功能是否完成了。衡量这个功能是否完成的首要标准就是这个功能可以工 作了,对用户来说已经可

以应用了。

 

8。敏捷过程提可持续的开发速度。责任人、开发者和用户应该能够保持一个长期的、恒定的开发速度。

   很多人都认为软件开发中加班是很正常的,不加班反而不正常,我对此有点不理解,这个可能是国情所致吧。敏捷过程希望能够可持续的进行开发,开发速度不会 随着迭代的任务不同而不同,不欣赏所谓的拼一拼也能完成的态度,开发工作不应该是突击行为。我们不能指望说突击这个项目后就可以轻松了,因为完成一个项目 后会接踵而来下一个项目,而只要还是拼拼的态度,下一个项目依旧会让你的组员再次突击。这时不知道有人会不会说,那我们就一直加班,也是“持续的开发速 度”啊,这时可要注意了,持续加班智

慧导致人疲劳、厌倦,保持长期恒定的速度也只是一种理想而已。
 
9。不断地关注优秀的技能和好的设计会增强敏捷能力。

  敏捷过程有很多好的技术实践可以加强产品敏捷能力,很多原则、模式和实践也可以增强敏捷开发能力。 《敏捷软件开发-原则、模式与实践》一书中介绍了很多设计,感兴趣的可以去仔细看看。
 
10。简单----使未完成的工作最大化的艺术----是根本的。

   我们不可能预期后面需求会如何变化,所以不可能一开始就构建一个完美的架构来适应以后的所有变化。敏捷团队不会去构建明天的软件,而把注意力放在如何通 过最简单的方法完成现在需要解决的问题。这时有人会说,我已经预计到了肯定存在哪些需求扩展点,我们在一开始是否需要考虑呢?这时团队需要根据自己的理解 去决定是否考虑,如果深信在明天发生了这个问题也可以轻易处理的话,那么就最好先不考虑。
 
11。最好的构架、需求和设计出自与自组织的团队。

        敏捷中有很多种实践,大家都知道,迭代式开发是主要的实践方法,而自组织团队也是主要的实践之一。在自组织团队中,管理者不再发号施令,而是让团队自身寻找最佳的工作方式来完成工作。要形成一个自组织团队其实比较难。CSDN采访Mishkin Berteig中说到 自组织团队的第一个要素就是必须有一个团队,而不仅仅是一群人。一群人是一帮在一起工作的人,他们彼此之间并没有太多的沟通,他们也并不视彼此为一体。项目一开始,我们就会组建“团队”,但很多时候由构架师、需求人员、开发人员和测试人员组成的是一群人而已。他还认为,团队的形成必须经历几个时期。在 经历了初期的磨合后,成员才会开始对团队共同的工作理念与文化形成一个基本的认识和理解。团队内会逐渐形成规矩,而且这些规矩是不言而喻的。比如,每个人 都知道上午九点来上班,都会主动询问别人是否需要帮助,也都会去主动和别人探讨问题。如果团队成员之间能够达成这样的默契,那么这个团队将成为一个真正高 效的工作团队。在这样团队中,成员之间相互理解,工作效率非常高。在自组织团队中,团队成员不需要遵从别人的详细指令。他们需要更高层次的指导,这种指 导更像是一个目标,一个致力于开发出更好的软件的目标。总之,自组织团队是一个自动自发、有着共同目标和工作文化的团队,这样的团队总是在向它的组织做出 承诺。但是,实现这些承诺对于自组织团队来说非常重要。否则,一旦出现问题,团队成员之间就会出现信任危机。


  虽然敏捷开发小组是以小组为整体 来工作的,但是还是有必要指明一些承担一定任务的角色。第一个角色是产品所有者(Product Owner)。产品所有者的主要职责包括:确认小组所有成员都在追求一个共同的项目前景,确定功能的优先级以便总是在处理最具有价值的功能,以及作出决定 使得对项目的投入可以产生良好的回报。可以对应为以前开发中的“产品经理”。另一角色是开发团队(developer),这里的开发人员包括了架构师、设计师、程序员、需求人员、测试人员、文档编写者等,有时产品所有者也可以被看作是

开发人员。还有一个重要角色就是项目经理(project manager)。敏捷开发的项目经理会更多的关注领导而不是管理。在某些项目中,项目经理可能同时也是开发人员,少数时候也会担任产品所有者。
   
12。每隔一定时间,团队会在如何才能更有效地工作方面进行反省,然后相应地对自己的行为进行调整。

  由于很多不确定性因素会导致计划失效,比如项目成员增减、技术应用效果、用户需求的改变、竞争者对我们的影响等都会让我们作出不同的反应。 敏捷不是基于预定义的工作方式,而是基于经验性的方式,对以上这些变化,小组通过不断的反省调整来保持团队的敏捷性。

面向对象设计的原则:

SRP 单一职责原则
 就一个类而言,应该仅有一个引起它变化的原因。

l         单一职责原则The Single Responsibility Principle,简称SRP):就一个类而言,应该仅有一个引起它变化的原因。在SRP中,我们把职责定义为“变化的原因()”。如果你能够想到多于一个的动机去改变一个类,那么这个类就具有多于一个的职责。软件设计真正要做的许多内容,就是发现职责并把那些职责相互分离。事实上,我们将要论述的其余原则都会以这样或那样的方式回到这个问题上。

l         开放封闭原则The Open-Close Principle,简称OCP):软件实体(类、模块、函数等等)应该是可以扩展的,但是不可以修改的。遵循开放封闭原则设计出的模块具有两个主要的特征。它们是:(1)、对于扩展是开放的。这意味着模块的行为是可以扩展的。当应用的需求改变时,我们可以对模块进行扩展,使其具有满足那些改变的新行为。换句话说,我们可以改变模块的功能。(2)、对模块行为进行扩展时,不必改动模块的源代码或者二进制代码。模块的二进制可执行版本,无论是可链接的库、DLL或者Java.jar文件,都无需改动。

l         Liskov替换原则The Liskov Substitution Principle,简称LSP):子类型必须能够替换掉它们的基类型。OCP原则是OOD中很多说法的核心LSP是使OCP成为可能的主要原则之一。正式子类型的可替换性才使得使用基类类型的模块在无需修改的情况下就可以扩展。这种可替换性必须是开发人员可以隐式依赖的东西。

l         依赖倒置原则The Dependency Inversion Principle,简称DIP):(1)、高层模块不应该依赖于底层模块。二者都应该依赖于抽象。(2)、抽象不应该依赖于细节。细节应该依赖于抽象。使用传统的过程化设计所创建出来的依赖关系结构,策略是依赖于细节的。面向对象的程序设计倒置了依赖关系结构,使得细节和策略都依赖于抽象,并且常常是客户拥有服务接口。事实上,这种依赖关系正式好的面向对象设计的标志所在。

l         接口隔离原则The Interface Segregation Interface,简称ISP):不应该强迫客户依赖它们不用的方法。如果强迫客户程序依赖于那些它们不适用的方法,那么这些客户程序就面临着由于这些未使用方法的改变所带来的变更。这就无意中导致了所有客户程序之间的耦合。我们希望尽可能地避免这种耦合,因此我们希望分离接口。

      REP 重用发布等价原则
       重用的粒度就是发布的粒度
      CCP 共用封闭原则
      包中的所有类对于同一类性质的变化应该是共同封闭的。一个变化若对一个包产生影响,则将对该包中的所有类产生影响,而对于其他的包不造成任何影响。
      CRP 共同重用原则
      一个包中的所有类应该是共同重用的。如果重用了包中的一个类,那么就要重用包中所有类。
      ADP 无环依赖原则
      在包的依赖关系图中不允许存在环。
      SDP 稳定依赖原则
      朝着稳定的方向进行依赖。
      SAP 稳定抽象原则
      包的抽象程度应该和其稳定程度一致。

极限编程实践
完整团队
XP项目的所有参与者(开发人员、业务分析师、测试人员等等)一起工作在一个开放的场所中,他们是同一个团队的成员。
计划游戏
计划是持续的,循序渐进的。每2周,开发人员就为下2周估算候选特性的成本,而客户则根据成本和商务价值来选择要实现的特性。
客户测试
作为选择每个所期望的特性的一部分,客户定义出自动验收测试来表明该特性可以工作。
简单设计
团队保持设计恰好和当前的系统功能相匹配,它通过了所有的测试,不包含任何重复,表达出了编写者想表达的所有东西,并且包含尽可能少的代码。
结对编程
所有的产品软件都是由两个程序员,并排坐在一起在同一台电脑上构建的。
测试驱动开发
程序员以非常短的循环周期工作,他们先增加一个失败的测试,然后使之通过。
改进设计
随时改进糟糕的代码。保持代码尽可能的干净,具有表达力。
持续集成
团队总是使系统完整地被集成。
集体代码所有权
任何结对的程序员都可以在任何时候改进任何代码。
编码标准
系统中所有的代码看起来就好像是被单独一个--非常值得胜任的--人编写的。
隐喻
团队提出一个程序工作原理的公共景像。
可持续的速度
团队只有持久才有获胜的希望,他们以能够长期维持的速度努力工作,他们保存精力,他们把项目看作是马拉松长袍,而不是全速短跑。

 

测试驱动开发

极限编程(eXtreme Programming,简称XP)是敏捷方法中最著名的一个。它由一系列简单却相互依赖的时间组成。这些实践结合在一起形成了一个胜于部分结合的整体。其中一个非常重要的,当前也受到格外重视的实践就是TDD(测试驱动的开发方法)。

在测试驱动的开发方法中,编写所有的代码的目的都是为了使失败的单元测试能够通过。首先编写一个单元测试,由于它要测试的功能还不在,所以它会运行失败。然后编写代码使测试通过。

编写测试用例和代码之间的更迭速度是很快的,基本上几分钟左右。测试用例和代码共同演化,其中测试用例循序渐进地对代码的编写进行指导。作为结果,一个非常完整的测试用例集和代码一起发展起来。

测试粗略的可以分为单元测试和验收测试。单元测试是用来验证系统中个别机制的白盒测试。

单元测试用来验证系统的小的组成单元应该按照所期望的方式工作,但是它们没有验证系统作为一个整体时工作的正确性。所以,单元测试是必要的,但是不够充分。

验收测试是用来验证系统满足客户需求的黑盒测试。验收测试由不了解系统内部机制的人编写。验收测试是程序,因此是可运行的。通常通过使用专门为应用程序的客户创建的脚本语言来编写验收测试。正如单元测试作为可编译、运行的有关系统内部结构的文档那样,验收测试是有关系统特性的可编译、执行的文档。

编写代码前就编写单元测试会带来四个很明显的好处:

1、首先编写测试使得程序中的每一项功能都有测试来验证它的操作的正确性。这就可以给以后的开发提供支援,使我们可以更自由地对程序进行更改,因为测试可以告诉我们程序仍然具有正确的行为。

2、首先编写测试迫使我们必须从程序调用者的有利视角去观察我们将要编写的程序。这样,我们就会在关注程序的功能的同时,直接关注它的接口,我们也就可以设计出便于调用的软件。

3、首先编写测试迫使我们把程序设计为可测试的。为了把程序设计为易于调用和可测试的,程序必须和它周边环境解耦。这样首先编写测试迫使我们解除软件中的耦合。面向对象设计的原则在进行这种解除耦合方面具有巨大的帮助作用。

4、首先编写测试的另一个重要效果是,测试可以作为一种无价的文档形式。测试就像一套范例,它帮助其他程序员了解如何使用代码。这份文档是可编译、可运行的。它保持最新。它不会撒谎。

首先编写验收测试的行为对于系统的架构方面具有深远的影响。为了使系统具有可测试性,就必须要在很高的系统架构层面对系统进行解耦合。正如单元测试可以促使你在小的方面可以做出优良的设计决策一样,验收测试可以促使你在大的方面做出优良的系统架构决策。

 软件大师、C++之父Bjarne Stroustrup曾经说过:设计和编程都是人的活动。忘记了这一点,将会失去一切。敏捷软件开发方法正是认识到软件开发的这一本质特征而提出的革新性开发方法。使用敏捷开发方法会给我们带来巨大的好处。当然要完全做到也是很困难的。这不仅需要对敏捷的深刻理解,更需要敏捷团队成员的共同努力。

本文参考:http://blog.csdn.net/open2job/article/details/6335000

 

 

posted on 2013-04-17 17:13 王海光 阅读(449) 评论(0)  编辑 收藏 引用 所属分类: 其他

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理