稳定依赖原则

“依赖方向应指向稳定方”

有的开发者写代码前会画图,有的开发者则不会。

但不管画不画图,其实多数开发者并不知道画图能为开发提供什么帮助。

​今天这篇文章,会聊一聊画图对开发的一些支持作用。

本篇文章适合以下小伙伴们观看:

  • 看不懂UML类图
  • 不知道画图对写代码有什么好处

好了,前言到此为止,正文开始!

依赖与稳定依赖

其实提到依赖,最常见的是UML图中的类图。

类图中充满了”依赖“这个词。

关于“依赖”的类图大概是这样:
在这里插入图片描述
简单解释一下图中的符号含义:

  • 加号/减号:代表访问控制标识符。简单点说:加号相当于public,减号相当于private。
  • 虚线和箭头:代表依赖和依赖方向。图中意为A依赖B。依赖原因是A中的method2使用了B作为返回值,所以依赖了B。

这是在UML类图中的“依赖”。

我在这里聊的“依赖”范围更广一些,最起码类图中的各种关系线条都称作依赖。

比如:
在这里插入图片描述
但其实它们对分析的作用都一样,都是只关注依赖方和被依赖方。

这里都做一个简化,画成这样:
在这里插入图片描述上图中意为A依赖B。用来概括上面那些各种类型的依赖。

现在,就要说它的用处了!注意看哦
在这里插入图片描述
现在有这么3个模块:A、B、C。

其中,A与C依赖B。

在开发中还是挺常见的吧?

emm,那现在思考一下,如果A、B、C分别发生了变化时,它们的影响范围分别是多少?

这里以影响的模块数量作为单位吧。比如,两个模块发生变化了,就标记为2。

先给个小提示:被依赖的模块变化时,依赖方的代码要不要调整呢?

写下来,或者画画图都可以(要不然反复思考和回忆还真挺累的)。

算好了吗?

我这里也画一下:
在这里插入图片描述
影响范围分别是:

  • A:1个模块(A本身)
  • B:3个模块(ABC)
  • C:1个模块(C本身)

发现了点东西吧?

B模块的变化影响了3个模块!这相当于几倍的A与C的影响范围了!

而且,图中举例的依赖方很少,如果依赖者更多,则带来的影响范围更可怕!

所以怎么样能降低影响呢?

有时候这个B还必须改(写完发现有谐音 哈哈哈)

那咱们就降低B模块的修改频度,必须改可以,但要少改,就少影响一点。

然后同时,把频繁变化的东西从B模块里面拿走(这个操作也称作分离变与不变)。

双管齐下,它就变成了低频度变化的模块。

然后,除了这个方法,剩下的就是文章标题:稳定依赖

就是说,依赖方向应指向稳定方。

它稳定了,就不容易变化。所以依赖它的那些模块也就不会频繁​受到它的影响,也就稳定多了。

这也是为什么要“稳定依赖”的原因。

小例子:接口的依赖方向为什么这样画?

在这里插入图片描述
接口和实现类的类图大概是这个样子的。

大家可能看过也可能没看过。

不过都没关系,我解释一下它的含义。

它表示:类AImpl 实现 接口A

大家可能也没有思考过为什么它长成这样(而不是反过来)。

也可能因为规定就这么画了:实现类指向接口,线型虚线+三角箭头。

但上面的文章中其实提到了这么做的关键。

这里停一下,想一想哈。

……

揭晓答案了:因为接口是被依赖方。一旦接口变化,实现类会受影响。

这也是有经验的开发者会经常说:接口不要随意变化。或者他们不说话,但做接口设计时,尽可能让接口稳定。

因为接口是被依赖方。而且同时被外部和内部依赖。

这里以web中的接口为例,会不会更好理解?

一个web接口的被依赖情况:

在这里插入图片描述
图中接口被多方依赖,所以接口一旦变化,影响范围就会很大。

影响传递

上面的图文看完了,应该对依赖和依赖方向比较熟悉了。

那现在聊聊影响传递。

现在有一个软件系统,它模块间的依赖方向是这样的:

在这里插入图片描述
图中,被点包起来的模块将会发生变化,让我们来看看影响情况

在这里插入图片描述
一点一点看哈,先看图例。白色方块代表未被影响的模块,黑色方块代表被影响的模块。

读图方向为从左到右。

从图中可以看到,影响是会传递的。最终甚至会传递到最上层(最远端)。

而且,一步一步的顺序图中可以看出:影响是沿着依赖箭头的反方向传递的。

那现在,你可能会有疑问了,影响传递威力这么大,那岂不是被依赖的底层永远都不能改了?

那当然也不是,下面让我们看看解决办法。

解决影响传递的方法:版本隔离

其实大家应该在开发中使用过这种解决方案。

比如,无论是node、maven,都会依赖指定版本号的模块(而不是任意版本)。

而且,如果是在多人协作的项目中,版本号一般是不允许随意修改的。

这其实是一种解决影响传递的方案。毕竟不变就不会被影响了嘛(笑)。

包括有些重要的接口,会有版本标记(比如v1、v2这种),其实道理也是一样的。

画图举例:

在这里插入图片描述
一样,先看图例:

  • 空心A:代表模块A的旧版本(V1)
  • 有颜色的A:代表模块A的新版本(V2)
  • 被圈上的空心A:代表模块A将会发生变化
  • 涂色的菱形:代表依赖A的新特性的模块

图中,新增的菱形模块依赖A的新特性。此时按理修改底层模块A一定会影响依赖它的很多模块。

为了消除影响传递带来的风险,这里使用版本隔离的方法解决问题。

新增了一个V2版本的模块,为菱形模块进行支持,新特性放在这里。

仍保留旧模块A的代码与功能。之前大块的功能都依赖旧A模块,这样旧A模块不变,就不会产生影响传递的效果。

所以就如图中一样:

在这里插入图片描述
依赖A模块的其他模块没被影响,而菱形模块也用到了A模块的新特性。

这样,既缩小了影响范围(V1),又用新特性支持了新模块(V2)。

那,此时完整的A模块在图中应该表述为:

在这里插入图片描述
即:它们两块(A模块的V1和V2版本)合起来,才是现在A模块的全部。

总结

​稳定依赖原则:依赖方向应该由不稳定指向稳定方(这样变更的影响范围更小)。

影响传递方向:变更的影响随着依赖方向反向传递。

​被依赖方可以使用版本隔离的方式来减小变更带来的影响范围。

内容还感兴趣吗?公众号中会有更多相关内容持续更新哦
在这里插入图片描述

  • 21
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值