软考考点之耦合与内聚类型区分

本文深入解析软件工程中的高内聚低耦合概念,阐述模块内聚性与耦合性的不同级别,以及如何在设计中实现这一原则,提升软件质量和可维护性。

除参见 《软考》系统开发与软件工程

高内聚低耦合,是软件工程中的概念,是判断设计好坏的标准,主要是面向对象的设计,看类的内聚性是否高,耦合度是否低

内聚关注模块内部的元素结合程度,耦合关注模块之间的依赖程度。

内聚性:

又称块内联系。指模块的功能强度的度量,即一个模块内部各个元素彼此结合的紧密程度的度量。若一个模块内各元素(语名之间、程序段之间)联系的越紧密,则它的内聚性就越高。

所谓高内聚是指一个软件模块是由相关性很强的代码组成,只负责一项任务,也就是常说的单一责任原则。

 

内聚(能联系实际写代码时的情景或方式,理解这些名称会更容易记些)。

模块内部的元素, 关联性越强, 则内聚越高, 模块单一性更强。 一个模块应当尽可能独立完成某个功能,

如果有各种场景需要被引入到当前模块, 代码质量将变得非常脆弱, 这种情况建议拆分为多个模块。
  

模块的种类有:
  偶然内聚(巧合内聚)一个模块内的各处理元素之间没有任何联系,只是偶然地被凑到一起。这种模块也称为巧合内聚,内聚程度最低。


  逻辑内聚:这种模块把几种相关的功能组合在一起, 每次被调用时,由传送给模块参数来确定该模块应完成哪一种功能 。相关的功能也就是逻辑上的功能放在一起。如表述,我和全世界的人,比较松


  时间内聚:把需要同时执行的动作组合在一起形成的模块称为时间内聚模块。仅是时间上相关的动作,如一边看书,一边听音乐,可以描述了件事情了,但还不是必须在一块执行的动作。


  过程内聚:构件或者操作的组合方式是,允许在调用前面的构件或操作之后,马上调用后面的构件或操作,即使两者之间没有数据进行传递。简单的说就是如果一个模块内的处理元素是相关的,而且必须以特定次序执行则称为过程内聚。两个功能同属于一个过程中,有了在一起的理由。
例如某要完成登录的功能,前一个功能判断网络状态,后一个执行登录操作,显然是按照特定次序执行的。


  通信内聚:指模块内所有处理元素都在同一个数据结构上操作或所有处理功能都通过公用数据而发生关联(有时称之为信息内聚)。即指模块内各个组成部分都使用相同的数据结构或产生相同的数据结构。两个模块需要交换数据(通信)了,才能完成某一个功能。这样在一起的 理由更充分了一些。


  顺序内聚:一个模块中各个处理元素和同一个功能密切相关,而且这些处理必须顺序执行,通常前一个处理元素的输出是后一个处理元素的输入。顺序虽然也代表着过程,但有本质的区别,还是体现在数据的关联上,顺序强调的是前一个输出是后一个的输入。不仅强调数据交流(通信)还限制顺序,在一起的理由就更充分了。
例如某要完成获取订单信息的功能,前一个功能获取用户信息,后一个执行计算均价操作,显然该模块内两部分紧密关联。
顺序内聚的内聚度比较高,但缺点是不如功能内聚易于维护。


  功能内聚:模块内所有元素的各个组成部分全部都为完成同一个功能而存在,共同完成一个单一的功能,模块已不可再分。即模块仅包括为完成某个功能所必须的所有成分,这些成分紧密联系、缺一不可。就是为了单一的功能,不可再拆分了,必须在一起了。


 功能内聚是最强的内聚,其优点是它的功能明确。判断一个模块是否功能内聚,一般从模块名称就能看出。如果模块名称只有一个动词和一个特定的目标(单数名词),一般来说就是功能内聚,如:“计算水费”、“计算产值”等模块。功能内聚一般出现在软件结构图的较低层次上。
功能内聚模块的一个重要特点是:他是一个“暗盒”,对于该模块的调用者来说,只需要知道这个模块能做什么,而不需要知道这个模块是如何做的。

 

耦合性:

也称块间联系。指软件系统结构中各模块间相互联系紧密程度的一种度量。模块之间联系越紧密,其耦合性就越强,模块的独立性则越差。模块间耦合高低取决于模块间接口的复杂性、调用的方式及传递的信息。

对于低耦合,粗浅的理解是:一个完整的系统,模块与模块之间,尽可能的使其独立存在。也就是说,让每个模块,尽可能的独立完成某个特定的子功能。模块与模块之间的接口,尽量的少而简单。如果某两个模块间的关系比较复杂的话,最好首先考虑进一步的模块划分。这样有利于修改和组合。

 

耦合

耦合可以分为以下几种,它们之间的耦合度由高到低排列如下:

  • 内容耦合:一个模块直接访问另一模块的内容,则称这两个模块为内容耦合。
    若在程序中出现下列情况之一,则说明两个模块之间发生了内容耦合:

    1. 一个模块直接访问另一个模块的内部数据。
    2. 一个模块不通过正常入口而直接转入到另一个模块的内部。
    3. 两个模块有一部分代码重叠(该部分代码具有一定的独立功能)。
    4. 一个模块有多个入口。

内容耦合可能在汇编语言中出现。大多数高级语言都已设计成不允许出现内容耦合。这种耦合的耦合性最强,模块独立性最弱。

