《敏捷软件开发》读书比较(二)

1、拙劣设计的症状:

  • 僵化性:设计难以改变。
  • 脆弱性:设计易于遭到破坏。
  • 牢固性:设计难以重用。
  • 粘滞性:难以做正确的事情(使用错误的方式应付变化却更容易)。
  • 不必要的复杂性:过分设计。
  • 不必要的重复:滥用鼠标(复制-粘贴反模式)。
  • 晦涩性:混乱的表达(可读性差)。
这些症状在本质上和代码的臭味相似,但是它们所处的层位稍高一些。
2、面向对象设计的SOLID原则。
3、臭味和原则。
      设计中的臭味是一种症状,是可以主观进行度量的(但很难客观进行度量)。这些臭味常常是由于违反了这些原则中的一个或者多个而导致的。敏捷团队应用这些原则去除臭味。当没有臭味时,他们不会应用这些原则。 仅仅因为是一个原则就无条件的去遵循它的做法是错误的。这些原则不是可以随意在系统中到处喷洒的香水。过分遵循这些原则会导致不必要的复杂性的设计臭味。
4、软件项目的设计是一个抽象的概念。 UML图,设计文档都只是描述设计的一些部分。最终的设计体现为源代码。
5、在大多数软件项目中最不稳定的东西就是需求。需求处在一个持续变动的状态之中。这是我们作为开发人员必须得接受的事实!
6、敏捷开发人员面对需求变更时,应该抓住变更的机会去改进设计,并 使修改后的设计对于同一类需求问题的变化具有弹性,而不是设法去给设计打补丁。
      注意:这时的“打补丁”做法也许能使一时的修改快速完成,但是它不是简单设计。它不符合开闭原则。打上补丁后的设计已经出现了某种设计臭味。
7、敏捷开发人员如何知道要做什么?
  • 他们遵循敏捷实践去发现问题;
  • 他们应用设计原则去诊断问题;并且
  • 他们应用适当的设计模式去解决问题。
      软件开发的这三个方面间的作用就是设计。
8、敏捷设计是一个过程,不是一个事件。它是一个持续的应用原则、模式以及实践来改进软件的结构和可读性的过程。
9、单一职责原则(SRP):高内聚性(cohesion)。
10、开放-封闭原则(OCP):如果遵循OCP原则,那么一旦对一个变化做出改进设计以后, 再对同样的变化改动时,就只需要添加新的代码,而不必改动已经正常运行的代码。对扩展开放也就是说增加新功能只需要编写新代码;对修改封闭也就是说增加新功能不需要修改原有代码。
11、实现OCP原则的关键是抽象。策略模式/模板方法模式/状态模式
12、当然,一般而言,无论模块是多么的“封闭”, 都会存在一些无法对之封闭的变化。 没有对于所有的情况都是贴切的模型。既然不可能完全封闭,那么就必须有策略地对待这个问题。
       因此,设计人员必须对于他设计的模块应该对哪种变化封闭做出选择。他必须猜测出最有可能发生变化的种类,然后构造抽象来隔离哪些变化。这需要设计人员具备一些从经验中获得的预测能力。
       但是,这一点不容易做到。如果开发人员猜测正确,他们就获得成功;如果他们猜测错误,他们就会遭受失败。并且 在大多数情况下,他们都会猜测错误
       那么,我们如何知道哪一个变化有可能发生呢?我们进行适当的调查,提出正确的问题,并且使用我们的经验和一般常识。最终,我们会一直等到变化发生时才采取行动。变化一旦来临,我们抓住机会改进设计,并使得修改后的设计对同类变化保持弹性,符合OCP。
