耦合(六种)与 内聚(七种)—《软件工程与计算》笔记
创始人
2024-04-07 10:13:39
0

耦合(六种)与 内聚(七种)

1. 耦合(六种)

耦合描述的是 两个模块 之间关系的复杂程度。耦合性越低越好,耦合度越高,模块划分越差,越不利于软件变更和复用。根据耦合性的高低依次分为以下六种耦合:

名称概述判断依据修改意见
内容耦合一个模块直接修改或者依赖于另一个模块的内容含有 goto/alter 语句
模块A 修改了 模块B 传来的数据
修改属性没有通过 get/set 方法
访问集合变量没有使用迭代器
去掉不该有的语句/加上缺少的变量或方法,更改代码保持语义不变。
公共耦合模块之间共享全局的数据。共享的是变量两个或多个模块共享全局变量将需要的全局共享变量变成方法参数传入
重复耦合模块之间有同样逻辑的重复代码一段业务逻辑在两个地方被调用却没有写在一个方法内,即明显两个地方的代码有极高的重复。创建一个方法,把重复出现的业务逻辑写进方法,通过调用方法传入不同的属性值实现和原来一样的业务逻辑
控制耦合一个模块给另一个模块传递控制信息。共享的是逻辑。传递的信息既有数据,还有逻辑(如果只传递数据则为数据耦合),两个模块都需要知道所传递的信息的逻辑含有 swith-caseif-else-if-elsecommandtypeflag 语句的,比较容易是控制耦合。
印记耦合共享一个数据类型,但是却只用了其中一部分。共享的是数据结构所传及所需。
数据耦合两个模块的所有参数是同类型的数据项。共享的是数据。所有数据全被用到
使用所传引用对象的方法
一个模块给另一个模块传入的参数得到输出
  • 内容、重复、公共耦合是不能接受的
  • 控制、印记耦合是可以接受的
  • 数据耦合是最好的

2. 内聚(七种)

内聚表达的是 一个模块 内部的联系的紧密性。内聚性越高越好,越低越不易实现变更和复用。内聚性由低到高依次分为以下七种内聚:

名称概述判断依据修改意见
偶然内聚模块执行多个完全不相关的操作将不相关的操作单独封装
逻辑内聚模块执行一系列相关操作,每个操作的调用由其他模块来决定这些操作逻辑上相似但没有直接关联,表现为 并立的 分支选择语句,即 swith-caseif-else-if-else (多个条件选择语句中最多只会有一个分支执行)将并立的操作单独封装
时间内聚模块执行一系列与时间有关的操作(相同的时间)
这些操作在同一时间段内发生
init() 初始化操作
c++ 构造函数、析构函数
将每个初始化模块单独封装
过程内聚模块执行一些与步骤顺序有关的操作这些操作是解决同一个问题的不同步骤,表现为这些操作的顺序不能颠倒
通信内聚模块执行一系列与步骤有关的操作,并且这些操作在相同的数据上进行。(相同的数据)注意是同一数据,有两种类型
- 方法间通信内聚(在多个方法中共享对象,这里,共享不当容易形成公共耦合)
- 方法内通信内聚(在方法中多次调用形参的不同属性)
功能内聚模块只执行一个操作或达到一个单一目的。(完全以功能(行为)为依据进行模块划分,通常是函数与过程)单一的目的 即指一个类内的各属性是否体现一个职责
或者各属性之间可否抽象
信息内聚模块进行许多操作,各个都有各自的入口点,每个操作的代码相对独立,而且所有操作都在相同的数据结构上完成。(以数据与功能间的相互支撑为依据进行模块分解)接口或抽象类通常是信息内聚的。
  • 偶然内聚、逻辑内聚是不能接受的
  • 时间、过程、通信内聚是可以接受不可避免的(一般控制器模块会是这三种内聚)
  • 功能内聚、信息内聚是最好的(执行具体功能的模块一般是这两种内聚中的一种或两种)

3. 例子

3.1 例1

3.1.1 问题

下面的 gcd 方法内部的代码是哪种类型的内聚?

int gcd(int p, int q) {int r;while(p != 0) {int r = p;p = q % p;q = r;}
}

3.1.2 解析

按照最大公约数的计算方式,完成 pq 的转换,模块达到了一个单一的目的,是功能内聚。

功能内聚强调目标与需求相对应

3.2 例2

3.2.1 问题

下面的 validate_checkout_request 方法的内部代码是哪种类型的内聚?

void validate_checkout_request(input_form i) {if(!(i.name.size()>4 && i.name.size()<20)) {error_message("Invalid name");}if(!(i.date.month>=1 && i.date.month<=12)) {error_message("Invalid month");}
}

