内聚和耦合(学习笔记与思考)

在《软件工程-实践者的研究方法》的10.2.3和10.2.4两节分别介绍了一些常见的模块内聚和耦合的情况。

内聚

内聚性主要体现在模块功能的专一性上,这意味着一个模块只能封装那些相互关联密切,以及与模块实现功能密切相关的属性和操作。

书中主要提到了以下几种内聚性

1.功能内聚

设计良好的模块只完成一个特定的功能,模块中的元素紧密配合来完成这个功能。

2.分层内聚

将各模块按访问的层次结构组织,高层可以访问低层,当低层不能访问高层。(个人理解,web应用里面的action->service->dao这三层的划分方式可能体现了分层内聚的思想,明显的特征就是action可以访问service层提供的方法,但service层不会知道action层的任何信息)

3.通信内聚

访问相同数据的所有操作都被定义到一个类中。(明显的例子就是DAO类)

耦合性

1.内容耦合

内容耦合可能发生在某个类的public域上,简单的解决方法就是将public域设为private的,然后提供getter/setter和在类外部对域进行修改的方法。

2.共有耦合/外部耦合

我将这两种情况合并都一起讨论了,个人感觉两个很相似。当大量的模块需要使用相同的一些数据时(如一个全局变量,或者一些文件,数据库),如果这个数据发生改变,这意味着所有依赖于它的模块可能也要进行相应的修改。我认为解决的方法可能是不直接使用(访问)这些数据,而是通过一个抽象好的模块(如DAO)来将使用数据的模块和数据访问接口耦合,从而解除各模块和特定数据之间的耦合。比如说你开始使用sqlserver数据库,如果你程序的其它部分不是通过一个抽象,统一的DAO接口来访问数据库,当底层数据库发生变更(比如sqlserver定制性不强,决定使用开源的mysql替换)时,所有使用数据的模块都要进行相应的修改。相反的,如果你使用数据的模块都是通过DAO接口来获取数据时,你需要做的只是提供一个特定于mysql的DAO实现,而使用数据的所有模块不需要任何的变跟。

3.控制耦合

控制耦合发生的在类A调用类B的方法,但B的方法执行的逻辑流程还依赖于A传递的额外控制信息。解决的方法可以是,使用B类的内部状态来替代外部传递进来的控制信息,如使用多态来将if-else变成两个不同的实现类,这样A根据不同的情况持有不同的B的实现类,并调用具体的方法。

4.标记耦合

类B作为类A方法的参数时就发生了这种耦合,最好的方法自然是使用模板。

1 class Printer(){
2   public void print(Integer a){
3     System.out.println(a)
4    }
5 }    

上面是一打印Integer的方法,如果现在需要支持string类型,上面的程序就显得无能为力,这就是Integer类跟Printer类产生了标记耦合。我们可以使用模板来解决这个问题。

1  class Printer<T>{
2    public void print(T a){
3      System.out.println(a)
4    }
5  }    

5.例程调用耦合

一个操作调用另一个操作,这样的耦合有时候是必须的。

6.类型使用耦合

类A使用类B定义的数据类型,可以将公用的数据类型单独拿出来形成一个模块。

7.包含导入耦合

有时候也是必须的,合理设计包结构可以最小化耦合的程度。

8.数据耦合

操作传递的参数过多,可以考虑使用DTO来规范传递的数据,减少不必要的数据传输。

以上就是我对内聚和耦合的学习笔记。

参考:

书籍:《软件工程-实践者的研究方法》

他人博客:http://blog.csdn.net/blizmax6/article/details/6756261

时间: 2024-10-15 17:25:41

内聚和耦合(学习笔记与思考)的相关文章

C++ Primer学习笔记与思考_1----变量和基本类型

C++ Primer学习笔记与思考_1----变量和基本类型 类型有什么作用? 类型告诉我们数据代表什么意思以及可以对数据执行哪些操作. 一:基本内置类型 C++标准规定了每个算术类型的最小存储空间,但是它并不阻止编译器使用更大的存储空间.对于int,几乎所有的编译器使用的存储空间都比所要求的大. 字符类型有两种char和wchar_t,其中wchar_t用于扩展字符集,比如汉字和日文,这些字符集中的一些字符不能用单个的char表示.  c++ primer第32页      和其他类型不同,c

