首页 > 其他分享 >【架构设计】如何让你的应用做到高内聚、低耦合?

【架构设计】如何让你的应用做到高内聚、低耦合?

时间:2023-01-06 14:02:23浏览次数:42  
标签:架构设计 功能 依赖 代码 模块 内聚 耦合

前言

最近review公司的代码,发现代码耦合程度特别高,修改一处,不知不觉就把其他地方影响到了,这就让我思考该如何让我们写的代码足够内聚,减少耦合呢?

"高内聚、松耦合"是一个非常重要的设计思想,能够有效地提高代码的可读性和可维护性,缩小功能改动导致的代码改动范围。它可以用来指导不同粒度代码的设计与开发,比如系统、模块、类,甚至是函数,也可以应用到不同的开发场景中,比如微服务、框架、组件、类库等。本文我们来探讨下如何让我们的应用做到高内聚、低耦合。

欢迎关注个人公众号『JAVA旭阳』交流沟通

什么是高内聚?

首先我们将目光投射到内聚上,通常我们的代码的内聚归为7类,如下图所示,内聚性从高到低。

  1. 功能内聚

将相同功能放到一个类或者模块中,内聚程度最高。

  1. 顺序内聚

如果一个功能的输出是另外一个功能的输入,这种存在顺序依赖关系的,我们将他们归到一个模块中叫做顺序内聚。

  1. 通信内聚

如果功能点使用相同输入或输出数据,我们将他们内聚到一个模块中,叫做通信内聚。

  1. 过程内聚

如果不同的功能是由同一个控制流支配的,我们称作过程内聚。

  1. 时间内聚

不同的功能在同一时间段内执行,比如银行不同的跑批任务,由时间去控制是否放在同一个模块中的内聚叫做时间内聚。

  1. 逻辑内聚

不同的功能可能他们内部的逻辑是一致的,我们将他归在一起叫做逻辑内聚。

  1. 偶然内聚

而偶然内聚是指不同的功能,没什么关联就直接放在一起了。这种情况很常见,比如A团队同时承担了支付、物流、产品等功能的开发,为了节省开发资源,他们就把不相干的功能放到一个模块中,那么这种偶然内聚会随着业务发展遇到各种问题。

上面讲解了内聚的可能7种分类,大家不用太较真,了解一下就行。

小结一下,我们所说的高内聚,其实是用来指导类或者模块本身的设计,简单来说,就是指相近的功能应该放到同一个类中,不相近的功能不要放到同一个类中。相近的功能往往会被同时修改,放到同一个类中,修改会比较集中,代码容易维护。

什么是低耦合?

现在我们聚焦到耦合上,耦合实际上关注在类与类之间或者模块与模块之间依赖关系的设计,我们通常有下面7种类型的耦合关系。

  1. 非直接耦合

两个模块之间没有直接关系,模块独立性最强

  1. 数据耦合

两个模块之间用参数传递关联,模块之间影响最小的耦合关系。比如订单系统输入物流编号ID,物流系统返回你具体的物流信息。

  1. 标记耦合

两个模块依赖同样的一个数据结构,传递的是数据结构。

比如租房费用计算系统,需要计算水费和电费,如果你传用户信息这个数据结构,让水费和电费系统领取用户对象的用水量和用电量,这就是标记耦合。更好的做法应该只需要传必要的用水量和用电量,而不是传输整个用户对象。

  1. 控制耦合

两个模块之间传输控制信息,比如某个标志或者开关,调用模块需要知道被调用模块的内部逻辑,增加了相互依赖和理解的复杂度。

  1. 外部耦合

一组模块需要与外部环境关联,这组模块访问同一全局变量,外部耦合有时候必不可少,但应尽量减少此类模块数量。

  1. 公共耦合

一组模块均访问同一全局数据区,这种情况叫做公共耦合。比如有一个公共变量,不同模块都去修改它。

  1. 内容耦合

一个模块直接操作或修改另外一个模块的内部书,一个模块不通过正常入口访问另外一个模块,这就是内容耦合,是最糟糕的情况,需要避免。比如直接调用另外一个类的set方法,所以这就要求我们不要无脑的把类的任何属性都加上set方法。

上面大致分享了耦合的7种情况,你们项目属于哪种情况呢?

这边再总结一下, 所谓低耦合是说,在代码中,类与类之间的依赖关系简单清晰。即使两个类有依赖关系,一个类的代码改动不会或者很少导致依赖类的代码改动。

高内聚,低耦合有什么关系?

前面讲解了内聚和耦合的多种情况,那么高内聚、低耦合之间有什么关系呢?

上图中左边部分的代码设计中,类的粒度比较小,每个类的职责都比较单一。相近的功能都放到了一个类中,不相近的功能被分割到了多个类中。这样类更加独立,代码的内聚性更好。一个类的修改,只会影响到一个依赖类的代码改动。我们只需要测试这一个依赖类是否还能正常工作就行了。

上图中右边部分的代码设计中,类粒度比较大,低内聚,功能大而全,不相近的功能放到了一个类中。这就导致很多其他类都依赖这个类。当我们修改这个类的某一个功能代码的时候,会影响依赖它的多个类。我们需要测试这三个依赖类,是否还能正常工作。

所以说, “高内聚”有助于“松耦合”,同理,“低内聚”也会导致“紧耦合”

如何做到高内聚、低耦合呢?

关于如何做到模块或者类的高内聚、低耦合,有一个很经典的指导法则,那就是迪米特法则

