组件设计原则和度量方法

在日常开发过程中,Spring、Dubbo、Mybatis等都是我们常用的开源框架。当你在使用这些框架时,不可避免需要通过分析源码来理解内部的实现原理。那么,你在翻阅源代码时,有没有想过这些框架的代码结构为什么要这样进行设计和实现呢?背后是否有一些组件设计的原则呢?这就是今天我们要讨论的话题。

我们知道,组件(Component)是设计和规划软件系统代码结构的基本单元,而在代码结构设计上最重要的关注点就是耦合(Coupling)度,用来处理组件与组件之间的关系。这里,我们以Dubbo框架为例进行切入并给出它的组件关系图。Dubbo框架的源码比较复杂,从顶层的代码结构进行梳理,我们可以得到这样的包结构图。


我们看到Dubbo在代码结构上一共包含common、remoting、rpc、cluster、registry、monitor、config和container等8大核心包,它们之间相互依赖构成一个整体。但这里的依赖关系并不是随意设计的,而是使用到了经典的组件设计原则(Component Design Principle)。

什么是组件设计原则?

组件设计原则有时候也称为分包(Package)原则。针对耦合度,在组件设计上包含以下三条设计原则: 

  1. 无环依赖原则

无环依赖原则的英文全称是Acyclic Dependencies Principle,它的含义很明确,就是说组件与组件之间的关联关系中不应该存在环状结构,我们要避免形成循环依赖。

  1. 稳定抽象原则

稳定抽象原则,即Stable Abstractions Principle。该原则认为如果一个组件是稳定的,那么它就应该是抽象的。反之,如果一个不稳定的组件中就不应该包含很多抽象的内容。

  1. 稳定依赖原则

稳定依赖原则,即Stable Dependencies Principle,强调的也是稳定性,认为组件与组件之间的依赖关系应该是有方向的,也就说一个组件只应该依赖于比它更稳定的组件,反之就是不合理的。

从原则的命名上我们也不难看出,组件耦合原则实际上更多关注的是稳定性(Stablility)。那么什么是稳定性呢?在软件系统中,如果某一个包被许多其他的软件包所依赖,也就是具有很多输入依赖关系的包就是稳定的,例如下图中的这个X组件。


而在下图中存在一个Y组件,但我们认为组件Y是不稳定的,因为Y没有被其他的组件所依赖,但Y自身依赖很多别的组件。


现实中的诸如Dubbo这种框架代码中的包结构通常比较复杂,可能很难找到这些一眼就能判断其稳定性的组件,这时候我们就需要借助一些量化标准来对包结构的稳定性进行衡量。让我们一起来看一下。

组件设计原则的度量方法

我们先来看看组件的稳定度如何进行度量,我们可以使用以下公式:

I = Ce / (Ca + Ce)

其中Ca代表向心耦合(Afferent Coupling),表示有多少个组件依赖与这个组件。而Ce代表离心耦合(Efferent Coupling),表示这个组件本身所依赖的组件数量。I代表Instability,即不稳定性,显然它的值处于[0,1]之间。

针对前面介绍的X和Y两个组件,我们可以使用该工作做一个简单计算。不难得出组件X的Ce=0,所以不稳定性I=0,说明它非常稳定。相反,组件Y的Ce=3,Ca=0,所以它的不稳定性I=1,说明它非常不稳定。

另一方面,组件的抽象度也同样存在类似的计算公式:

A = AC / CC

其中A代表抽象度(Abstractness)。AC(Abstract Class)表示组件中抽象类的数量,而CC(Concrete Class)表示组件中所有类的总和,这样通过对比AC和CC就能简单得出该组件的抽象度。

事实上,组件之间都存在一个依赖链,稳定性在该依赖链上具有传递性。下图展示的是一种更常见的场景,沿着依赖的方向,组件的不稳定性应该逐渐降低,稳定性应该逐渐升高。如果已经处于稳定状态的组件就不应该去依赖处于不稳定状态的组件。


另一方面,正如上图所展示的,大多数组件即具备一定的稳定性也表现出一定的抽象度。如果一个组件的稳定度和抽象度都是1,意味着该组件里面全是抽象类且没有任何组件依赖它,那么这个组件就没有任何用处。相反,如果一个组件稳定度和抽象度都是0,那么意味着这个组件不断在变化,不具备维护性,这也是我们不想设计的组件。所以,在稳定度和抽象度之间我们应该保持一种平衡,下图中中间的那个线就是平衡线。在有些资料中,这条平衡线有一个专业的名称,即主序列(Main Sequence),如下图所示。


我们用距离(Distance)的概念来量化这种平衡,距离的计算公式:

D = abs(1 - I - A) * sin(45)

距离的图形化表示参考下图。


通过这些度量方法,我们就可以全面分析组件的稳定度、抽象度以及与主序列之间的平衡关系。

