连载:面向对象葵花宝典:思想、技巧与实践(28) - 设计原则:内聚&耦合

前面通过实例讲解了一个一环扣一环的面向对象的开发流程:用例模型 -> 领域模型 -> 设计模型(类模型 + 动态模型),解答了面向对象如何做的问题。接下来我们就要讲“如何做好面向对象设计”的技巧了

===================================================================

【内聚】

参考维基百科的解释,内聚的含义如下:


cohesion refers to the degree to which the elements of a module belong together.

(http://en.wikipedia.org/wiki/Cohesion_(computer_science))

翻译一下即:内聚指一个模块内部元素彼此结合的紧密程度

 

看起来很好理解,但深入思考一下,其实没有那么简单。

首先:“模块”如何理解?

你一定会说,“模块”当然就是我们所说的系统里的“XX模块”了,例如一个ERP系统的“权限”模块,一个电子商务的“支付”模块,一个论坛网站的“用户管理”模块。。。。。。等等

 

你说的没错,但在面向对象领域,谈到“内聚”的时候,模块的概念远远不止我们通常所理解的“系统内的某个模块”这个范围,而是可大可小,大到一个子系统,小到一个函数,你都可以理解为内聚里所说的“模块”。

 

所以,你可以用“内聚”来判断一个函数设计是否合理,一个类设计是否合理,一个接口设计是否合理,一个包设计是否合理,一个模块/子系统设计是否合理。

 

其次:“元素”究竟是什么?

有了前面对“模块”的深入研究后,元素的含义就比较容易明确了(不同语言稍有不同)。

函数:函数的元素就是“代码”

类/接口:类的元素是“函数、属性”

包:包的元素是“类、接口、全局数据”等

模块:模块的元素是“包、命名空间”等

 

再次:“结合”是什么?

英文的原文是“belong”,有“属于”的意思,翻译成中文“结合”,更加贴近中文的理解。但“结合”本身这个词容易引起误解。绝大部分人看到“结合”这个单词,想到的肯定是“你中有我、我中有你”这样的含义,甚至可能会联想到“美女和帅哥”的结合,抑或“青蛙王子和公主”的结合这种情况。

这样的理解本身也并没有错,但比较狭隘。

我们以类的设计为例:假如一个类里面的函数都是只依赖本类其它函数(当然不能循环调用啦),那内聚性肯定是最好的,因为“结合”得很紧密。

 

但如果这个类的函数并不依赖本类的函数呢?我们就一定能说这个类的内聚性不好么?

其实也不尽然,最常见的就是CRUD操作类,这几个函数相互之间没有任何结合关系(某些设计可能会先查询再修改,但这样的设计不是事务安全的),但其实这几个函数的内聚性非常高。

 

所以,关于内聚的结合概念,我认为不是非常恰当的描述。那么,就究竟什么才是真正的“内聚”呢?

答案就藏在显而易见的地方,翻开你的词典,仔细看看cohesion的含义,你会看到另外一个解释:凝聚力!

 

“凝聚力”就是“内聚”的核心思想,抛开面向对象不谈,我们日常工作中几乎随处可见“凝聚力”:

你可能会说,你的团队很有凝聚力。。。。。。

领导可能会说:我们要增强团队的凝聚力。。。。。。

成功学大师会说:凝聚力是一个团队成功的基石。。。。。。。

 

面向对象领域的“凝聚力”,和团队的“凝聚力”是一样的概念。

l 判断团队凝聚力时,我们关注团队成员是否都专注于团队的目标;判断面向对象模块的凝聚力时,我们同样关注元素是否专注于模块的目标,即:模块本身的职责!

l 判断团队凝聚力时,我们还会关注团队成员之间是否互相吸引和帮助;判断面向对象模块凝聚力时,我们同样关注元素间的结合关系;

 

虽然判断内聚性的时候我们会考虑元素的结合情况,但其实是否专注模块的职责,才是内聚性的充要条件

当模块的元素全部都专注于模块的职责的时候,即使元素间的结合不是很紧密,也是符合内聚性的要求的,这也是CRUD设计符合内聚性的原因。

 

所以,判断一个模块(函数、类、包、子系统)“内聚性”的高低,最重要的是关注模块的元素是否都忠于模块的职责,简单来说就是“不要挂羊头卖狗肉”。

【耦合】

参考维基百科,耦合的定义如下:


 coupling or dependency is the degree to which each program module relies on each one of the other modules

(http://en.wikipedia.org/wiki/Coupling_(computer_science))

简单翻译一下:耦合(或者称依赖)是程序模块相互之间的依赖程度。

 

从定义来看,耦合和内聚是相反的:内聚关注模块内部的元素结合程度,耦合关注模块之间的依赖程度。

 

理解耦合的关键有两点:什么是模块,什么是依赖。

 

什么是模块?

模块和内聚里面提到的模块一样,耦合中的模块其实也是可大可小。常见的模块有:函数、类、包、子模块、子系统等

 

什么是依赖?

依赖这个词很好理解,通俗的讲就是某个模块用到了另外一个模块的一些元素。

例如:A类使用了B类作为参数,A类的函数中使用了B类来完成某些功能。。。。。。等等

================================================ 
转载请注明出处:http://blog.csdn.net/yunhua_lee/article/details/24481189
================================================ 

时间: 2024-09-15 14:07:43

连载:面向对象葵花宝典:思想、技巧与实践(28) - 设计原则:内聚&耦合的相关文章

连载:面向对象葵花宝典:思想、技巧与实践(26) - 类模型三板斧

类模型设计其实就是程咬金打天下 -- 三板斧 而已 :) 第一斧(照猫画虎):领域类映射 面向对象类设计首先要解决的一个问题是:类从哪里来 ? 有的人可能会认为,要发挥想象力.创造力.....等各种"力"--这种方法的主要问题是:我们不是在进行纯粹的艺术创造,而是要最终满足客户需求,而不能天马行空. 有的人可能会想到,参考其它的系统吧,把类似系统拿过来改吧改吧 --这种方法的主要问题是:如果没有其它类似系统给你参考呢 ?还有的人干脆就说:拍脑袋吧,凭感觉吧 -- 这种方法的主要问题是:

连载:面向对象葵花宝典:思想、技巧与实践(1) - 程序设计思想的发展

史前时代:面向机器 最早的程序设计都是采用机器语言来编写的,直接使用二进制码来表示机器能够识别和执行的指令和数据.简单来说,就是直接编写0和1的序列来代表程序语言.例如:使用0000 代表 加载(LOAD),0001 代表 存储(STORE)等.  机器语言由机器直接执行,速度快,但一个很明显的缺点就是:写起来实在是太困难了,一旦你发现自己写错了,改起来更蛋疼!这样直接导致程序编写效率十分低下,编写程序花费的时间往往是实际运行时间的几十倍或几百倍.  有一个关于机器语言和比尔盖茨的笑话,是说比尔

连载:面向对象葵花宝典:思想、技巧与实践(34) - DIP原则

DIP,dependency inversion principle,中文翻译为"依赖倒置原则".   DIP是大名鼎鼎的Martin大师提出来的,他在1996 5月的C++ Reporter发表" The Dependency Inversion Principle"的文章详细阐述了DIP原则,并且在他的经典著作< Agile Software Development, Principles, Patterns>(中文翻译为:敏捷软件开发:原则.模式与

连载:面向对象葵花宝典:思想、技巧与实践(31) - OCP原则

开闭原则是一个大部分人都知道,但大部分人都不懂的设计原则! ==================================================================== OCP,Open-Closed Principle,中文翻译为"开闭原则".   当我第一次看到OCP原则时,我的感觉就是这原则也太抽象了吧,什么开,什么闭呢?   然后我去寻找更加详细的答案,最经典也是最常见的解释就是维基百科了: http://en.wikipedia.org/wiki/

连载:面向对象葵花宝典:思想、技巧与实践(35) - NOP原则

NOP,No Overdesign Priciple,不要过度设计原则.   这应该是你第一次看到这个原则,而且你也不用上网查了,因为这个不是大师们创造的,而是我创造的:)   之所以提出这个原则,是我自己吃过苦头,也在工作中见很多人吃过类似的苦头.   你可能也见过这样的场景: 产品提出了一个需求,设计师眼光非常长远,他甚至把5年后可能的业务变化都提出来并且加以设计了,让你不得不佩服设计师的高瞻远瞩的眼光,并且由衷的从心底赞叹:牛逼啊!   但很快你就会发现,设计师是很牛逼,但你开发的时候就很

连载:面向对象葵花宝典:思想、技巧与实践(30) - SRP原则

前面详细阐述了"高内聚低耦合"的总体设计原则,但如何让设计满足这个原则,并不是一件简单的事情,幸好各位前辈和大牛已经帮我们归纳总结出来了,这就是"设计原则"和"设计模式".毫不夸张的说,只要你吃透这些原则和模式并熟练应用,就能够做出很好的设计. ================================================================== [SRP原则详解] SRP,single responsibility

连载:面向对象葵花宝典:思想、技巧与实践(27) - 动态模型设计

类模型指导我们如何声明类,动态模型指导我们如何实现类! 动态模型设计一般都是在类模型设计完成后才开始,因为动态模型设计的时候一般都需要用到类模型中的类.相对类模型来说,动态模型要相对简单一些,主要原因在于动态模型设计的时候没有什么设计原则和设计模式需要应用,只需要对照用例模型,根据用例模型的特点,选取一个合适的动态模型将其表述出来即可. 动态模型在实际开发过程中有非常重要的作用,简单来说,如果没有动态模型,那么你虽然完成了类设计,但还是不能编码,或者只能编写类的声明代码(类属性.方法名称),但不

连载:面向对象葵花宝典:思想、技巧与实践(7) - “对象”新解

有了"类"的清晰定义后,"对象"就比较容易理解了. 对象就是一个具体的类,一个真实存在的类. 前面我们提到面向对象是对现实世界的模拟,那么对象就是现实世界中存在的"物体".   例如,"人"是一个类,我就是一个"人"的对象,你也是"人"的对象,奥巴马也是"人"的对象...... 又比如:你去国美买冰箱,但国美肯定没有一个单独叫做"冰箱"的东西卖给你

连载:面向对象葵花宝典:思想、技巧与实践(32) - LSP原则

LSP是唯一一个以人名命名的设计原则,而且作者还是一个"女博士"  ============================================================= LSP,Liskov substitution principle,中文翻译为"里氏替换原则".   这是面向对象原则中唯一一个以人名命名的原则,虽然Liskov在中国的知名度没有UNIX的几位巨匠(Kenneth Thompson.Dennis Ritchie).GOF四人帮

连载:面向对象葵花宝典:思想、技巧与实践(29) - 高内聚低耦合

高内聚低耦合,可以说是每个程序猿,甚至是编过程序,或者仅仅只是在大学里面学过计算机,都知道的一个简单的设计原则. 虽然如此流行和人所众知,但其实真正理解的人并不多,很多时候都是人云亦云. =============================================================== 要想真正理解"高内聚低耦合",需要回答两个问题: 1)为什么要高内聚低耦合? 2)高内聚低耦合是否意味内聚越高越好,耦合越低越好?   第一个问题:为什么要高内聚低耦合? 经