【已回答】编程思想里面,何谓解耦?

    想知道何为解耦,就要先知道何为“耦合”。
    什么是耦合这个东西叫老虎钳。
    它的作用很多,可以剪断铁丝、可以把铁丝扭起来完成捆扎、可以捏合/撕裂铁皮……甚至,应急情况下,它还可以拿来拧螺丝(强烈不推荐!因为很容易把螺丝棱面拧花甚至拧圆,导致再也拧不开,只能切割掉)。
    这个东西叫压线钳。
    顾名思义,这东西只能拿来压制网线水晶头——也可以在制作水晶头前,很方便的剥开网线、露出线芯。
    很显然,压线钳和网线水晶头、以及网络布线这个业务严重耦合了——它知道了太多关于网线、关于水晶头的细节;又针对这些细节做了太多的设计。
    这个耦合,就使得它只能拿来制作网线,做其他任何东西都不再适合。
    耦合的好处很显然,在压线钳这个案例中,耦合带来了设计的简化(只需要考虑制作网线这一个场景,不需要考虑其他)、操作的简化(剪短网线,剥开外层套皮,剥出每根线的铜芯,按标准顺序排布整齐,然后塞进水晶头,用压线钳一压,完成)……
    因此……
    嗯,再重复一次那个经典的商城案例吧。这次我说详细点。
    事情是这样的:那是一家云计算公司;众所周知,云计算听起来高大上,但核心业务其实就是……卖虚拟机。
    其中一种生成虚拟机的方式是通过这个命令:
    virt-install --name=guest1-rhel5-64#虚拟机的名字 --file=/var/lib/libvirt/images/guest1-rhel5-64.dsk#磁盘文件,虚拟机拿它当硬盘用 --file-size=8#磁盘文件最大值 --nonsparse--graphicsspice --vcpus=2#虚拟机的CPU核心数量 --ram=2048#虚拟机物理内存大小 --location=http://example1.com/installation_tree/RHEL5.6-Serverx86_64/os --networkbridge=br0 --os-type=linux --os-variant=rhel5.4

软硬件解耦是什么意思
    编程思想里面,何谓解耦?

一、解耦是什么

    解耦就是用数学方法将两种运动分离开来处理问题,常用解耦方法就是忽略或简化对所研究问题影响较小的一种运动,只分析主要的运动。
    数学中解耦是指使含有多个变量的数学方程变成能够用单个变量表示的方程组,即变量不再同时共同直接影响一个方程的结果,从而简化分析计算。通过适当的控制量的选取,坐标变换等手段将一个多变量系统化为多个独立的单变量系统的数学模型,即解除各个变量之间的耦合。最常见的有发电机控制,锅炉调节等系统。软件开发中的耦合偏向于两者或多者的彼此影响,解耦就是要解除这种影响,增强各自的独立存在能力,可以无限降低存在的耦合度,但不能根除,否则就失去了彼此的关联,失去了存在意义。

二、解耦是什么意思?

    首先要明确有个“耦合”的物理概念,耦合是指两个或两个以上的体系或两种运动形式间通过相互作用而彼此影响以至联合起来的现象。 解耦就是用数学方法将两种运动分离开来处理问题,常用解耦方法就是忽略或简化对所研究问题影响较小的一种运动,只分析主要的运动

