Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1347032
  • 博文数量: 244
  • 博客积分: 1039
  • 博客等级: 少尉
  • 技术积分: 1562
  • 用 户 组: 普通用户
  • 注册时间: 2011-01-06 09:40
文章分类

全部博文(244)

文章存档

2021年(2)

2019年(6)

2018年(2)

2014年(1)

2013年(187)

2012年(47)

分类: LINUX

2012-07-02 10:24:16

             在上一节中,主要写了类的设计原则。然后在网上找了一些包的设计原则和包之间的耦合性原则的介绍,均比较散,只是一个大概上的介绍,今天在网上搜索到一篇不错的文章,现摘抄如下:
   

             1  晨后综合症和包的发布

你曾有过这样的经历吗?工作了一整天,终于完成了某项功能后回家,不料第二天早晨一来却发现那项功能不再工作了。原因是什么呢?因为有人比你走得更 晚,并且更改了你所依赖的某些东西!这就是所谓的“晨后综合症"。受“晨后综合症”困扰的团队常常几周时间都无法构建出一个稳定的版本,每个人都忙于一遍 遍更改他们的代码,试图使之能够相容与其他人所做的最近更改,从而造成团队士气低落,效率不高,陷入了可怕的集成地狱中。为此有的团队在集成期间禁 止 check in ,这显然不是一个好办法,一方面,如果不用技术手段很难避免有意或无意的 check in ,另一方面开发者为了进行后续开发而又不影响当前集成的版本,可能不得不手工进行版本管理, 再有,它使团队成员间的协作也变得困难。

对包进行发布能有效避免晨后综合症的发生。造成晨后综合症的原因在于依赖者所依赖的包是变化的,这就使依赖者工作于一个不稳定的基础之上,对被依赖 者的改变,依赖者必须作出相容的改变。采用包的发布机制,依赖者必须选择被依赖包发布的一个特定版本,而发布后的包,其内容是不允许变化的,因此依赖者所 依赖的东西就不会改变;同时,被依赖包的任何改变都必须作为一个新版本发布,而依赖者有权决定是否采用这个新版本,换句话说,是否接受被依赖者的改变是由 依赖者决定的,而在此之前,依赖者是不得不被动地接受被依赖者的改变。

 

2  包的设计原则

要对包进行发布,首先要先设计好包,对规模较大的应用来说,划分包的组合很多,仅仅把看起来像是适合在一起的类放进相同的包中,得到的往往是一种不 好的包结构:发布很困难、不容易重用、难于更改等等,这种包结构带来的可能是更多的麻烦。显然我们需要一些原则来指导包的划分,以下列出这些原则,前三个 原则用来指导把类划分到包中,关注包的内聚性,后三个原则用来处理包之间的相互关系,关注包的耦合性。

2.1  REP 重用发布等价原则

重用的粒度就是发布的粒度。

如果一个包中的软件是用来重用的,那么它就不能再包含不是为了重用目的而设计的软件。换句话说,一个包中的软件要么都是可重用的,要么都不是可重用 的。简单地声明一个类是可重用的做法是不现实的,我们所重用的任何东西都必须同时被发布和跟踪。如果一个包同时包含了可重用的类和不可重用的类,那么当不 可重用的类发生变化时,就要进行一次包的发布,而原本不受影响的重用者就需要决定是否采用新版本,以及采用新版本后可能的编译,连接和测试工作。这些内耗 操作是应该避免的。

2.2  CRP 共同重用原则

一个包中的所有类应该是共同重用的。如果重用了包中的一个类,那么就要重用包中的所有类。

在大多数情况下,一个可重用抽象需要多个类来表达,该原则规定这些类应该在一个包中,而属于不同抽象的类不应该在一个包中。乍看起来,这条原则 和 REP 有点相似,但实际上还是不同的,比如,抽象 A 包括类 A1、A2、A3 ,抽象 B 包含类 B1、B2、B3 ,从 REP 原则来 看,这个包没有什么不对,因为该包的软件都是可重用的,但它却违反了 CRP 原则,因为重用者完全可以只重用 A 抽象的类或只重用 B 抽象的类,这 样当任一抽象的改变都会导致该包重新发布,虽然该发布对某一抽象的使用者是无意义的,但是他们仍然需要需要重新验证和重新发布,这会白费相当数量的努力。

