`
fangang
  • 浏览: 867200 次
  • 性别: Icon_minigender_1
  • 来自: 北京
博客专栏
311c4c32-b171-3767-b974-d26acf661fb2
谈谈用例模型的那些事儿
浏览量:38039
767c50c5-189c-3525-a93f-5884d146ee78
一次迭代式开发的研究
浏览量:68455
03a3e133-6080-3bc8-a960-9d915ed9eabc
我们应当怎样做需求分析
浏览量:407952
753f3c56-c831-3add-ba41-b3b70d6d913f
重构,是这样干的
浏览量:87049
社区版块
存档分类
最新评论

(原创)一个优秀软件开发人员的必修课:GRASP(2)低耦合

阅读更多

我偶然在google或yahoo这样的搜索引擎搜索GRASP发现,除了国外的网站,国内网站多介绍和讨论GoF而很少介绍GRASP,即使这少量的文章也讲解非常粗略。个人认为作为优秀的开发人员,理解GRASP比GoF更重要,故写此文章。前面我在原创)一个优秀软件开发人员的必修课:GRASP软件开发模式浅析中介绍了使用GRASP的目的,今天允许我调换一下顺序,先从低耦合讲起,因为诸如创建者模式、信息专家模式的根本目的就是降低耦合。

1.低耦合(Low Coupling

“低耦合”这个词相信大家已经耳熟能详,我们在看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那里得到值对象。至于用OracleMySQL还是SQL Server,如何执行的操作,与我无关。

但是,作为优秀的开发人员,仅仅依靠框架提供的降低软件耦合的方法是远远不够的。根据我的经验,以下一些问题我们应当引起注意:

1)根据可能的变化设计软件

我们采用职责驱动设计,设计中尽力做到“低耦合、高内聚”的一个非常重要的前提是,我们的软件是在不断变化的。如果没有变化我们当然就不用这么费劲了;但是如果有变化,我们希望通过以上的设计,使我们在适应或者更改这样的变化的时候,付出更小的代价。这里提供了一个非常重要的信息是,我们努力降低耦合的是那些可能发生变更的地方,因为降低耦合是有代价的,是以增加资源耗费和代码复杂度为代价的。如果系统中某些元素不太可能变更,或者降低耦合所付出的代价太大,我们当然就应当选择耦合。有一次我试图将我的表现层不依赖于struts,但发现这样的尝试代价太大而失去意义了。对于软件可能变更的部分,我们应当努力去降低耦合,这就给我们提出一个要求是,在软件设计的时候可以预判日后的变化。根据以往的经验我认为,一个软件的业务逻辑和采用的技术框架往往是容易变化的2个方面。客户需求变更是我们软件设计必须考虑的问题。在RUP的开发过程中,为什么需要将分析设计的过程分为分析模型和设计模型,愚以为,从分析模型到设计模型的过程实际上是系统从满足直接的客户需求到优化系统结构、适应可预见的客户需求变更的一个过程。这种客户需求的变更不仅仅指对一个客户需求的变更,更是指我们的软件从适应一个客户需求到适应更多客户需求的过程。另一个方面,现在技术变更之快,EJBhibernatespringajax,一个一个的技术像走马灯一样从我们脑海中滑过,我们真不知道明天我在用什么。在这样的情况下,适应变化就是我们最佳的选择。

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的子类数十上百个,甚至贯穿这个项目各个模块,这样的变更是灾难性的。这种情况最典型的例子是我们现在使用hibernatespring设计DAO对象的方式,具体的描述参见我写的《如何在struts + spring + hibernate的框架下构建低耦合高内聚的软件结构》一文。

总之,“低耦合”给软件项目带来的优点是:易于变更、易于重用。

  • 大小: 21.4 KB
分享到:
评论
10 楼 JavaVM 2007-05-14  
期待你的《“单例”改变了我们的设计模式》
9 楼 fangang 2007-05-14  
谢谢Uranus的支持,实际上我们学习设计模式就是要思考它为什么好,我们为什么要用它,它还有没有问题需要修改。最近我正在着手写《“单例”改变了我们的设计模式》,详细描述在单例模式大行其道的今天,GoF中的许多模式都需要改改了。至于你的那个问题,我已经写到我的博客《设计模式GRASP和GoF是怎样解决耦合的问题》中了。
8 楼 jameswei 2007-05-12  
受教了.
7 楼 Uranus 2007-05-11  
对了,我还想请教你一个问题呢,我之前听一个人说过,不管是gof的设计模式还是GRASP设计模式,最终的目的就是解耦合,不知道你怎么看这句话的,是否可以据个例子?
6 楼 Uranus 2007-05-11  
说真的,我觉得你这篇文章才是写得最好的(和你的create模式相比,因为create模式中,你可能脑子很清楚,但是写的语句让初学者很摸不到头脑),我个人感觉好像设计模式都是国外人的提出来我们用,我们就缺乏提出思想的人,我们好多同志都是看这个好就拿过来用,根本说不出好在哪。你这个能力很强,希望将来在你的文章里面能多看到这种模式这样做的理由是什么
5 楼 hellovalue 2007-01-24  
               
4 楼 fangang 2007-01-22  
daoger 写道
文章很好,地方不对!
发在敏捷开发板块才合适!
谢谢指教
3 楼 daoger 2007-01-22  
文章很好,地方不对!
发在敏捷开发板块才合适!
2 楼 fangang 2007-01-22  
是的,正因为它的重要,我希望通过这篇文章,提供一个话题,大家都谈谈这方面的体会,共同进步
1 楼 silentlakeside 2007-01-22  
支持一下,我也觉得GRASP很重要,我是在《应用UML与模式》这一书中看到GRASP,从此后我的设计思路基本上就是参照这几个原则了。我觉得很多设计模式都是从GRASP发展而来。

相关推荐

    GRASP模式简介

    低耦合度或低耦合模式的核心思想是在分配一个职责时要使保持低耦合度。耦合度是一个类与其它类关联、知道其他类的信息或者依赖其他类的强弱程度的度量。一个具有低(弱)耦合度的类不依赖于太多的其他类。 5. 控制...

    对grasp的理解和应用

    GRASP(General Responsibility Assignment Software Patterns)是一套面向对象设计的原则,用于指导软件开发中的职责分配。这个概念在软件工程中至关重要,特别是在UML(统一建模语言)和软件建模中,因为它帮助...

    GRASP\GRASP_source.rar

    GRASP,全称为“贪婪搜索法的粗糙集理论应用”(Greedily Refined Search Algorithm using a Perturbation Heuristic),是一种在计算机科学和人工智能领域中常见的优化算法。它主要用于解决组合优化问题,如旅行商...

    OOD原则 GRASP GOF

    这意味着每个类都应有一个明确且单一的职责,避免职责混杂导致代码耦合度过高。 2. **开闭原则(Open-Closed Principle, OCP)**: 类应该是对扩展开放的,对修改关闭的。当需要增加新功能时,可以通过扩展已有类...

    软件需求分析英文课件:Chap 7-GRASP.ppt

    软件需求分析英文课件:Chap 7-GRASP.ppt

    软件开发设计原则软件开发设计原则

    - 一个软件实体(类、模块、函数等)应该是对扩展开放,对修改关闭。这意味着当需要新增功能时,应尽量通过扩展已有代码,而不是修改已有的代码来实现。 3. **里氏替换原则(Liskov Substitution Principle, LSP)...

    java\软件设计中的原则(GRASP)

    7. 纯虚构(Pure Fabrication):当需要为某项任务创建一个单独的类,但又不想增加原有类的耦合度时,可以创建一个纯虚构类。例如,为了数据库交互而创建一个独立的数据访问对象。 8. 中介者(Mediator):中介者...

    软件需求分析英文课件:Chap 9-Iteration 2--More GRASP.ppt

    软件需求分析英文课件:Chap 9-Iteration 2--More GRASP.ppt

    GRASP10[1].3.0培训教程(公开).pdf

    每一个实例都详细介绍了如何建立几何形状、进行分析和查看结果,最终通过仿真的方式来预测天线的辐射特性。 GRASP10培训教程还涉及了软件中的3D视图设置,这允许用户直观地观察和分析天线的三维几何结构以及电磁场...

    meta_version2.rar_grasp_orienteering_orienteering problem

    本项目提供的"meta_version2.rar"压缩包文件包含了一个实现GRASP(Greedy Randomized Adaptive Search Procedure)算法的代码,用于解决定向越野问题。GRASP是一种基于贪婪策略的启发式算法,它结合了随机化和局部...

    软件需求分析课件:Chap 7-GRASP.ppt

    总之,GRASP作为面向对象设计的一个关键工具,能够帮助开发者在软件需求分析阶段更有效地构建对象模型,明确对象职责,优化系统结构,提升代码质量。通过理解和应用GRASP原则,开发者可以创建出更稳定、可维护和易于...

    软件需求分析课件:Chap 9-Iteration 2--More GRASP.ppt

    《软件需求分析课件:Chap 9-Iteration 2--More GRASP.ppt》主要探讨了在软件开发过程中的迭代二(Elaboration Iteration 2)阶段,特别是关于对象设计模式、GRASP(一般职责分配原则,General Responsibility ...

    UML-GRASP模式简述

    3. 低耦合(Low Coupling)模式:在分配一个职责时要保持低耦合度。 4. 高内聚(High Cohesion)模式:分配一个职责的时候要保持类的高聚合度。 5. 控制者(Controller)模式:将处理系统事件消息的职责分派给代表...

    论文研究-H-GRASP:一种基于GRASP改进的混合SAT解法器.pdf

    为了改善GRASP的局限性,提出了一种能解决含有伪布尔(PB)和合取范式(CNF)混合约束问题的新的混合算法(H-GRASP)。该新算法采用了切削平面技术来提取PB约束条件之间的推论,并把它结合到普通的蕴涵图中,分析...

    panda_grasp_sim_2-main.zip

    总之,Panda Grasp Simulator 2是一个强大且实用的工具,它为Panda机械臂的使用者提供了丰富的学习和研究资源。通过对这款仿真器的深入理解和应用,我们可以更好地理解和掌握机械臂的相关技术,推动自动化领域的创新...

    grasp:Grasp 是通用核心教室的开源 LMS

    Grasp 是一个用于公共核心课堂的开源学习管理系统。 Grasp 的主要目标是利用技术无缝融入课堂并改善师生之间的交流。入门先决条件带有 Rails 的 Ruby 2.0+ Ruby 和 PhantomJS 的安装超出了本自述文件的范围。依赖...

Global site tag (gtag.js) - Google Analytics