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.子类应该可以替换其基类。
如下图2-14所示。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技术的原则。没有它,组件和类的易用性和重用性都会大打折扣。该原则的实质很简单:如果一个类有几个使用者,与其让 这个类载入所有使用者需要使用的所有方法,还不如为每一个使用者创建一个特定的接口,并让该类分别实现这些接口。
3 包体系结构的原则Principles of Package Architecture
类是必不可少的,但对于组织一个设计来说还不够,粒度更大的包有助于此。但是我们应该怎样协调类和包之间的从属关系?下面的三条原则都属于包聚合原则,能对我们有所帮助。
3.1 包聚合原则
3.1.1 发布重用等价原则The Release Reuse Equivalency Principle (REP)1
重用的粒度就是发布的粒度。The granule of reuse is the granule of release.一个可重用的元件(组件、一个类、一组类等),只有在它们被某种发布(Release)系统管理以后,才能被重用。用户不愿意使用那些每 次改动以后都要被强迫升级的元件。因此,即使开发者发布了可重用元件的新版本,他也必须支持和维护旧版本,这样才有时间让用户熟悉新版本。
因此,将什么类放在一个包中的判断标准之一就是重用,并且因为包是发布的最小单元,它们同样也是重用的最小单元。体系结构师应该将可重用的类都放在包中。
3.1.2 共同封闭原则The Common Closure Principle (CCP)2
一起变化的类放在一起。Classes that change together, belong together.一个大的开发项目通常分割成很多网状互联的包。管理、测试和发布这些包的工作可不是微不足道的工作。在任何一个发布的版本中,如果改动 的包数量越多,重建、测试和部署也就会越多。因此我们应该尽量减少在产品的发布周期中被改动的包的数量,这就要求我们将一起变化的类放在一起(同一个 包)。
3.1.3 共同重用原则The Common Reuse Principle (CRP)3
不一起重用的类不应该放在一起。Classes that aren‘t reused together should not be grouped together.对一个包的依赖就是对包里面所有东西的依赖。当一个包改变时,这个包的所有使用者都必须验证是否还能正常运行,即使它们所用到的没有任 何改变也不行。
比如我们就经常遇到操作系统需要升级。当开发商发布一个新版本以后,我们的升级是迟早的问题,因为开发商将会不支持旧版本,即使我们对新版本没有任何兴趣,我们也得升级。
如果把不一起使用的类放在一起,同样的事情我们也会遇到。一个和我们无关的类的改变也产生包的一个新版本,我们被强迫升级和验证这个包是否影响正常的运行。
3.1.4 包聚合原则之间的张力Tension between the Package Cohesion Principles
这三条原则实际上是互斥的。它们不能被同时满足,因为每一条原则都只针对某一方面,只对某一部分人有好处。REP和CRP都想重用元件的人有好处,CCP 对维护人员有好处。CCP使得包有尽可能大的趋势(毕竟,如果所有的类都属于一个包,那么将只会有一个包变化);CRP尽量使得包更小。
幸运的是,包并不是一成不变的。实际上,在开发过程中,包的转义和增删都是很正常的。在项目开发的早期,软件建筑师建立包的结构体系,此时CCP占主导地 位,维护只是辅助。在体系结构稳定以后,软件建筑师会对包结构进行重构,此时尽可能的运用REP和CRP,从而最大的方便重用元件的人员。
3.2 包耦合原则The Package Coupling Principles.
下面三条原则主要关心包之间的关系。
3.2.1 无依赖回路原则The Acyclic Dependencies Principle (ADP)1
包与包之间的依赖不能形成回路。The dependencies between packages must not form cycles.因为包是发布的粒度。人们倾向于节省人力资源,所以工程师们通常只编写一个包而不是十几个包。这种倾向由于包聚合原则被放大,后来人们就将 相关的类组成一组。
因此,工程师发现他们只会改动较少的几个包,一旦这些改动完成,他们就可以发布他们改动的包。但是在发布前,他们必须进行测试。为了测试,他们必须编译和连编他们的包所依赖的所有的包。
3.2.2 依赖稳定原则(Stable Dependencies Principle,SDP)
朝稳定的方向依赖Depend in the direction of stability.虽然这条原则看起来很明显,但是关于这方面还是有很多需要说明的地方,稳定性并不一定为大家所了解。
稳定性是什么?站在一个硬币上,这稳定吗?很可能你说不。然而,除非被打扰,硬币将保持那个位置很长时间。硬币没有变化,但是很难认为它是稳定的。稳定性 与需要改动所要做的工作量相关。硬币不稳定是因为只需要很小的工作量就能把它翻过来。换个角度,桌子就要稳定得多。
对于软件这说明什么?一个软件包很难被改动受很多因素影响:代码大小、复杂度、透明度等等。这些我们先不说,可以肯定的一点是,如果有很多其它的包依赖于 一个软件包,那么该软件包就难以改动。一个包如果被许多其它包依赖,那么该包是很稳定的,因为这个包的任何一个改动都可能需要改动很多其它的包。
3.2.3 稳定抽象原则( Stable Abstractions Principle ,SAP)
稳定的包应该是抽象包。Stable packages should be abstract packages.我们可以想象应用程序的包结构应该是一个互相联系的包的集合,其中不稳定的包在顶端,稳定的包在底部,所有的依赖方向朝下。那些顶端的 包是不稳定而且灵活的,但那些底部的包就很难改动。这就导致一个两难局面:我们想要将包设计为难以改动的吗?
明显地,难以改动的包越多,我们整个软件设计的灵活性就越差。但是好像有一点希望解决这个问题,位于依赖网络最底部的高稳定性的包的确难以改动,但是如果遵从OCP,这样的包并不难以扩展。
(转载文章请保留出处:北天JAVA技术网(www.java114.com))
分享到:
相关推荐
总之,OO设计原则为软件开发者提供了一套实用的指南,帮助他们构建出更加健壮、灵活和易于维护的系统。通过理解并实践这些原则,开发者可以有效地应对软件开发过程中的常见挑战,提高软件的整体质量和性能。
标题和描述中提到的“23种设计模式,OO思想”,是软件工程领域的一个核心概念,尤其是对于面向对象编程(Object-Oriented Programming,简称OO)的深入理解和实践至关重要。设计模式是由Erich Gamma、Richard Helm、...
面向对象设计原则与设计模式是...总之,面向对象设计原则和设计模式是现代软件开发中不可或缺的组成部分,它们不仅有助于提高软件的复用性和可维护性,还能促进团队间的沟通和协作,是构建高质量软件系统的重要基石。
在软件开发领域,设计模式和设计原则是构建高效、可扩展和可维护系统的核心概念。本文将深入探讨这些概念,并通过“OO Principles Explained译文.pdf”提供的内容,解析它们在实际开发中的应用。 首先,设计模式是...
.pdf JAVA设计模式.chm 软件设计的七大原则.doc 设计之道.pdf C#设计模式分析.doc C#设计模式-微软.rar 从追MM谈Java的23种设计模式.txt 什么是OO思想.txt 探寻软件的永恒之道.txt 你还...
千万不要轻视这些OO原则,因为每个设计模式背后都包含了几个OO原则的概念。很多时候,在设计时有两难的情况,这时候我们必须回归到OO原则,以方便判断取舍。可以这么说:OO原则是我们的目标,而设计模式是我们的做法...
千万不要轻视这些OO原则,因为每个设计模式背后都包含了几个OO原则的概念。很多时候,在设计时有两难的情况,这时候我们必须回归到OO原则,以方便判断取舍。可以这么说:OO原则是我们的目标,而设计模式是我们的做法...
《OO设计五个原则》深入探讨了面向对象设计(Object-Oriented Design,简称OO设计)中的五大核心原则,这些原则是软件工程领域公认的基石,旨在提高软件系统的稳定性、可维护性和可扩展性。本文将详细解析这五大原则...
在探讨设计模式的入门知识之前,我们需要对面向对象(Object-Oriented,OO)和面向过程(Procedure-Oriented)的编程思想有所了解。面向过程的编程是以事件为中心的,注重于具体的操作步骤,如C语言就是面向过程编程...
懂了设计模式,你就懂了面向对象分析和设计(OOA/D)的精要。...这也是我们软件设计所准求的,因此无论是OO中的封装、继承、多态,还是我们的设计模式的原则和实例都是在为了这两个目标努力着、贡献着。
本书荣获2005年第十五届Jolt通用类图书震撼大奖。 本书英文xx版被《程序员》等机构评选为2006年*受...第1章还介绍了四个OO基本概念(抽象、封装、继承、多态),而第1章到第9章也陆续介绍了九个OO原则(Principle)。
虽然许多OO设计模式在FP中也有实现,例如工厂函数(Factory Functions)、适配器模式(Adapter)、装饰器函数(Decorator Functions)、迭代器模式(Iterator Pattern)、策略模式(Strategy)、外观模式(Facade)...
千万不要轻视这些OO原则,因为每个设计模式背后都包含了几个OO原则的概念。很多时候,在设计时有两难的情况,这时候我们必须回归到OO原则,以方便判断取舍。可以这么说:OO原则是我们的目标,而设计模式是我们的做法...
下面我们将从OO的设计基础、面向对象设计模式、设计目标、设计原则五大方面来浅谈Java中OO的概念和设计原则。 一、OO的设计基础 OO是基于对象概念,以对象为中心,以类和继承为构造机制,充分利用接口和多态提供...
GRASP模式,OO原则和设计模式的基础,原创不易,请珍惜下载
在本项目中,"OO设计和伪状态模式实现的控制台五子棋游戏"是一个用C#编程语言实现的控制台应用程序,旨在教授面向对象编程(Object-Oriented Programming, OOP)和设计模式,特别是状态模式的应用。下面将详细阐述...
以上设计模式都是基于面向对象的核心概念来设计的,它们有效地利用了封装、继承和多态,使得代码更加灵活、可扩展和易于维护。在实际项目中,结合面向对象的设计原则(如单一职责原则、开闭原则、里氏替换原则、依赖...
每一章均会引入一至多个设计模式,并结合相关的OO原则进行讲解,帮助读者理解模式背后的逻辑与目的。作者指出,当面临设计抉择时,应回归OO原则,以此作为决策依据,从而达到更好的设计效果。 ### 教学方法与内容...
千万不要轻视这些OO原则,因为每个设计模式背后都包含了几个OO原则的概念。很多时候,在设计时有两难的情况,这时候我们必须回归到OO原则,以方便判断取舍。可以这么说:OO原则是我们的目标,而设计模式是我们的做法...