学习java和k8s时发现他们的概念有共性,觉得比较有意思记录一下.
只是由技术引发的乱七八糟的想法,和具体技术没有太大关系,写着玩 (#^.^#)
延展思考后,提炼出四个关键词,先概述下,后面分别详述:
1.抽象: 代码解决了很多重复性的工作,能够实现去重的基础就是从千奇百怪的具象事物中抽象出共有的规律,抽象出不变的规律,以不变应万变.我这里对于抽象的理解是,它是对真实世界的 "分组" / "分类".
2.解耦: 我理解为"如何"去"分组",选择合适的方式,可以实现最大程度的复用.
3.粒度: 即颗粒度,我理解为"分组"的"大小"控制到何种程度.
4.关系: 真实世界被自己以 "某种方式" 细分到 "一定大小" 的 "分组" ,需要通过对于他们关系的描述,重新组成有机的整体.
从1到4的过程有点天下大势,合久必分,分久必合的感觉.
抽象是"分",解耦是如何"分",粒度是"分"到什么程度,关系是"合".
具体解释:
1.抽象:
Java有一句:万事万物皆对象
k8s同理:万事万物皆资源
他们的模式都是定义xxx类(Java)/xxx资源类型(k8s),有了类/类型,就可以据此创建出无数实例,比如定义学生类,然后new 无数个学生对象.
所以我把面向对象的抽象方法,理解为对真实世界的概念进行分组
比如把世界中的学生都划分到A组,称为学生类,任意一个学生都属于A组.
但世界不是泾渭分明的,一个人既可以是学生,也可以是别人的老师,分组是任意的,可交叠的
而以下图的方式才能真正表现出分组的任意性,世界本身就是混乱的,可以从不同的角度去理解,我可以框选任意范围作为一个分组
所以面向对象的抽象就是对世界进行任意的分组.
2. 解耦
刚接触解耦的概念时,我是困惑的,比如本来A模块调用B模块,A与B耦合.
如果加入中间件C,A调用C,C调用B,突然就说A和B解耦了,我第一反应是A和C耦合,C和B耦合,那么A和B难道不是耦合的吗?
但耦合不是等式,不能这样传递,以下图为例:A耦合B,B发生变化,那么A也受影响.
如果加入C作为桥梁,即使B变化了,只需要调整C和B的耦合关系,A和C的耦合可以保持不变,也就意味着A不需要变化.
java中的JDBC屏蔽数据库差异,k8s的PV屏蔽掉具体存储载体的差异,都是承担C的角色,可以让成型的代码主体A不用变化.
这正是我把"解耦"理解为"如何"分组的原因,本来是把事物分成两组即可描述清楚,现在要分成三组才能描述清楚,但分成三组时A更具通用性(因为它可以保持不变).
3. 粒度
沿用上图的概念就是框选范围的大小,拆分的越细,可控性越强,但粒度不是越细越好,合适是最重要的.
合适的粒度是:用斧头砍木头,用雕刻刀在米粒上雕花
粒度过大: 斧头雕花,没有那个操作精度,无法操作
粒度过小: 雕刻刀砍木头,累死你
对于"解耦"我理解为"如何分组",这里当然你也可以将"粒度"控制也强行理解为"如何分组"
但我更想表达的是,解耦是在决定以何种角度拆分事物,粒度是将事物拆分到何种程度.
他们的概念虽然可以相互转化,但还是略有不同.
4.关系
通过前三步,已经找到一种合适角度对事物分组并且分组的大小也刚好合适(这个答案往往并不是唯一的),现在已经以面向对象的方式对真实世界进行了映射,世界是有机的整体,而被我们拆分的事物,就是通过"关系"的描述重组成有机整体.
我们常说关系有三种:1对1,1对多,多对多
最具普适性的是多对多关系,因为可以说,1对多是特殊的多对多关系,而1对1是特殊的1对多关系.
但我惯用的思路是,关系只有一种: 1对多关系
因为1对1是特殊的1对多关系,而我舍弃多对多关系,是因为我往往需要从一个出发点去看待事物.
倘若有两个分组:A组 和 B组 (注意这是指被抽象出来的两大分组,每个组中都可以有无数实例)
1. 假设A和B是一对一关系,一个A实例对应一个B实例,可以理解成一个A实例可以对应多个B实例,但是B此时只有一个而已.
2. 假设A和B是多对多关系,那么对A而言,一个A实例可以对应多个B实例,此时只体现A与B的一对多关系. 他们多对多关系体现在:于此同时,一个B实例可以对应多个A实例,而这对于A而言是不用感知的.
以数据库联表查询为例,单次的联表查询其实只有一对多关系,首先1对1是特殊的1对多,不多解释,而查询的时候总是有一张表是概念上的[主表], [其它的表]都是这个概念上的主表的附属.
即使[主表] 和 [其它的表]是多对多的关系,由于确定了[主表], [主表]是基点,对于它而言,[主表]和[其它的表]的关系永远是一对多.
既然确定了谁是主表,一切都要从它的角度出发去看,永远看不到[其它的表]和[主表]的一对多关系,所以多对多关系永远得不到体现.
正如我们都是从自己的角度去看世界,有点"我"外无物的意味