讲到这里,你可能会问,如何能够有效计算出这些度量方法背后的具体量化数据呢?通过人工的方式进行计算显然不可行,这时候就需要引入一些专门的测量工具了。

组件设计原则的测量工具

这里介绍一款组件关系分析的利器:JDepend。JDepend是用来评价Java代码是否遵循组件设计原则的便捷工具,可以给出代码工程中包与包之间的依赖关系,并分析出每个包的稳定和抽象程度以及是否存在循环依赖等。这些指标与前面中介绍的组件设计量化标准保持一致。

使用JDepend时,我们一般加载它为Eclipse提供的插件。安装完JDepend插件之后,在Eclipse中会出现一个“Run JDepend Analysis”菜单。


直接执行命令,就可以得到JDepend的分析结果了。接下来,我们还是以Dubbo为例,来看一下该框架中位于整个依赖关系中心位置的dubbo.rpc,可以看到如下图所示的分析结果。


JDepend给出了四个子页面,分别是所选中的对象、存在循环依赖关系的包、多依赖的包和被依赖的包。从图中,我们看到具体类(CC)、抽象类(AC)、向心耦合(Ca)、离心耦合(Ec)、不稳定性(I)、抽象度(A)和距离(D)等组价设计原则中所介绍的指标数量,同时还使用“Cycle!”用来标识是否包结构是否存在循环依赖。当然,针对这些可视化界面,JDepend还提供了完整的文本结果描述。

同时,JDepend还为我们自动生成了主序列图以及各个包在该图中的分布情况。对于com.alibaba.dubbo.rpc包而言,得到的效果如下图。


在上图中,我们点击某个点,可以看到该点所代表的包结构中的不稳定性、抽象度和主序列之间的距离值。而图中所分布点分为三种颜色,绿色集中主序列线附件,代表在不稳定性和抽象度之间达成了比较好的一种平衡。黑色点位则相对差一下,如果红色点位,则表示设计上出现了问题,需要引起我们的注意。

可以说,任何组件的设计在耦合度上都不可能是完美的,对于复杂的系统而言尤其如此。因此,更多的时候,我们追求的是一种平衡性。组件设计原则为我们追求这种平衡性提供了很好的理论依据和量化标准,我们可以通过工具将这些理论依据和量化标准转化为工程实践,从而更好地指导我们的日常开发工作。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/3226628.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

桥联亲和素-标记生物素法(BRAB)

桥联亲和素-标记生物素法(BRAB)是一种基于生物素与亲和素(或链霉亲和素)之间高亲和力特性的生物医学检测方法。以下是关于BRAB法的详细解释: 一、定义与原理 BRAB法,也称为桥联亲和素-标记生物素法&#xf…

游戏AI的创造思路-技术基础-情感计算(1)