三、程序设计经常提到的解耦,到底是要解除什么之间的耦合?

    但凡是做企业级的软件,低耦合高内聚都是金标准。
    先用两张图说明下到底是解除什么之间的耦合:
    高耦合低内聚
    低耦合高内聚
    你觉得哪个好?
    先说说低耦合:
    这个词相信大家已经耳熟能详,我们在看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.合理的职责划分
    合理的职责划分,让系统中的对象各司其职,不仅是提高内聚的要求,同时也可以有效地降低耦合。
    3.使用接口而不是继承
    继承就是一种耦合。如果子类A继承了父类B,不论是直接或间接的继承,子类A都必将依赖父类B。子类A必须使用在存在父类B的环境中,父类B不存在子类A就不能使用,这样将影响子类A的可移植性。
    一旦父类B发生任何变更,更改或去掉一个函数名,或者改变一个函数的参数,都将导致子类A不得不变更,甚至重写。假如父类B的子类数十上百个,甚至贯穿这个项目各个模块,这样的变更是灾难性的。
    “低耦合”给软件项目带来的优点是:易于变更、易于重用。
    再说说高内聚
    高内聚是另一个普遍用来评判软件设计质量的标准。内聚,更为专业的说法叫功能内聚,是对软件系统中元素职责相关性和集中度的度量。如果元素具有高度相关的职责,除了这些职责内的任务,没有其它过多的工作,那么该元素就具有高内聚性,反之则为低内聚性。高内聚要求软件系统中的各个元素具有较高的协作性,因为在我们在完成软件需求中的一个功能,可能需要做各种事情,但是具有高内聚性的一个元素,只完成它职责内的事情,而把那些不在它职责内的事情拿去请求别人来完成。
    1.可读性
    如果一段程序条理非常清晰,每个类通过名称或说明都能清楚明白它的意义,类的每个属性、函数也都是易于理解的它所应当完成的任务和行为,这段程序的可读性必然提高。在软件产业越来越密集,软件产业中开发人员协作越来越紧密、分工越来越细的今天,软件可读性的要求相信也越来越为人们所重视。
    2.复用性
    在软件开发中,最低等级的复用是代码拷贝,然后是函数的复用、对象的复用、组件的复用。软件开发中最懒的人是最聪明的人,他们总是想到复用。在代码编写的时候突然发现某个功能是曾经实现过的功能,直接把它拷贝过来就ok了。如果这段代码在同一个对象中,那么就提出来写一个函数到处调用就行了。如果不是在同一个对象中呢,就将其抽象成一个对象到处调用吧。如果不在一个项目中呢,那就做成组件给各个项目引用吧。
    代码复用也使我们的代码在复用的过程中不断精化、不断健壮、提高代码质量。代码的复用的确给我们的开发带来了不少便利,但是一段代码能否在各个需要的地方都能复用呢?这给我们的软件开发质量提出了新的要求:好的代码可以复用,不好的则不行。软件中的一个对象如果能保证能完成自己职能范围内的各项任务,同时又不去理会与自己职能无关的其它任务,那么它就能够保证功能的相对独立性,也就可以脱离自己所处的环境而复用到其它环境中,这是一个具有内聚性的对象。
    3.可维护性和易变更性
    我们现在的软件是在不断变更的,这种变更不仅来自于我们的客户,更来自于我们的市场。如果我们的软件通过变更能及时适应我们的市场需求,我们就可以在市场竞争中获胜。怎样能及时变更以适应我们的市场呢,就是通过调整软件的结构,使我们每次的变更付出的代价最小,耗费的人力最小,这种变更才最快最经济。
    高内聚的软件,每个系统、模块、类的任务都高度相关,就使每一次的变更涉及的范围缩小到最小。比如评审表发生了变更,只会与评审表对象有关,我们不会去更改其它的对象。如果我们能做到这一点,我们的系统当然是可维护性好、易变更性好的系统。
    简单的总结下:
    1、耦合、内聚的评估标准是强度,耦合越弱越好,内聚越强越好;
    2、所谓过度指的是由于错误理解导致的效果相反的设计;
    3、耦合指的模块之间的关系,最弱的耦合设计是通过一个主控模块来协调n个模块之间的运作。还是举一个我举过的例子:客户要求在界面上增加一个字段,你的项目要修改几个地方呢?如果你只要修改项目文档,那么你的开发构架就是最低强度的耦合,而这种设计成熟的开发团队都已经做到了,他们使用开发工具通过项目模型驱动数据库和各层次的代码,而不是直接修改那些代码;
    4、内聚指的是模块内部的功能,最强的内聚就是功能单一到不能拆分,也就是原子化,
    5、所以强内聚和弱耦合是相辅相成的,一个良好的设计是由若干个强内聚模块以弱耦合的方式组装起来的
    解耦合其实是程序员必备能力,但理解这个概念依然需要大量体系基础知识。对于想在计算机行业长期发展的朋友来说,夯实算法数据结构和计算机体系基础知识其实是非常非常重要的。
    基础往往决定了上层建筑,楼房再高,地基不稳最后也白搭。这些基础知识包括:算法、计算机网络、计算机组成原理、计算机编译原理、操作系统、数据库等等。
    要想进大厂先从刷算法做起是个好方法,算法厉害的人进大厂非常容易,这里送一本阿里P8撰写的算法刷题笔记,身边不少朋友通过它加入大厂:
    祝大家前程似锦,在编码的道路上一马平川。
    要是觉得不错的话,那就帮我
    @findyi
    点个赞,一键三连呗,硬核码字不易。