3.2.2 解析

分析一:两个 if 判断可能都会为 true 并执行其后语句(非并立),即这两个操作是相关联的,故不是逻辑内聚。在方法中多次调用了形参 i 的不同属性,模块执行的操作是在相同的数据上进行的,故为方法内通信内聚。综上,本题是通信内聚。

分析二:本方法旨在判断输入值是否有效,模块达到一个单一的目的。所以如果需求与方法实现的目标一致(但是本题没有给出需求),也可以是功能内聚。

3.3 例3

3.3.1 问题

下面的 validate_checkout_request 方法的内部代码是哪种类型的内聚?validate_checkout_request 方法与 valid_month 方法之间是哪种类型的耦合?

void validate_checkout_request(input_form i) {if(!valid_string(i.name)) {error_message("Invalid name");}if(!valid_month(i)) {error_message("Invalid month");}int valid_month(input_form i) {return i.date.month>=1 && i.date.month<=12;}
}

3.3.2 解析

  • validate_checkout_request 方法中两个 if 判断语句非并立分支(即并非毫不相关),故排除逻辑内聚。两个判断语句中使用了形参 i 的不同属性,即模块执行的操作在相同的数据上进行,是通信内聚。
  • 第一个模块给第二个模块传递 date 数据,第二个模块只用了其中的一部分,故为印记标记。(因为 valid_month 没有修改 d 的值,故排除内容耦合。)

印记耦合改进后为数据耦合(所有传递的属性全被用到):

void validate_checkout_request(input_form i) {if(!valid_string(i.name)) {error_message("Invalid name");}if(!valid_month(i.date.month)) {error_message("Invalid month");}
}int valid_month(int month) {return month>=1 && month<=12;
}

3.4 例4

3.4.1 问题

下面的 validate_checkout_requst 方法与 valid 方法之间是哪种类型的耦合?

void validate_checkout_request(input_form i) {if(!valid(i.name.STRING)) {error_message("Invalid name");}if(!valid(i.date.DATE)) {error_message("Invalid month");}
}int valid(String s, int type) {swith(type) {case STRING:return strlen(s)=1 && d.month<=12;}
}

3.4.2 解析

第一个模块给第二个模块传递的信息既有数据,又有逻辑:第一个模块发送给第二个模块的消息是由一个值 i.name/i.date 和数据类型 STRING/DATE 组成,第二个模块也要根据数据类型来判断值是否有效这个逻辑来解析消息。所以两个模块共享的是逻辑,是控制耦合。

同时,第二个模块对接收到的 date 类型的参数,只用了其中的 month 属性,故也为印记耦合。

控制耦合和印记耦合是可以接受的。但也可以进行代码完善,完善后为数据耦合:

void validate_checkout_request(input_form i) {if(!valid(i.name.STRING)) {error_message("Invalid name");}if(!valid(i.date.DATE)) {error_message("Invalid month");}
}int valid_string(String s) {return strlen(s)return d.month>=1 && d.month<=12;
}

相关内容

热门资讯

银河麒麟V10SP1高级服务器... 银河麒麟高级服务器操作系统简介: 银河麒麟高级服务器操作系统V10是针对企业级关键业务...
【NI Multisim 14...   目录 序言 一、工具栏 🍊1.“标准”工具栏 🍊 2.视图工具...
AWSECS:访问外部网络时出... 如果您在AWS ECS中部署了应用程序,并且该应用程序需要访问外部网络,但是无法正常访问,可能是因为...
不能访问光猫的的管理页面 光猫是现代家庭宽带网络的重要组成部分,它可以提供高速稳定的网络连接。但是,有时候我们会遇到不能访问光...
AWSElasticBeans... 在Dockerfile中手动配置nginx反向代理。例如,在Dockerfile中添加以下代码:FR...
Android|无法访问或保存... 这个问题可能是由于权限设置不正确导致的。您需要在应用程序清单文件中添加以下代码来请求适当的权限:此外...
月入8000+的steam搬砖... 大家好,我是阿阳 今天要给大家介绍的是 steam 游戏搬砖项目,目前...
​ToDesk 远程工具安装及... 目录 前言 ToDesk 优势 ToDesk 下载安装 ToDesk 功能展示 文件传输 设备链接 ...
北信源内网安全管理卸载 北信源内网安全管理是一款网络安全管理软件,主要用于保护内网安全。在日常使用过程中,卸载该软件是一种常...
AWS管理控制台菜单和权限 要在AWS管理控制台中创建菜单和权限,您可以使用AWS Identity and Access Ma...