其中一个模块访问另一个模块的内部,也就是信赖另一个模块的内容

  • 公共耦合:一组模块都访问同一个全局数据结构,则称之为公共耦合。公共数据环境可以是全局数据结构、共享的通信区、内存的公共覆盖区等。如果模块只是向公共数据环境输入数据,或是只从公共数据环境取出数据,这属于比较松散的公共耦合;如果模块既向公共数据环境输入数据又从公共数据环境取出数据,这属于较紧密的公共耦合。
    公共耦合会引起以下问题:一个模块通过公共的数据与另一个模块关联,有共用的大量数据,那么还是不独立。

    1. 无法控制各个模块对公共数据的存取,严重影响了软件模块的可靠性和适应性。
    2. 使软件的可维护性变差。若一个模块修改了公共数据,则会影响相关模块。
    3. 降低了软件的可理解性。不容易清楚知道哪些数据被哪些模块所共享,排错困难。

    一般地,仅当模块间共享的数据很多且通过参数传递很不方便时,才使用公共耦合。

  • 外部耦合:一组模块都访问同一全局简单变量,而且不通过参数表传递该全局变量的信息,则称之为外部耦合。模块间通过外部的简单变量,少量的共用数据产生关联,独立性好点了。

  • 控制耦合:模块之间传递的不是数据信息,而是控制信息例如标志、开关量等,一个模块控制了另一个模块的功能。模块间通过控制信号,肯定是外部的了,并且是开关量,共用数据更少了。独立性更好了。

  • 标记耦合:调用模块和被调用模块之间传递数据结构而不是简单数据,同时也称作特征耦合。表就和的模块间传递的不是简单变量,而是像高级语言中的数据名、记录名和文件名等数据结果,这些名字即为标记,其实传递的是地址。标记理解为地址的话,地址里的内容可不一定是固定的,所以模块间的关系,基本开始脱离数据这么紧密的关系了,开始独立了。

  • 数据耦合:调用模块和被调用模块之间只传递简单的数据项参数。相当于高级语言中的值传递。只是传递了个数据,如1,不用于共用数据了才行了,更加独立了。

  • 非直接耦合:两个模块之间没有直接关系,它们之间的联系完全是通过主模块的控制和调用来实现的。耦合度最弱,模块独立性最强。

  • 软件设计时,如何做好高内聚低耦合?

在设计上我们应采用以下原则:若模块间必须存在耦合,应尽量使用数据耦合,少用控制耦合,慎用或有控制地使用公共耦合,并限制公共耦合的范围,尽量避免内容耦合。

 

 

### 高内聚的概念 高内聚是指在一个模块、类或组件内部,各个元素之间的联系紧密,职责单一且高度相关。这种设计原则确保了模块内部的功能集中,减少了模块内部的复杂性和冗余[^2]。高内聚类型包括偶然内聚、逻辑内聚、时间内聚、通信内聚顺序内聚、功能内聚和信息内聚等,其中功能内聚是最理想的状态,因为它表示模块内的所有元素都共同完成一个明确的功能[^3]。 ### 高内聚件开发中的应用 在件开发中,高内聚的应用主要体现在以下几个方面: 1. **提高可维护性**:高内聚的设计使得模块内部的功能更加集中,减少了模块之间的依赖关系,从而降低了系统的复杂性。这使得开发人员更容易理解和维护代码[^1]。 2. **增强可扩展性**:由于模块内部的职责单一且高度相关,新增功能或修改现有功能时,只需对相关模块进行调整,而不影响其他模块。这种设计方式使得系统更容易扩展[^1]。 3. **提升可重用性**:高内聚的模块通常具有明确的功能定义,这使得它们可以在不同的项目或系统中被重复使用。通过复用已有的高内聚模块,可以显著减少开发时间和成本[^2]。 4. **改善测试效率**:高内聚的模块由于其职责单一,测试时更容易覆盖所有可能的情况。这不仅提高了测试的效率,还减少了潜在的错误和缺陷[^1]。 ### 应用场景 1. **模块化设计**:在设计大型件系统时,采用高内聚的原则可以帮助开发者将系统划分为多个独立的模块,每个模块负责一个特定的功能。这种设计方式不仅提高了系统的可维护性,还增强了系统的可扩展性。 2. **面向对象编程**:在面向对象编程中,类的设计应遵循高内聚的原则。每个类应该只有一个职责,并且类中的方法和属性都应该围绕这个职责展开。这种设计方式有助于提高代码的可读性和可维护性。 3. **微服务架构**:在微服务架构中,每个服务都是一个独立的模块,负责处理特定的业务逻辑。通过遵循高内聚的原则,每个服务可以独立部署、扩展和维护,从而提高了系统的灵活性和可靠性[^1]。 4. **代码重构**:在代码重构过程中,开发人员可以通过识别和分离低内聚的代码块,将其转换为高内聚的模块。这种重构方式可以显著提高代码的质量和可维护性[^2]。 ### 示例代码 以下是一个简单的Python示例,展示了如何通过高内聚的设计原则来实现一个功能单一的类: ```python class Calculator: def add(self, a, b): return a + b def subtract(self, a, b): return a - b def multiply(self, a, b): return a * b def divide(self, a, b): if b == 0: raise ValueError("Cannot divide by zero") return a / b ``` 在这个示例中,`Calculator`类的所有方法都围绕一个明确的功能展开,即基本的数学运算。每个方法的职责单一,且相互之间联系紧密,符合高内聚的设计原则。 ###
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

guangod

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值