13、接口属于客户。ClientInterface(而不是ServerInterface)说明抽象类和它们的客户的关系要比和实现它们的子类的关系更密切一些。
14、封装变化,哪里变化就封装哪里。我们一开始不需要也没有必要去猜测变化。但是,变化一旦出现,我们必须抓住机会改进设计,使修改后的设计能够对同一类变化封闭。因此,抽象是关键,抽象是最稳定的东西。
15、开放-封闭原则(OCP)是面向对象设计的核心所在。遵循这个原则可以带来面向对象技术所声称的巨大好处(也就是,灵活性、可重用性和可维护性)。OCP背后的主要机制是抽象(abstraction)和多态(polymorphism)。而支持抽象和多态的关键机制之一是继承(inheritance)。在使用继承时有一个重要的原则需要注意,那就是里氏替换原则(LSP)。
16、Liskov替换原则(LSP):若对每个类型S的对象O1,都存在一个类型T的对象O2, 使得在所有针对T编写的程序P中,用O1替换O2后,程序P的行为功能不变,则S是T的子类型。
17、对于里氏替换原则的违反也常常会导致对开闭原则的违反,从而使代码中出现使用运行时类型辨别(RTTI)。这种方式难免使得客户端代码出现switch或if/else语句。
18、如果一个新派生类型的创建会导致我们去修改它的基类,这就常常意味着设计是有缺陷的(当然也违反了OCP)。
19、有效性并非本质属性。
       由里氏替换原则可以得出一个重要的结论:一个模型,如果孤立的看,并不具有真正意义上的有效性。 模型的有效性只能通过它的客户程序来表现
20、IS-A关系是针对行为的。LSP清楚的指出,OOD中IS-A关系是就行为方式而言的,行为方式是可以进行合理假设的,是客户程序所依赖的。
21、基于契约设计(Design By Contact):在重新声明派生类的例程时,只能使用相等的或更弱的前置条件来替换原始的前置条件;只能使用相等或者更强的后置条件来替换原始的后置条件。
22、在大多数情况下,接受一个多态中的微秒错误都不会比试着修改设计使之完全符合LSP更为有利。 接受缺陷而不是去追求完美这是一个工程上的权衡问题。好的工程师知道何时接受缺陷比追求完美更为有利。不过,不应该轻易放弃对于LSP原则的遵循。
23、用提取公共部分的方法代替(直接的)继承。例如,类Line和类LineSegment, 线和线段具有许多的相同属性,但是它们在行为上不是严格的IS-A关系。LineSegment继承自Line会带来问题,例如线一定有截距;但线段可能没有截距。更好的做法是通过提取一个LinearObject对象作为Line和LineSegment的抽象基类,可以很好的塑造上合理的模型。——这是一个OOD的重要工具。
24、违反里氏替换原则的典型迹象:
  • 完成的功能少于其基类的派生类
  • 派生类中出现了退化的函数
  • 派生类的方法中添加了其基类中不会抛出的异常
在派生类中存在退化函数并不总是表示违反了LSP,但是当存在这种情况时,还是值得注意一下的。
25、OCP是OOD中很多说法的核心。而LSP使OCP成为可能。
26、依赖倒置原则(DIP): 高层模块不应该依赖于低层模块,二者都应该依赖于抽象;抽象不应该依赖于细节,细节应该依赖于抽象。
这样做的目的是:低层模块的改动不至于影响高层模块;细节的改动不会影响到抽象。只有抽象接口层的改动才会促使高层模块和细节做出相应的改动,然而,抽象通常都是比较稳定的。因此,这是一种合理的设计。依赖倒置原则(DIP)是框架(framework)设计的核心原则。
27、倒置的接口所有权。(不要调用我们,我们会调用你)
        依赖倒置原则中的“倒置”不仅仅是依赖关系的倒置,它也是接口所有权的倒置。在应用依赖倒置原则(DIP)时,我们发现往往是客户拥有抽象接口,而它们的服务者则从这些抽象接口中派生。
28、依赖于抽象。有个启发式规则:
  • 任何变量都不应该持有一个指向具体类的指针和引用
  • 任何类都不应该从具体类派生
  • 任何方法都不应该覆写它的任何基类中的已经实现了的方法
当然,任何程序都有违反该规则的情况。但是这些规则值得我们注意。
29、接口隔离原则(ISP)用来处理“胖”接口所具有的缺点。那么什么是“胖”接口?如果类的接口不是内聚的,就说明这个类的接口是‘胖“的。我们通常说,要使接口尽量的”窄“,就是这样道理。
30、胖类会导致它们的客户程序之间产生不正常的并且有害的耦合关系。当一个客户程序要求该胖类进行一个改动时,会影响到所有其它的客户程序。因此,客户程序应该仅仅依赖于它们实践调用的方法。适配器模型可以帮助我们很好的分离接口,解决胖类接口的困扰,防止接口污染。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值