低耦合高内聚,一直是软件开发人员心中始终铭记的开发准则,然而在平常的开发中,却经常忽略它的存在,或者不能清晰的知道如何去作才能更好的解耦和内聚。多年从事于软件开发工做的我,开发了不少功能,也接手过不少别人的工做,深知其中的坑与痛,因此决心作出改变,本文将从0开始逐步深刻研究,探索低耦合、高内聚的编码之道。segmentfault
首先,先了解下前人总结的耦合性和聚合性的分类,此部份内容来自百度,若是你们以前有所了解能够直接跳过:安全
耦合性,也叫耦合度,是对模块间关联程度的度量。耦合的强弱取决于模块间接口的复杂性、调用模块的方式以及经过界面传送数据的多少。模块间的耦合度是指模块之间的依赖关系,包括控制关系、调用关系、数据传递关系。模块间联系越多,其耦合性越强,同时代表其独立性越差( 下降耦合性,能够提升其独立性)。软件设计中一般用耦合度和内聚度做为衡量模块独立程度的标准。划分模块的一个准则就是高内聚低耦合。网络
通常模块之间可能的链接方式有七种,构成耦合性的七种类型。它们之间的关系为(独立性由强到弱)数据结构
若是两个模块之间没有直接关系,它们之间的联系彻底是经过主模块的控制和调用来实现的,这就是非直接耦合。这种耦合的模块独立性最强。编码
若是一个模块访问另外一个模块时,彼此之间是经过数据参数(不是控制参数、公共数据结构或外部变量)来交换输入、输出信息的,则称这种耦合为数据耦合。因为限制了只经过参数表传递数据,按数据耦合开发的程序界面简单、安全可靠。所以,数据耦合是松散的耦合,模块之间的独立性比较强。在软件程序结构中至少必须有这类耦合。设计
补充:数据耦合的结果只和传入的参数有关,且不会改变参数的数据,因此耦合度极低,平常开发应尽可能分离出这样的模块结构来下降耦合。code
若是一组模块经过参数表传递记录信息,就是标记耦合,也称特征耦合。事实上,这组模块共享了这个记录,它是某一数据结构的子结构,而不是简单变量。这要求这些模块都必须清楚该记录的结构,并按结构要求对此记录进行操做。在设计中应尽可能避免这种耦合,它使在数据结构上的操做复杂化了。若是采起“信息隐蔽”的方法,把在数据结构上的操做所有集中。接口
若是一个模块经过传送开关、标志、名字等控制信息,明显地控制选择另外一模块的功能,就是控制耦合。这种耦合的实质是在单一接口上选择多功能模块中的某项功能。所以,对所控制模块的任何修改,都会影响控制模块。另外,控制耦合也意味着控制模块必须知道所控制模块内部的一些逻辑关系,这些都会下降模块的独立性。内存
补充:平常开发中常常须要根据某种状态来决定执行的逻辑,这几乎是不可避免的,这种状况咱们就须要尽可能把状态逻辑封装到顶层,各个状态要执行的具体逻辑封装成独立的模块以最大限度下降影响。开发
一组模块都访问同一全局简单变量而不是同一全局数据结构,并且不是经过参数表传递该全局变量的信息,则称之为外部耦合。例如C语言程序中各个模块都访问被说明为extern类型的外部变量。外部耦合引发的问题相似于公共耦合,区别在于在外部耦合中不存在依赖于一个数据结构内部各项的物理安排。
补充:外部耦合指的是共同访问一些简单变量,不涉及数据结构。
若一组模块都访问同一个公共数据环境,则它们之间的耦合就称为公共耦合。公共的数据环境能够是全局数据结构、共享的通讯区、内存的公共覆盖区等。 这种耦合会引发下列问题:
全部公共耦合模块都与某一个公共数据环境内部各项的物理安排有关,若修改某个数据的大小,将会影响到全部的模块。
没法控制各个模块对公共数据的存取,严重影响软件模块的可靠性和适应性。
公共数据名的使用,明显下降了程序的可读性。
公共耦合的复杂程度随耦合模块的个数增长而显著增长。若只是两个模块之间有公共数据环境,则公共耦合有两种状况。
若一个模块只是往公共数据环境里传送数据,而另外一个模块只是从公共数据环境中取数据,则这种公共耦合叫作松散公共耦合。若两个模块都从公共数据环境中取数据,又都向公共数据环境里送数据,则这种公共耦合叫作紧密公共耦合。只有在模块之间共享的数据不少,且经过参数表传递不方便时,才使用公共耦合。不然,仍是使用模块独立性比较高的数据耦合好些。
若是发生下列情形,两个模块之间就发生了内容耦合。
1、一个模块直接访问另外一个模块的内部数据; 2、一个模块不经过正常入口转到另外一模块内部(好比反射); 3、两个模块有一部分程序代码重叠(只可能出如今汇编语言中); 4、一个模块有多个入口。
在内容耦合的情形,所访问模块的任何变动,或者用不一样的编译器对它再编译,都会形成程序出错。好在大多数高级程序设计语言已经设计成不容许出现内容耦合。它通常出如今汇编语言程序中。这种耦合是模块独立性最弱的耦合。
内聚的种类通常也是分红7种,从上到下内聚性依次加强:
一个模块内的各处理元素之间没有任何联系,只是偶然地被凑到一块儿。这种模块也称为巧合内聚,内聚程度最低(极力避免)。
这种模块把几种相关的功能组合在一块儿, 每次被调用时,由传送给模块参数来肯定该模块应完成哪种功能(与控制耦合相似) 。
把须要同时执行的动做组合在一块儿造成的模块称为时间内聚模块。
构件或者操做的组合方式是,容许在调用前面的构件或操做以后,立刻调用后面的构件或操做,即便二者之间没有数据进行传递。简单的说就是若是一个模块内的处理元素是相关的,并且必须以特定次序执行则称为过程内聚。例如某要完成登陆的功能,前一个功能判断网络状态,后一个执行登陆操做,显然是按照特定次序执行的。
指模块内全部处理元素都在同一个数据结构上操做或全部处理功能都经过公用数据而发生关联(有时称之为信息内聚)。即指模块内各个组成部分都使用相同的数据结构或产生相同的数据结构。
一个模块中各个处理元素和同一个功能密切相关,并且这些处理必须顺序执行,一般前一个处理元素的输出时后一个处理元素的输入。例如某要完成获取订单信息的功能,前一个功能获取用户信息,后一个执行计算均价操做,显然该模块内两部分紧密关联。顺序内聚的内聚度比较高,但缺点是不如功能内聚易于维护。
模块内全部元素的各个组成部分所有都为完成同一个功能而存在,共同完成一个单一的功能,模块已不可再分。即模块仅包括为完成某个功能所必须的全部成分,这些成分紧密联系、缺一不可。
经过上面的内容,咱们已经对耦合性和内聚性有了必定程度的理解,在平常的开发中,咱们要尽量用耦合性低,内聚性高的方式,参考上面的介绍。这样子在开发过程当中前期会有必定的速度影响,可是在以后,不管查找问题仍是扩展功能亦或是修改收益仍是很是大的,当别人由于一个小的变更就抓耳挠腮,无从下手,必须重构时,你就会暗自庆幸当时的机智!