2.3  CCP 共同封闭原则

包中的所用类对于同一类性质的变化应该是共同封闭的。一个变化若对一个包产生影响,则将对该包中的所有类产生影响,而对其他的包不造成任何影响。

REP 和 CRP 关注的都是重用性, CCP 关注的是可维护性。对大多数的应用来说,可维护性的重要性是超过可重用性的。一个变化(包括需求 上的,设计上的等等)可能会引起多个类的更改, CCP 要求我们把这些类放在一个包中,同时把那些不受影响的类放到其他的包中,因此一个包只有一个引起 变化的原因,一个变化只对一个包产生影响,这样大大减少了重新发布的次数和重新发布对其他包的影响,从而提高了软件的可维护性。

2.4  ADP 无环依赖原则

在包的依赖关系图中不允许存在环。

如果包的依赖关系图中存在环,就会导致环上的所有软件包必须同时发布,如下图,
由于 P3 使用了 P1 中的一个类而形成了依赖环,若要发布 P1 ,必须先发布 P2 和 P3 ,而发布 P3 又要先发布  P1 和 P2,P1、P2、P3 实际上已经变成了同一个大包,于是工作于这些包上的开发人员不可避免地会遭受晨后综合症。
去掉依赖环的方法有两个:

  1. 使用DIP。如图,把Y的接口和实现分离,

  2. 增加新包。如图,把 P1 和 P3 都依赖的类移到一个新包中

 

2.5  SDP 稳定依赖原则

朝着稳定的方向进行依赖。

如果一个包被很多包所依赖,那么它就是稳定的,因为要使所有依赖于它的包能够相容于对它所做的更改,往往需要非常大的工作量。一个系统中的所有包并 非都应该都是稳定的,因为如果那样的话,系统将很难更改。 SDP 指导我们处理稳定包和不稳定包之间的关系:不稳定的包应该依赖于稳定的包,一个包应该 依赖于比他更稳定的包。你设计了一个不稳定的包,期望它能随变化容易地更改,可当它被一个稳定的包依赖后,它就再也不会易于更改了,这就使软件难于修改和 变化。

2.6  SAP 稳定抽象原则

包的稳定程度应该和其稳定程度一致。

一个系统的高层构架和设计决策应该被放进稳定的包中,因为这些构架决策不应该经常改变,然而稳定包的不易更改的特点会使这些架构决策不灵活,显然只 用稳定性来度量一个包是不够的, SAP 告诉我们:稳定的包也应该是抽象的。它应该包含抽象类,系统通过在其他包中实现该稳定包中的抽象类来进行扩展, 而该稳定包无需修改,从而在保持稳定的同时也不失灵活性。

 

3  包的设计过程

几年前当我还不知道这些包的设计原则时,认为包就是系统的高层的功能分解,应该在项目开始时就设计好,结果遭受了失败。实际上,包的依赖关系图和描 绘系统的功能之间几乎没有关系,它是系统可构建性的映射图。项目开始时,我们还不知道系统中有哪些类,更不必说它们之间的关系,在这种情况下不仅很难创建 出包依赖关系图,即使创建出来也很可能是不合理的。包的依赖关系结构应该是和系统的逻辑设计一起增长和演化的,项目开始时不必考虑包,系统仍以类的粒度组 织,随着开发的进行,类越来越多,对依赖关系进行管理,避免项目开发中出现晨后综合症的需要也不断增长,此时我们应用 CCP 原则对把可能一同变化的类 组织成包进行发布,随着系统的不断增长,我们开始关注创建可重用的元素,于是开始使用 CRP 和 REP 来指导包的组合。最后使用 ADP、SDP、 SAP 对包图进行度量,去掉不好的依赖。

 

4  你真的采用了包的发布机制了吗 如果说某个做产品的团队没有采用包的发布机制,它也许会大叫冤枉:我们明明是进行了发布的呀,你看,这不是我们发布的1.0、1.2版本吗?事实 上,任何一个产品都离不开包的发布,只不过对这样的团队而言,他们系统里真正意义上的包只有一个,那就是整个系统,而该包的发布常常是在经过了晨后综合症 的洗礼之后,是在开发基本完毕后进行的,实际上,我们更应该在产品的开发过程中使用这一机制,这样,产品的开发过程才会以合理,有序的方式进行,产品才能 尽快地交付。
阅读(1029) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~