四、程序设计经常提到的解耦,到底是要解除什么之间的耦合?

    但凡是做企业级的软件,低耦合高内聚都是金标准。
    先用两张图说明下到底是解除什么之间的耦合:
    高耦合低内聚
    低耦合高内聚
    你觉得哪个好?
    先说说低耦合:
    这个词相信大家已经耳熟能详,我们在看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.合理的职责划分
    合理的职责划分,让系统中的对象各司其职,不仅是提高内聚的要求,同时也可以有效地降低耦合。
    3.使用接口而不是继承
    继承就是一种耦合。如果子类A继承了父类B,不论是直接或间接的继承,子类A都必将依赖父类B。子类A必须使用在存在父类B的环境中,父类B不存在子类A就不能使用,这样将影响子类A的可移植性。
    一旦父类B发生任何变更,更改或去掉一个函数名,或者改变一个函数的参数,都将导致子类A不得不变更,甚至重写。假如父类B的子类数十上百个,甚至贯穿这个项目各个模块,这样的变更是灾难性的。
    “低耦合”给软件项目带来的优点是:易于变更、易于重用。
    再说说高内聚
    高内聚是另一个普遍用来评判软件设计质量的标准。内聚,更为专业的说法叫功能内聚,是对软件系统中元素职责相关性和集中度的度量。如果元素具有高度相关的职责,除了这些职责内的任务,没有其它过多的工作,那么该元素就具有高内聚性,反之则为低内聚性。高内聚要求软件系统中的各个元素具有较高的协作性,因为在我们在完成软件需求中的一个功能,可能需要做各种事情,但是具有高内聚性的一个元素,只完成它职责内的事情,而把那些不在它职责内的事情拿去请求别人来完成。
    1.可读性
    如果一段程序条理非常清晰,每个类通过名称或说明都能清楚明白它的意义,类的每个属性、函数也都是易于理解的它所应当完成的任务和行为,这段程序的可读性必然提高。在软件产业越来越密集,软件产业中开发人员协作越来越紧密、分工越来越细的今天,软件可读性的要求相信也越来越为人们所重视。
    2.复用性
    在软件开发中,最低等级的复用是代码拷贝,然后是函数的复用、对象的复用、组件的复用。软件开发中最懒的人是最聪明的人,他们总是想到复用。在代码编写的时候突然发现某个功能是曾经实现过的功能,直接把它拷贝过来就ok了。如果这段代码在同一个对象中,那么就提出来写一个函数到处调用就行了。如果不是在同一个对象中呢,就将其抽象成一个对象到处调用吧。如果不在一个项目中呢,那就做成组件给各个项目引用吧。
    代码复用也使我们的代码在复用的过程中不断精化、不断健壮、提高代码质量。代码的复用的确给我们的开发带来了不少便利,但是一段代码能否在各个需要的地方都能复用呢?这给我们的软件开发质量提出了新的要求:好的代码可以复用,不好的则不行。软件中的一个对象如果能保证能完成自己职能范围内的各项任务,同时又不去理会与自己职能无关的其它任务,那么它就能够保证功能的相对独立性,也就可以脱离自己所处的环境而复用到其它环境中,这是一个具有内聚性的对象。
    3.可维护性和易变更性
    我们现在的软件是在不断变更的,这种变更不仅来自于我们的客户,更来自于我们的市场。如果我们的软件通过变更能及时适应我们的市场需求,我们就可以在市场竞争中获胜。怎样能及时变更以适应我们的市场呢,就是通过调整软件的结构,使我们每次的变更付出的代价最小,耗费的人力最小,这种变更才最快最经济。
    高内聚的软件,每个系统、模块、类的任务都高度相关,就使每一次的变更涉及的范围缩小到最小。比如评审表发生了变更,只会与评审表对象有关,我们不会去更改其它的对象。如果我们能做到这一点,我们的系统当然是可维护性好、易变更性好的系统。
    简单的总结下:
    1、耦合、内聚的评估标准是强度,耦合越弱越好,内聚越强越好;
    2、所谓过度指的是由于错误理解导致的效果相反的设计;
    3、耦合指的模块之间的关系,最弱的耦合设计是通过一个主控模块来协调n个模块之间的运作。还是举一个我举过的例子:客户要求在界面上增加一个字段,你的项目要修改几个地方呢?如果你只要修改项目文档,那么你的开发构架就是最低强度的耦合,而这种设计成熟的开发团队都已经做到了,他们使用开发工具通过项目模型驱动数据库和各层次的代码,而不是直接修改那些代码;
    4、内聚指的是模块内部的功能,最强的内聚就是功能单一到不能拆分,也就是原子化,
    5、所以强内聚和弱耦合是相辅相成的,一个良好的设计是由若干个强内聚模块以弱耦合的方式组装起来的
    解耦合其实是程序员必备能力,但理解这个概念依然需要大量体系基础知识。对于想在计算机行业长期发展的朋友来说,夯实算法数据结构和计算机体系基础知识其实是非常非常重要的。
    基础往往决定了上层建筑,楼房再高,地基不稳最后也白搭。这些基础知识包括:算法、计算机网络、计算机组成原理、计算机编译原理、操作系统、数据库等等。
    要想进大厂先从刷算法做起是个好方法,算法厉害的人进大厂非常容易,这里送一本阿里P8撰写的算法刷题笔记,身边不少朋友通过它加入大厂:
    祝大家前程似锦,在编码的道路上一马平川。
    要是觉得不错的话,那就帮我
    @findyi
    点个赞,一键三连呗,硬核码字不易。

免责声明:本站部分内容转载于网络,其中内容仅代表作者个人观点,与本网无关。其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。若有来源标注错误或侵犯了您的合法权益,请作者持权属证明与本网联系,我们将及时更正、删除,谢谢。

本站联系邮箱:douxingdu02@163.co m