网站首页 > java教程 正文
我是架构精进之路,点击上方“关注”,坚持每天为你分享技术干货,私信我回复“01”,送你一份程序员成长进阶大礼包。
本文主要内容:
1、什么是组件?
组件是软件的部署单元,是整个软件系统在部署过程中可以独立完成部署的最小实体/最小单元。
具体的表现大概如下:
Java中,组件是jar文件,又称jar包
Ruby中,组件是gem文件
.Net中,组件是DLL文件
Python中,组件是一个可以import的Module
PHP中,组件是可以是Redis、Kafka等操作类的封装
什么样的组件是好的组件?
根据组件的定义,组件是整个软件系统在部署过程中可以独立完成部署的最小单元。从部署的角度上来说,多个组件可以链接成独立的可执行文件,也可以最总成部署单元,而单个组件也可以动态加载的插件形式来独立部署。
不论采用哪种形式,好的组件都应该永远保持可以被独立部署的特性,同时意味着组件应该可以被单独开发。
人们为了“偷懒”,为了减少源码合并和编译耗费的时间,而想出的一种东西。可以模块化编译、部署。
2、如何设计组件?
如果说类似SOLID这些编码设计原则,是用于指导我们如何用砖砌墙和盖房间,那么组件构建原则就是用来指导我们如何将这些房间组合成房子的。
用类组合一个组件的专业术语叫做:组件聚合。
2.1 组件聚合遵循的3个基本原则:
即用来决定什么样的类应该被组合成一个组件。
2.1.1 REP:复用/发布等同原则
软件复用的最小粒度应等同于其发布的最小粒度。直白地说,就是要复用一段代码就把它抽成组件。
该原则指导我们组件拆分的粒度。
2.1.2 CCP:共同闭包原则
为了相同目的而同时修改的类,应该放在同一个组件中。该原则指导我们组件拆分的粒度。
一个类不应该同时存在着多个变更原因,将所有可能会被一起修改的类(不论是在源码层面或者是抽象理念层有紧密关系的类)集中在一起,组成组件。由同一个原因引起的代码修改,最好在同一个组件中,如果分散在多个组件中,那么开发、提交、部署的成本都会上升。
CCP针对的就是可维护性。对大部分应用程序,可维护性的重要性要远远高于可复用性。
2.1.3 CRP:共同复用原则
不要强迫一个组件的用户依赖他们不需要的东西。
相信你一定有这种经历,集成了组件A,但组件A依赖了组件B、C。即使组件B、C 你完全用不到,也不得不集成进来。这是因为你只用到了组件A的部分能力,组件A中额外的能力带来了额外的依赖。如果遵循共同复用原则,你需要把A拆分,只保留你要用的部分。
2.2 三原则关系
REP、CCP、CRP 三个原则之间存在彼此竞争的关系,REP 和 CCP 是黏合性原则,它们会让组件变得更大,而 CRP 原则是排除性原则,它会让组件变小。
优秀的软件架构师需要而且能够在这三者之间进行平衡。
3、如何用组件构建系统?
3.1 组件依赖/结构图
组件依赖/结构图,不是顶层设计的功能模块图,不与顶层设计的功能模块对应,同时不是用来描述应用程序功能的。
它更像是应用程序在构建性与维护性方面的一张地图,重要目标是指导如何隔离频繁的变更,我们不希望那些频繁变更的组件影响到其他本来应该很稳定的组件。
3.2 组件耦合原则
三个组件耦合原则(基于组件依赖/结构图):
3.2.1 ADP:无依赖环原则
循环依赖中的组件在发布的过程中,都必须要集成另一个它依赖的组件,而环中的组件都互相依赖,不存在独立相对的组件。导致发布困难,如下图情况所示:
消除环依赖的方法,主要是组件依赖关系图中不应该出现环。
1)应用依赖反转原则
2)创建一个新的组件
3.2.2 SDP:稳定依赖原则
依赖必须要指向更稳定的方向。
这里组件的稳定性指的是它的变更成本,和它变更的频繁度没有直接的关联(变更的频繁程度与需求的稳定性更加相关)。影响组件的变更成本的因素有很多,比如组件的代码量大小、复杂度、清晰度等等,最最重要的因素是依赖它的组件数量,让组件难以修改的一个最直接的办法就是让很多其他组件依赖于它!
组件被依赖的越多,则改动影响面越大,改动则越需要慎重,则改动困难程度越高,即改动没有那么随意,则稳定性高。而没有被依赖的组件,则随意改,看心情都行,改动困难程度非常低,则稳定性差。
3.2.3 SAP:稳定抽象原则
一个组件的抽象化程度应该与其稳定性保持一致。
在一个软件系统中,总有些部分是不应该经常发生变更的,通常用于表现该系统的高阶架构设计及一些策略相关的高阶决策。为了防止高阶架构设计和高阶策略难以修改,通常抽象出稳定的接口、抽象类为单独的组件,让具体实现的组件依赖于接口组件,这样它的稳定性就不会影响它的扩展性。
耦合指标
通过 稳定性指标I 和 抽象化程度A 可以推导:D指标(稳定性 I 与其抽象化程度 A 之间的关系)
将不稳定性(I)作为横轴,抽象程度(A)作为纵轴,那么最稳定、只包含抽象类和接口的组件应该位于左上角(0,1),最不稳定、只包含具体实现类,没有任何接口的组件应该位于右下角(1,0),他们连线就是主序列线,位于线上的组件,他们的稳定性和抽象程度相匹配,是设计良好的组件。
左下角位于(0,0)周围区域的组件,它们是非常稳定(注意这里的稳定指的是变更成本)并且非常具体的组件,因为它的抽象程度低,决定了它经常改动的命运,但是又有许多其他组件依赖它,改起来非常痛苦,所以这个区域叫做痛苦区。
右上角区域的组件,没有其他组件依赖它,它自身的抽象程度又很高,很有可能是陈旧的老代码,所以这个区域叫做无用区。
可以用点距离主序列线的距离 Z 来表示组件是否遵循稳定抽象原则,Z 越大表示组件越违背稳定依赖原则。
总结
在了解了什么是组件之后,我们很方便地根据应用程序描绘软件组件依赖/结构图,基于此,介绍了组件聚合需要遵循的基本原则:
同时三原则存在互相限制,优秀的软件架构师需要而且能够在这三者之间进行平衡。
对于如何用组件构建系统,组件耦合原则:
边界的解耦方式也可以分为3个层次:
从上到下,(开发、部署)成本依次升高,如果低层次的解耦已经满足需要,不要进行高层次的解耦。所以不完全边界能解决的,不要用完全边界,低层次解耦能解决的,不要用高层次解耦。
- END -
作者:架构精进之路,专注软件架构研究,技术学习与个人成长,关注并私信我回复“01”,送你一份程序员成长进阶大礼包。
Thanks for reading!
- 上一篇: 文件后缀,也称为文件扩展名,用于标识文件的类型
- 下一篇: 我的世界启动器使用方法详解
猜你喜欢
- 2024-12-13 我的世界启动器使用方法详解
- 2024-12-13 文件后缀,也称为文件扩展名,用于标识文件的类型
- 2024-12-13 openmeetings(开源视频会议系统)的详细安装步骤 (windows版)
- 2024-12-13 你一定要看的安装及卸载测试用例的步骤及方法总结
- 2024-12-13 JVM理解classloader加载class文件的原理和机制
- 2024-12-13 傻瓜式Windows编程
- 2024-12-13 反向 Debug 了解一下?揭秘 Java DEBUG 的基本原理
- 2024-12-13 初学Tomcat会遇到的所有问题,解决方法都在这儿了
- 2024-12-13 Unity3D手游开发实践《腾讯桌球》客户端开发经验总结
- 2024-12-13 Tomcat 内存溢出问题总结
你 发表评论:
欢迎- 最近发表
-
- 多种负载均衡算法及其Java代码实现
- 输入www.baidu.com背后经历了啥?说清楚这个,已经超过90%的人了
- 优化MySQL:为什么你应该用 UNSIGNED INT 存储IP地址
- 实模式下CPU如何获取数据及指令(实模式寻址方式)
- java基础都在这了,小主们拿去吧(java基础是指什么)
- 盘点爬虫语言为何选择Python而不是Java
- 搭载Dubbo+Zookeeper踩了这么多坑,我终于决定写下这篇
- 网络协议之TCP/IP协议(面试必考内容) - javaEE初阶 - 细节狂魔
- 深夜报警!10亿次请求暴击,如何用Redis找出最热IP?
- VPN技术(IPsec/L2TP/SSLVPN/PPTP)学习笔记
- 标签列表
-
- java反编译工具 (77)
- java反射 (57)
- java接口 (61)
- java随机数 (63)
- java7下载 (59)
- java数据结构 (61)
- java 三目运算符 (65)
- java对象转map (63)
- Java继承 (69)
- java字符串替换 (60)
- 快速排序java (59)
- java并发编程 (58)
- java api文档 (60)
- centos安装java (57)
- java调用webservice接口 (61)
- java深拷贝 (61)
- 工厂模式java (59)
- java代理模式 (59)
- java.lang (57)
- java连接mysql数据库 (67)
- java重载 (68)
- java 循环语句 (66)
- java反序列化 (58)
- java时间函数 (60)
- java是值传递还是引用传递 (62)
本文暂时没有评论,来添加一个吧(●'◡'●)