迪米特法则是说不该有直接依赖关系的类之间,不要有依赖;有依赖关系的类之间,尽量只依赖必要的接口。换更形象点的说,每个模块只和自己的朋友“说话”(talk),不和陌生人“说话”(talk)。

展开来讲,我们在做设计的时候特别关注下面的一些要点。

  1. 多用接口隐藏实现的细节, 接口是一个契约,相对稳定。
  2. 尽量避免不同模块或者类之间共享全局变量,万一一个地方需要修改,连带的其他模块也会影响
  3. 能用private的地方,坚决不用public, 不要给类的任何属性都加set方法,体现良好的封装性,暴露越少,影响也就越少。
  4. 合理使用设计模式,因为设计模式会很好的保证代码的可扩展性、封装性
  5. 注意分层设计和调用,比如在业务层直接用SQL语句操作数据库,而应该讲数据库操作封装到DAO层中,业务层调用DAO层
  6. 避免直接操作或者调用其他模块或类(内容耦合),也就是直接调用set方法,而是应该通过接口调用
  7. 尽量使用数据耦合,少用控制耦合。比如传输一个普通的数据变量是合适的。但传输一个控制命令给你,让你去执行分支a还是分支b还是分支c,这就不是很合适,所以尽量采用一些其他的方法来规避掉这些控制命令的发送。
  8. 模块的功能划分尽可能的单一, 遵循单一职责原则
  9. 模块只堆外暴露最小限度的接口,遵循接口隔离原则
  10. 模块之间的交互要尽量少,接口的设计要尽量简单,比如能传基本类类型就不要传输整个对象。

总结

“高内聚、松耦合”是一个非常重要的设计思想,能够有效提高代码的可读性和可维护性,缩小功能改动导致的代码改动范围。“高内聚”用来指导类本身的设计,“松耦合”用来指导类与类之间依赖关系的设计。

所谓高内聚,就是指相近的功能应该放到同一个类中,不相近的功能不要放到同一类中。相近的功能往往会被同时修改,放到同一个类中,修改会比较集中。所谓松耦合指的是,在代码中,类与类之间的依赖关系简单清晰。即使两个类有依赖关系,一个类的代码改动也不会或者很少导致依赖类的代码改动。

所以我们在设计的时候,尽量要多动动脑子,想想这个功能是不是属于这个模块的呢?他们之间的交互合理吗?复杂吗?有没有更简单的方式呢?多问自己几个问题,你做出的设计会越来越优秀。

欢迎关注个人公众号『JAVA旭阳』交流沟通

标签:架构设计,功能,依赖,代码,模块,内聚,耦合
From: https://www.cnblogs.com/alvinscript/p/17030224.html

相关文章

  • SimpleAdmin系统教程之:项目架构设计
    一、说明本章主要介绍的是SimpleAdmin后端架构设计,作为一个系统的基石,一个好的架构设计可以让开发者在开发中少走很多弯路。在写SimpleAdmin这个系统之前,也用过一些其他的......
  • 物联网移动APP架构设计
    Android系统架构应用层SMS短信客户端程序、电话拨号程序、图片浏览器、Web浏览器等。这些应用程序都是用Java语言编写的,并且都是可以被开发人员开发的其他应用程序所替换应......
  • 【架构设计】你的应用该如何分层呢?
    前言最近review公司的代码,发现现在整个代码层级十分混乱,一个service类的长度甚至达到了5000多行。而且各种分层模型DTO、VO乱用,最终出现逻辑不清晰、各模块相互依赖、代......
  • Netty-架构设计及入门程序-3
    一、原生NIO存在的问题1、NIO的类库和API繁杂,使用麻烦:需要熟练掌握Selector、ServerSocketChannel、SocketChannel、ByteBuffer等。2、需要具备其他的额外技能:要熟......
  • 5-1 脚手架创建项目流程架构设计
    1一周导读1.1标题完成imooc-cli脚手架创建项目流程开发1.2将收获什么命令行交互方法服务端框架eggjs的应用和API开发方法eggjs集成云mongodb1.3主......
  • SaaS架构:中央库存系统架构设计
    近年来,越来越多的零售企业大力发展全渠道业务。在销售额增长方面,通过线上的小程序、直播、平台渠道等方式,拓展流量变现渠道;在会员增长方面,通过各种各样的互动方式,全渠......
  • SaaS架构:多租户系统架构设计
    一、什么是多租户?多租户技术是一种软件架构技术,它是在探讨与实现如何于多用户的环境下共用相同的系统或程序组件,并且仍可确保各用户间数据的隔离性。它是为共用的数......
  • 【架构设计】保持简单轻量设计的三个原则——DRY,KISS, YAGNI
    前言一个软件轻量简单的软件架构是非常重要的,它可以让我们花最小的代价就能满足业务上的需求。那如何保证轻量简单呢?那今天就和大家分享下这其中的秘密,也就是3个重要的指......
  • 5分钟了解系统架构设计(3)
    最近梳理了之前学习的架构设计相关的一些课程学习总结,将其整理成了一个大纲脑图,以每篇5分钟系列展现出来,希望对你有所帮助。本篇,我们聚焦如何在面试中回答架构设计。其......
  • 如何降低类之间的耦合
    最近在写人员信息管理的程序,用Java实现,第一次CC完,我就写了一个类和一个test类Tmis.java,只是实现了功能,却没有用OO的思想,代码重用几乎不可能,第二次CC完,类分为了Tmis.java,Emp......