游戏中的AI也是可以和你打情感牌的哦,不要以为NPC是没有感情的,不过,不要和NPC打过多的情感牌,你会深陷其中无法自拔的~~~~~~ 目录 1. 情感计算算法定义 2. 发展历史 3. 公式和函数 3.1. 特征提取阶段 TF-IDF(词频…

如何监控 PostgreSQL 中表空间的使用情况并进行合理的管理?

文章目录 如何监控 PostgreSQL 中表空间的使用情况并进行合理的管理 一、引言 在 PostgreSQL 数据库中,表空间(Tablespace)是用于管理数据库对象存储位置的逻辑存储区域。有效地监控和管理表空间的使用情况对于确保数据库的性能、优化存储资…

为什么NAND Flash需要进行坏块管理而NOR Flash不需要呢?

NOR Flash和NAND Flash是两种不同类型的闪存技术,它们在存储单元的连接方式、耐用性、坏块管理等方面存在差异。 NOR Flash的存储单元是并联的,每个存储单元的字线和源线分别相连,这使得NOR Flash在读取速度上具有优势,适合用于执…

深度学习和NLP中的注意力和记忆

深度学习和NLP中的注意力和记忆 文章目录 一、说明二、注意力解决了什么问题?#三、关注的代价#四、机器翻译之外的关注#五、注意力(模糊)记忆?# 一、说明 深度学习的最新趋势是注意力机制。在一次采访中,现任 OpenAI 研…

玩鸣潮提示错误代码126:加载x3daudio1_7.dll失败无法打开的多个详细有效解决方法分享

玩游戏期间你是否也有遇到过找不到x3daudio1_7.dll无法继续执行代码打不开游戏?那么遇到这个问题要怎么办?有什么方法能解决?今天详细给大家介绍一下如何解决找不到x3daudio1_7.dll文件或x3daudio1_7.dll丢失的多个不同方法! 第一…

淘宝扭蛋机小程序:互联网下的潮玩新增速

近些年,潮玩成为了年轻一代的新宠,吸引了无数的年轻消费者,尤其是扭蛋机行业!扭蛋机具有价格低、商品丰富等特点,性价比非常高,受众群体遍布到了各个年龄层。扭蛋机商品具有非常高的观赏性和收藏性&#xf…

centos在GitHub上下载代码

1、安装git yum install -y git2、下载 git clone https://github.com/dji-sdk/Payload-SDK3、若遇到 centos 7 git clone 报错:fatal: unable to access解决方法: 3.1、 打开/etc/hosts文件;命令:sudo vim /etc/hosts 3.2、 添…

赋能数字安全新未来 | 湖南省“网安工匠”工业信息安全技能提升培训班圆满结束!

湖南省“网安工匠”工业信息安全技能提升培训班于7月9日在湖南邮电职业技术学院落下帷幕,该培训班由湖南省工业和信息化厅、湖南省通信管理局联合主办,湖南邮电职业技术学院、湖南会览网安教育服务有限公司承办,旨在深化工业信息安全技能&…

《Unpaired Unsupervised CT Metal ArtifactReduction》代码讲解

论文讲解见上篇博客 这篇论文的标题是《Unpaired Unsupervised CT Metal Artifact Reduction》,作者是Bo-Yuan Chen和Chu-Song Chen。这篇论文主要研究了如何使用深度学习技术来减少医学成像中由于金属植入物引起的CT图像伪影。 项目给出了几个不同的unet网…

美国商超入驻Homedepot,会成为传统家织厂家跨境赛道吗?

近年来,随着全球化步伐的加快和电子商务的蓬勃发展,越来越多的企业开始寻求跨境拓展的机会。在这样的背景下,美国知名的家居用品零售商超——Homedepot成为了许多国内外家织厂家关注的焦点。那么,美国商超入驻Homedepot究竟如何呢…

ArcGis将同一图层的多个面要素合并为一个面要素

这里写自定义目录标题 1.加载面要素的shp数据 2.点击菜单栏的地理处理–融合,如下所示: 3.将shp面要素输入,并设置输出,点击确定即可合并。合并后的属性表就只有一个数据了。

神经网络构成、优化、常用函数+激活函数

Iris分类 数据集介绍,共有数据150组,每组包括长宽等4个输入特征,同时给出输入特征对应的Iris类别,分别用0,1,2表示。 从sklearn包datasets读入数据集。 from sklearn import darasets from pandas impor…

Python 视频的色彩转换

这篇教学会介绍使用OpenCV 的cvtcolor() 方法,将视频的色彩模型从RGB 转换为灰阶、HLS、HSV...等。 因为程式中的OpenCV 会需要使用镜头或GPU,所以请使用本机环境( 参考:使用Python 虚拟环境) 或使用Anaconda Jupyter 进行实作( 参考&#x…

【数据结构】--- 堆

​ 个人主页:星纭-CSDN博客 系列文章专栏 :数据结构 踏上取经路,比抵达灵山更重要!一起努力一起进步! 目录 一.堆的介绍 二.堆的实现 1.向下调整算法 2.堆的创建 3.堆的实现 4.堆的初始化和销毁 5.堆的插入 5.1扩容…

Bad substitution 奇怪的问题

记得之前写过一篇文章是关于shell 脚本的,这里,当时的系统是 CentOS 的,最近公司把所有的服务器系统都更换为 Ubuntu 了, 结果以前写的那个脚本无法执行了,错误就是 Bad substitution,网上搜索基本都是 {}…

[C++初阶]list类的初步理解

一、标准库的list类 list的底层是一个带哨兵位的双向循环链表结构 对比forward_list的单链表结构,list的迭代器是一个双向迭代器 与vector等顺序结构的容器相比,list在任意位置进行插入删除的效率更好,但是不支持任意位置的随机访问 list是一…

【EIScopus稳检索-高录用】第五届大数据与社会科学国际学术会议(ICBDSS 2024)

大会官网:www.icbdss.org 大会时间:2024年8月16-18日 大会地点:中国-上海 接受/拒稿通知:投稿后1-2周内 收录检索:EI,Scopus *所有参会者现场均可获取参会证明,会议通知(邀请函)&…

二维码生成需知:名片二维码尺寸多少合适?电子名片二维码制作方法?

随着数字化时代的到来,二维码在各个领域的应用越来越广泛,名片作为商业交流的重要工具之一,也开始逐渐融入二维码的元素。通过在名片上添加二维码,我们可以轻松实现信息的快速传递和分享。然而,名片二维码的尺寸选择成…

【割点 C++BFS】2556. 二进制矩阵中翻转最多一次使路径不连通

本文涉及知识点 割点 图论知识汇总 CBFS算法 LeetCode2556. 二进制矩阵中翻转最多一次使路径不连通 给你一个下标从 0 开始的 m x n 二进制 矩阵 grid 。你可以从一个格子 (row, col) 移动到格子 (row 1, col) 或者 (row, col 1) ,前提是前往的格子值为 1 。如…