C++ Primer 学习笔记与思考_7 void和void*指针的使用方法

(一)void的含义 void的字面意思是"无类型",void差点儿仅仅有"凝视"和限制程序的作用,由于从来没有人会定义一个void变量,让我们试着来定义: void a; 这行语句编译时会出错.提示"illegal use of type 'void'".只是.即使void a的编译不会出错.它也没有不论什么实际意义. void真正发挥的作用在于: (1) 对函数返回的限定: (2) 对函数參数的限定. int f(void); equal t

C++ Primer 学习笔记与思考_9 表达式中过的那些容易忽略的地方

(一)移位操作符用于IO 输入输出标准库分别重载了位操作符>>和<<用于输入和输出.并且像其他的二元操作符一样,移位操作符也是左结合的,这也正好说明了我们为什么可以把多个输入输出操作连接为单个语句: cout<<"hi"<<"there "<<endl; 将其执行为: ( (cout<<"hi")<<"there" )<<endl;

c++学习笔记和思考

1.内置类型:int float等编程语言自己定义的类型 类类型:自己声明的类,即是对对象的抽象 2.const double *cp 表示cp是指向一个const类型double类型数据的指针,而非是const指针 3.typedef string *pstring; const pstring cstr; //该声明是把cstr定义为指向string类型对象的const指针,其中const 修饰的是pstring .等价于 string *const cstr; const指针可以放在类型前

C++ Primer 学习笔记与思考_4 ---getline&amp;&amp;size_type&amp;&amp;const_iterator混搭

(一)getline的用法 我们在使用string读入字符串的时候,其输入操作符: * 读取并忽略开头所有空白字符(如空格,换行符,制表符) * 读取字符直至再次遇到空白字符,读取终止. 所以如果我们输入"hello world",string将只输出hello. 为了解决这个问题,我们引入getline函数,它接受两个参数:一个输入流对象和一个string对象,但是getline会读取换行符,保存到string中时却忽略换行符,所以string中是空串. 我们通常用getchar()

C++ Primer 学习笔记与思考_3 ---头文件那些事儿(extern)

(一)extern在头文件里的使用方法 由于头文件包括在多个源文件里.而且变量的定义仅仅能出现一次,所以在头文件里. 仅仅能够声明不能够出现定义. 我们能够在头文件里用extern声明全局变量,这样在包括此头文件的cpp 中可直接使用 声明过的这个全局变量(例如以下面程序中的变量a). 可是有三个例外: 1.头文件里能够定义类 2.值在编译时就已经知道的const对象 3.能够定义inline函数 extern int ival; // yes extern int ival=1; //erro

C++ Primer 学习笔记与思考_5 bitset你用的正确吗?

bitset类型比整型值上的低级位操作更容易使用,简化了位集的处理.在定义bitset时,要明确bitset含有的位数,在尖括号内给出它的长度值. 注意位集合的编号从0开始,低位存低阶位. 最重要的一个问题:bitset的下标是从右边开始的!!!!很多人的博客都写错了,希望引起大家注意. 1.使用unsigned long值初始化bitset对象 若bitset类型长度大于unsigned long值的二进制位数,则其余的高阶位将置为0:若bitset类型长度小于unsigned long值的二

C++ Primer 学习笔记与思考_10 类型转换易错处大总结

(一)隐式转换 先来看一组样例: int ival=0; ival=3.451+3; 首先做加法操作,操作数分别为int和double类型,c++并没有直接把两个数加在一起,而是提供了一组转换规则,以便在执行算术操作之前,将两个操作数转换为同一种数据类型.在这里是自动执行的,所以他们被成为隐式转换. 因为 C++定义了算术类型之间的内置转换以尽可能防止精度损失,所以这里3转换为double型相加得6.451.但是下一步赋值的时候,右操作数进行截断处理,对此精度会有损失,编译器也会给出警告. 2.

C++ Primer 学习笔记与思考_7 void和void*指针的用法

(一)void的含义 void的字面意思是"无类型",void几乎只有"注释"和限制程序的作用,因为从来没有人会定义一个void变量,让我们试着来定义: void a; 这行语句编译时会出错,提示"illegal use of type 'void'".不过,即使void a的编译不会出错,它也没有任何实际意义. void真正发挥的作用在于: (1) 对函数返回的限定: (2) 对函数参数的限定. int f(void); equal to in