1.1 设计正在“腐烂”的征兆(Symptoms of Rotting Design)

  有四个主要的征兆告诉我们该软件设计正在“腐烂”中。它们并不是互相独立的,而是互相关联,它们是过于僵硬、过于脆弱、不可重用性和粘滞性过高。

  1. 过于僵硬Rigidity Rigidity 致使软件难以更改,每一个改动都会造成一连串的互相依靠的模块的改动,项目经理不敢改动,因为他永远也不知道一个改动何时才能完成。

  2. 过于脆弱Fragility Fragility 致使当软件改动时,系统会在许多地方出错。并且错误经常会发生在概念上与改动的地方没有联系的模块中。这样的软件无法维护,每一次维护都使软件变得更加难以维护。(恶性循环)

  3. 不可重用性immobility immobility 致使我们不能重用在其它项目中、或本项目中其它位置中的软件。工程师发现将他想重用的部分分离出来的工作量和风险太大,足以抵消他重用的积极性,因此软件用重写代替了重用。

  4. 粘滞性过高viscosity viscosity有两种形式:设计的viscosity和环境的viscosity.当需要进行改动时,工程师通常发现有不止一个方法可以达到目的。但 是这些方法中,一些会保留原有的设计不变,而另外一些则不会(也是说,这些人是hacks)。一个设计如果使工程师作错比作对容易得多,那么这个设计的 viscosity 会很高。

  环境的viscosity高是指开发环境速度很慢且效率很低。

  2 面向对象的类设计原则

  2.1 开放关闭原则The Open Closed Principle (OCP)

  A module should be open for extension but closed for modification.一个模块应该只在扩展的时候被打开(暴露模块内部),在修改的时候是关闭的(模块是黑盒子)。

  在所有的面向对象设计原则中,这一条重要。该原则是说:我们应该能够不用修改模块的源代码,能更改模块的行为。

  2.1.1 动态多态性(Dynamic Polymorphism)

  2.1.2 静态多态性(Static Polymorphism)

  另外一种使用OCP的技术是使用模板或范型,如Listing 2-3.LogOn函数不用修改代码可以扩展出多种类型的modem. 2.1.3 OCP的体系结构目标(Architectural Goals of the OCP)

  通过遵照OCP应用这些技术,我们能创建不用更改内部代码可以被扩展的模块。这是说,在将来我们给模块增添新功能是,只要增加新的代码,而不用更改原 先的代码。 第 3 页,共 17 页使软件完全符合OCP可能是很难的,但即使只是部分符合OCP,整个软件的结构性能也会有很大的提高。我们应该记住,让变化不要波及已经正常工作的代码 总是好的。

  2.2 Liskov 替换原则The Liskov Substitution Principle(LSP)

  Subclasses should be substitutable for their base classes.子类应该可以替换其基类。

  Derived类应该能替换其Base类。也是说,Base基类的一个用户User如果被传递给一个Devrived类而不是Base类作为参数,也能正常的工作。

  2.3 依赖性倒置原则The Dependency Inversion Principle (DIP)1

  Depend upon Abstractions. Do not depend upon concretions.依赖抽象,不要依赖具体。

  如果说OCP声明了OO体系结构的目的,DIP则阐述了其主要机制。依赖性倒置的策略是要依赖接口、或抽象函数、或抽象类,而不是依赖于具体的函数和类。这条原则是支持组件设计、COM、CORBA、EJB等等的背后力量。

  2.3.1 依赖抽象Depending upon Abstractions.

  实现该原则十分简单。设计中的每一个依赖都应该是接口、抽象类,不要依赖任何一个具体类。

  显然这样的限制比较严峻,但是我们应该尽可能的遵守这条原则。原因很简单,具体的模块变化太多,抽象的则变化少得多。而且,抽象是“铰链”点,在这些位置,设计可以弯曲或者扩展,而不用进行更改(OCP)。

  2.4 接口隔离原则The Interface Segregation Principle (ISP)

  Many client specific interfaces are better than one general purpose interface多个和客户相关的接口要好于一个通用接口。

  ISP是另一条在底层支持组件如COM技术的原则。没有它,组件和类的易用性和重用性都会大打折扣。该原则的实质很简单:如果一个类有几个使用者,与其让 这个类载入所有使用者需要使用的所有方法,还不如为每一个使用者创建一个特定的接口,并让该类分别实现这些接口。