高内聚低耦合1.docx
- 文档编号:15945717
- 上传时间:2023-07-09
- 格式:DOCX
- 页数:11
- 大小:23.07KB
高内聚低耦合1.docx
《高内聚低耦合1.docx》由会员分享,可在线阅读,更多相关《高内聚低耦合1.docx(11页珍藏版)》请在冰点文库上搜索。
高内聚低耦合1
对高内聚,低耦合的理解
内聚:
一个模块内各个元素彼此结合的紧密程度
耦合:
一个软件结构内不同模块之间互连程度的气宇(耦合性也叫块间联系。
指软件系统结构中个模块间彼此联系紧密程度的一种气宇。
模块之间联系越紧密,其耦合性就越强,模块的独立性则越差,模块间耦合的高低取决于模块间接口的复杂性,挪用的方式和传递的信息。
)
最近编码的时候,老是在犹豫是把某个方式封装在一个类里,仍是单独的封装成一个类。
这让我突然想起内聚耦合这两个名词。
咱们一直追求着,高内聚,低耦合。
对于低耦合,粗浅的理解是:
一个完整的系统,模块与模块之间,尽可能的使其独立存在。
也就是说,让每一个模块,尽可能的独立完成某个特定的子功能。
模块与模块之间的接口,尽可能的少而简单。
若是某两个模块间的关系比较复杂的话,最好第一考虑进一步的模块划分。
如此有利于修改和组合。
对于低耦合,我粗浅的理解是:
在一个模块内,让每一个元素之间都尽可能的紧密相连。
也就是充分利用每一个元素的功能,各施所能,以最终实现某个功能。
若是某个元素与该模块的关系比较疏松的话,可能该模块的结构还不够完善,或是该元素是多余的。
内聚和耦合,包括了横向和纵向的关系。
功能内聚和数据耦合,是咱们需要达到的目标。
横向的内聚和耦合,通常体此刻系统的各个模块、类之间的关系,而纵向的耦合,体此刻系统的各个层次之间的关系。
对于我在编码中的困惑,我是如此想的,用面向对象的思想去考虑一个类的封装。
一个方法,如何封装,拿到现实生活中来看,看这种能力(方法)是否是属于这类事物(类)的本能。
如果是,就封装在这个类里。
如果不是,则考虑封装在其它类里。
如果这种能力,很多事物都具有,则一定要封装在这类事物的总类里。
如果这种能力,很多事物都会经常用到,则可以封装成一个总类的静态方法。
关于耦合内聚的概念
这些是软件工程中的知识,我上网查过,总结着几位大虾的评论,关于耦合的概念应该是这样的:
1,对象之间的耦合度就是对象之间的依赖性.指导使用和维护对象的主要问题是对象之间的多重依赖性.对象之间的耦合性越高.维护成本越高.因此对象的设计应使类和构件之间的耦合最小.
2,耦合性是程序结构中各个模块之间彼此关联的气宇.它取决于各个模块之间的接口的复杂程度,挪用模块的方式一级哪些信息通过接口,一般模块之间可能的连接方式有七种,耦合性由低到高别离是:
非直接耦合,数据耦合,标记耦合,控制耦合,外部耦合,公共耦合,内容耦合.
一个软件是由多个子程序组装而成,而一个程序由多个模块(方式)组成.
耦合是指各个外部程序(子程序)之间的关系紧密度
而内聚就是指程序内的各个模块之间的关系紧密度
所以说,为什么要高内聚,模块之间的关系越紧密,出错就越少!
低耦合就是说,子程序之间的关系越复杂,就会产生出更多的意想不到的错误!
会给以后的维护工作带来很多麻烦
一个优秀软件开发人员的必修课:
高内聚
高内聚Java软件工程软件模式
一个重要的模式:
高内聚。
2.高内聚(HighCohesion)
高内聚是另一个普遍用来评判软件设计质量的标准。
内聚,更为专业的说法叫功能内聚,是对软件系统中元素职责相关性和集中度的气宇。
若是元素具有高度相关的职责,除这些职责内的任务,没有其它过量的工作,那么该元素就具有高内聚性,反之则为低内聚性。
高内聚要求软件系统中的各个元素具有较高的协作性,因为在咱们在完成软件需求中的一个功能,可能需要做各类情形,可是具有高内聚性的一个元素,只完成它职责内的情形,而把那些不在它职责内的情形拿去请求他人来完成。
这就恍如,若是我是一个项目领导,我的职责是监控和协调我的项目各个阶段的工作。
当我的项目进入需求分析阶段,我会请求需求分析员来完成;当我的项目进入开发阶段,我会请求软件开发人员来完成;当我的项目需要测试的时候,我会请求测试人员。
。
。
。
。
。
若是我参与了开发,我就不是一个高内聚的元素,因为开发不是我的职责。
咱们的项目为何要高内聚呢?
我感觉能够从可读性、复用性、可保护性和易变更性四个方面来理解。
1.可读性
一个人写文章、讲情形,层次清楚才能易于理解,这一样发生在读写软件代码上。
若是一堆代码写得一团乱麻,东一个跳转西一个挪用,读它的人会感觉超级头疼。
这种情形或许一直在写程序的你我都曾经有过经历。
若是一段程序层次超级清楚,每一个类通过名称或说明都能清楚明白它的意义,类的每一个属性、函数也都是易于理解的它所应当完成的任务和行为,这段程序的可读性必然提高。
在软件产业愈来愈密集,软件产业中开发人员协作愈来愈紧密、分工愈来愈细的今天,软件可读性的要求相信也愈来愈为人们所重视。
2.复用性
在软件开发中,最低品级的复用是代码拷贝,然后是函数的复用、对象的复用、组件的复用。
软件开发中最懒的人是最伶俐的人,他们老是想到复用。
在代码编写的时候突然发觉某个功能是曾经实现过的功能,直接把它拷贝过来就ok了。
若是这段代码在同一个对象中,那么就提出来写一个函数处处挪用就好了。
若是不是在同一个对象中呢,就将其抽象成一个对象处处挪用吧。
若是不在一个项目中呢,那就做成组件给各个项目引用吧。
代码复用也使咱们的代码在复用的进程中不断精化、不断健壮、提高代码质量。
代码的复用的确给咱们的开发带来了很多便利,可是一段代码可否在各个需要的地方都能复用呢?
这给咱们的软件开发质量提出了新的要求:
好的代码能够复用,不好的则不行。
软件中的一个对象若是能保证能完成自己职能范围内的各项任务,同时又不去理会与自己职能无关的其它任务,那么它就可以够保证功能的相对独立性,也就可以够离开自己所处的环境而复用到其它环境中,这是一个具有内聚性的对象。
3.可保护性和易变更性
在前面《如安在struts+spring+hibernate的框架下构建低耦合高内聚的软件》中我提到,咱们此刻的软件是在不断变更的,这种变更不仅来自于咱们的客户,更来自于咱们的市场。
若是咱们的软件通过变更能及时适应咱们的市场需求,咱们就可以够在市场竞争中获胜。
如何能及时变更以适应咱们的市场呢,就是通过调整软件的结构,使咱们每次的变更付出的代价最小,花费的人力最小,这种变更才最快最经济。
高内聚的软件,每一个系统、模块、类的任务都高度相关,就使每一次的变更涉及的范围缩小到最小。
比如评审表发生了变更,只会与评审表对象有关,咱们不会去更改其它的对象。
若是咱们能做到这一点,咱们的系统固然是可保护性好、易变更性好的系统。
那么,咱们如何做到高内聚呢?
就拿前面我提到的评审项目举例。
我此刻要为“评审表”对象编写一段填写并保留评审表的代码。
评审表对象的职责是更新和查询评审表的数据,可是在显示一个要填写的评审表的时候,我需要显示该评审计划的名称、该评审计划有哪些评审对象需要评审。
此刻我如何编写显示一个要填写的评审表的代码?
我在评审表对象的那个相应的函数中编写一段查询评审计划和评审对象的代码吗?
假设你如此做了,你的代码就不是高内聚的,因为查询评审计划和评审对象的数据不是它的职责。
正确的方式应当去请求“评审计划”对象和“评审对象”对象来完成这些工作,而“评审表”对象只是获取其结果。
另外,若是一个对象要完成一个虽然在自己职责范围内,但进程超级复杂的任务时,也应当将该任务分解成数个功能相对独立的子函数来完成。
我曾经看见一个朋友写的数百行的一个函数,让人读起来超级费力。
同时如此的函数中一些相对独立的代码,本能够复用到其它代码中,也变成了不可能。
所以我给大家的建议是,不要写太长的函数,超过一百行就可以够考虑将一些功能分解出去。
与“低耦合”一样,高内聚也不是一个绝对,而是一个相对的指标,应当适当而不能过度。
正如咱们在现实生活中,若是在一个十来人的小公司,每一个人的分工可能会粗一些,所分派的职责会广一些杂一些,因为其整体的任务少;而若是在一个一两百人的大公司,每一个人的分工会细一些,所分派的任务会加倍专一些,因为整体任务多,更需要专业化的分工来提高效率。
软件开发也是一样,若是“评审计划”对象完成的业务功能少,而且不复杂,它完全能够代理它的子表“评审对象”和“评审者”的管理。
可是“评审计划”对象需要完成的“对评审计划表的管理”那个大体职责包括的业务功能繁多或复杂,它就应当将“对评审对象表的管理”交给“评审对象”对象,将“对评审者表的管理”交给“评审者”对象。
一样,高内聚的可保护性好、易变更性好只能是一个相对的指标。
若是一个变更的确是大范围的变更,你永久不可能通过内聚就不进行大范围的变更了。
同时内聚也是要付出代价的,所以你也没必要要去为了一个不太可能的变更去进行过度设计,应当掌握一个度。
过度的内聚必将增加系统中元素之间的依赖,提高耦合度。
所以“高内聚”与“低耦合”是矛盾的,必需衡量利弊,综合地去向理。
在李洋等人翻译的《UML和模式应用》中,将内聚和耦合翻译为软件工程中的阴与阳,是中国人对内聚和耦合的最佳解释。
综上所述,“高内聚”给软件项目带来的长处是:
可读性强、易保护和变更、支持低耦合、移植和重用性强。
一个优秀软件开发人员的必修课:
GRASP
(2)低耦合
关键字:
设计模式
我偶然在google或yahoo如此的搜索引擎搜索GRASP发觉,除国外的网站,国内网站多介绍和讨论GoF而很少介绍GRASP,即便这少量的文章也讲解超级粗略。
个人以为作为优秀的开发人员,理解GRASP比GoF更重要,故写此文章。
前面我在《(原创)一个优秀软件开发人员的必修课:
GRASP软件开发模式浅析》中介绍了利用GRASP的目的,今天允许我调换一下顺序,先从低耦合讲起,因为诸如创建者模式、信息专家模式的根本目的就是降低耦合。
1.低耦合(LowCoupling)
“低耦合”那个词相信大家已经耳熟能详,咱们在看spring的书籍、MVC的数据、设计模式的书籍,无处不提到“低耦合、高内聚”,它已经成为软件设计质量的标准之一。
那么什么是低耦合?
耦合就是对某元素与其它元素之间的连接、感知和依赖的量度。
这里所说的元素,即能够是功能、对象(类),也能够指系统、子系统、模块。
假设一个元素A去连接元素B,或通过自己的方式能够感知B,或当B不存在的时候就不能正常工作,那么就说元素A与元素B耦合。
耦合带来的问题是,当元素B发生变更或不存在时,都将影响元素A的正常工作,影响系统的可保护性和易变更性。
同时元素A只能工作于元素B存在的环境中,这也降低了元素A的可复用性。
正因为耦合的各种短处,咱们在软件设计的时候尽力追求“低耦合”。
低耦合就是要求在咱们的软件系统中,某元素不要过度依赖于其它元素。
请注意这里的“过度”二字。
系统中低耦合不能过度,比如说咱们设计一个类能够不与JDK耦合,这可能吗?
除非你不是设计的Java程序。
再比如我设计了一个类,它不与我的系统中的任何类发生耦合。
若是有如此一个类,那么它必然是低内聚(关于内聚的问题我随后讨论)。
耦合与内聚常常是一个矛盾的两个方面。
最佳的方案就是寻觅一个适合的中间点。
哪些是耦合呢?
1.元素B是元素A的属性,或元素A引用了元素B的实例(这包括元素A挪用的某个方式,其参数中包括元素B)。
2.元素A挪用了元素B的方式。
3.元素A直接或间接成为元素B的子类。
4.元素A是接口B的实现。
幸运的是,目前已经有大量的框架帮忙咱们降低咱们系统的耦合度。
比如,利用struts咱们能够应用MVC模型,使页面展现与业务逻辑分离,做到了页面展现与业务逻辑的低耦合。
当咱们的页面展现需要变更时,咱们只需要修改咱们的页面,而不影响咱们的业务逻辑;一样,咱们的业务逻辑需要变更的时候,咱们只需要修改咱们的java程序,与咱们的页面无关。
利用spring咱们运用IoC(反向控制),降低了业务逻辑中各个类的彼此依赖。
假设类A因为需要功能F而挪用类B,在通常的情形下类A需要引用类B,因此类A就依赖于类B了,也就是说当类B不存在的时候类A就无法利用了。
利用了IoC,类A挪用的仅仅是实现了功能F的接口的某个类,那个类可能是类B,也可能是另一个类C,由spring的配置文件来决定。
如此,类A就再也不依赖于类B了,耦合度降低,重用性提高了。
利用hibernate则是使咱们的业务逻辑与数据持久化分离,也就是与将数据存储到数据库的操作分离。
咱们在业务逻辑中只需要将数据放到值对象中,然后交给hibernate,或从hibernate那里取得值对象。
至于用Oracle、MySQL仍是SQLServer,如何执行的操作,与我无关。
可是,作为优秀的开发人员,仅仅依托框架提供的降低软件耦合的方式是远远不够的。
按照我的经验,以下一些问题咱们应当引发注意:
1)按照可能的转变设计软件
咱们采用职责驱动设计,设计中尽力做到“低耦合、高内聚”的一个超级重要的前提是,咱们的软件是在不断转变的。
若是没有转变咱们固然就不用这么费力了;可是若是有转变,咱们希望通过以上的设计,使咱们在适应或更改如此的转变的时候,付出更小的代价。
这里提供了一个超级重要的信息是,咱们尽力降低耦合的是那些可能发生变更的地方,因为降低耦合是有代价的,是以增加资源花费和代码复杂度为代价的。
若是系统中某些元素不太可能变更,或降低耦合所付出的代价太大,咱们固然就应被选择耦合。
有一次我试图将我的表现层不依赖于struts,但发觉如此的尝试代价太大而失去意义了。
对于软件可能变更的部份,咱们应当尽力去降低耦合,这就给咱们提出一个要求是,在软件设计的时候能够预判往后的转变。
按照以往的经验我以为,一个软件的业务逻辑和采用的技术框架往往是容易转变的2个方面。
客户需求变更是咱们软件设计必需考虑的问题。
在RUP的开发进程中,为何需要将分析设计的进程分为分析模型和设计模型,愚以为,从分析模型到设计模型的进程实际上是系统从知足直接的客户需求到优化系统结构、适应可预见的客户需求变更的一个进程。
这种客户需求的变更不单单指对一个客户需求的变更,更是指咱们的软件从适应一个客户需求到适应更多客户需求的进程。
另一个方面,此刻技术变更之快,EJB、hibernate、spring、ajax,一个一个的技术像走马灯一样从咱们脑海中滑过,咱们真不明白明天我在用什么。
在如此的情形下,适应转变就是咱们最佳的选择。
2)合理的职责划分
合理的职责划分,让系统中的对象各司其职,不仅是提高内聚的要求,同时也能够有效地降低耦合。
比如评审计划BUS、评审表BUS、评审报告BUS都需要通过评审计划DAO去查询一些评审计划的数据,若是它们都去直接挪用评审计划DAO(如图A),则评审计划BUS、评审表BUS、评审报告BUS三个对象都与评审计划DAO耦合,评审计划DAO一旦变更将与这三个对象都有关。
在那个实例中,实际上评审计划BUS是信息专家(关于信息专家模式我将在后面讨论),评审表BUS和评审报告BUS若是需要取得评审计划的数据,应当向评审计划BUS提出需求,由评审计划BUS提供数据(如图B)。
通过如此的调整,系统的耦合度就降低了。
3)利用接口而不是继承
通过对耦合的分析,咱们不难发觉,继承就是一种耦合。
若是子类A继承了父类B,不论是直接或间接的继承,子类A都必将依赖父类B。
子类A必需利用在存在父类B的环境中,父类B不存在子类A就不能利用,如此将影响子类A的可移植性。
一旦父类B发生任何变更,更改或去掉一个函数名,或改变一个函数的参数,都将致使子类A不能不变更,乃至重写。
假设父类B的子类数十上百个,乃至贯穿那个项目各个模块,如此的变更是灾难性的。
这种情形最典型的例子是咱们此刻利用hibernate和spring设计DAO对象的方式,具体的描述参见我写的《如安在struts+spring+hibernate的框架下构建低耦合高内聚的软件结构》一文。
总之,“低耦合”给软件项目带来的长处是:
易于变更、易于重用
模块的耦合与内聚
2009-08-0500:
07 阅读52 评论0
字号:
大 中 小
模块的耦合与内聚
耦合(Coupling)是模块之间依赖程度的气宇。
内聚和耦合是紧密相关的,与其它模块存在强耦合的模块通常意味着弱内聚,而强内聚的模块通常意味着与其它模块之间存在弱耦合。
模块设计追求强内聚,弱耦合。
内聚(Cohesion)是一个模块内部各成份之间相关联程度的气宇。
耦合(Coupling)
耦合(Coupling)是指两个或两个以上的电路元件或电网络的输入与输出之间存在紧密配合与相互影响,并通过相互作用从一侧向另一侧传输能量的现象;概括的说耦合就是指两个实体相互依赖于对方的一个量度.分为以下几种:
非直接耦合:
两个模块之间没有直接关系,它们之间的联系完全是通过主模块的控制和调用来实现的
:
一个模块访问另一个模块时,彼此之间是通过简单数据参数(不是控制参数、公共数据结构或外部变量)来交换输入、输出信息的。
:
一组模块通过参数表传递记录信息,就是标记耦合。
这个记录是某一数据结构的子结构,而不是简单变量。
:
如果一个模块通过传送开关、标志、名字等控制信息,明显地控制选择另一模块的功能,就是控制耦合。
外部耦合:
一组模块都访问同一全局简单变量而不是同一全局数据结构,而且不是通过参数表传递该全局变量的信息,则称之为外部耦合。
公共耦合:
若一组模块都访问同一个公共数据环境,则它们之间的耦合就称为公共耦合。
公共的数据环境可以是全局数据结构、共享的通信区、内存的公共覆盖区等。
内容耦合:
如果发生下列情形,两个模块之间就发生了内容耦合
(1)一个模块直接访问另一个模块的内部数据;
(2)一个模块不通过正常入口转到另一模块内部;
(3)两个模块有一部分程序代码重迭(只可能出现在汇编语言中);
(4)一个模块有多个入口。
耦合强度,依赖于以下几个因素:
(1)一个模块对另一个模块的调用;
(2)一个模块向另一个模块传递的数据量;
(3)一个模块施加到另一个模块的控制的多少;
(4)模块之间接口的复杂程度。
耦合按从强到弱的顺序可分为以下几种类型:
(1)内容耦合。
当一个模块直接修改或操作另一个模块的数据,或者直接转入另一个模块时,就发生了内容耦合。
此时,被修改的模块完全依赖于修改它的模块。
(2)公共耦合。
两个以上的模块共同引用一个全局数据项就称为公共耦合。
(3)控制耦合。
一个模块在界面上传递一个信号(如开关值、标志量等)控制另一个模块,接收信号的模块的动作根据信号值进行调整,称为控制耦合。
(4)标记耦合。
模块间通过参数传递复杂的内部数据结构,称为标记耦合。
此数据结构的变化将使相关的模块发生变化。
(5)数据耦合。
模块间通过参数传递基本类型的数据,称为数据耦合。
(6)非直接耦合。
模块间没有信息传递时,属于非直接耦合。
如果模块间必须存在耦合,就尽量使用数据耦合,少用控制耦合,限制公共耦合的范围,坚决避免使用内容耦合。
内聚
内聚(Cohesion)是一个模块内部各成分之间相关联程度的度量
一、内聚强度
内聚按强度从低到高有以下几种类型:
(1)偶然内聚。
如果一个模块的各成分之间毫无关系,则称为偶然内聚。
(2)逻辑内聚。
几个逻辑上相关的功能被放在同一模块中,则称为逻辑内聚。
如一个模块读取各种不同类型外设的输入。
尽管逻辑内聚比偶然内聚合理一些,但逻辑内聚的模块各成分在功能上并无关系,即使局部功能的修改有时也会影响全局,因此这类模块的修改也比较困难。
(3)时间内聚。
如果一个模块完成的功能必须在同一时间内执行(如系统初始化),但这些功能只是因为时间因素关联在一起,则称为时间内聚。
(4)过程内聚。
如果一个模块内部的处理成分是相关的,而且这些处理必须以特定的次序执行,则称为过程内聚。
(5)通信内聚。
如果一个模块的所有成分都操作同一数据集或生成同一数据集,则称为通信内聚。
(6)顺序内聚。
如果一个模块的各个成分和同一个功能密切相关,而且一个成分的输出作为另一个成分的输入,则称为顺序内聚。
(7)功能内聚。
模块的所有成分对于完成单一的功能都是必须的,则称为功能内聚
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 高内聚低 耦合