深入理解设计原则之组件构建原则【软件架构设计】

news2024/11/27 22:27:10

系列文章目录

C++高性能优化编程系列
深入理解软件架构设计系列
深入理解设计模式系列
高级C++并发线程编程

组件构建原则

  • 系列文章目录
  • 1、组件构建原则的定义和解读
  • 1、组件
  • 2、组件聚合
    • 2.1、复用/发布等同原则(REP)
    • 2.2 、共同闭包原则(CCP)
    • 2.3、 共同复用原则(CRP)
    • 2.4、组件聚合张力图
  • 3、组件耦合
    • 3.1、 无依赖环原则
    • 3.2、 稳定依赖原则
    • 3.3、 稳定抽象原则

1、组件构建原则的定义和解读

组件构建原则是指在设计和开发组件时遵循的一些基本原则。这些原则旨在确保组件具有高可用性、可维护性、可扩展性和可复用性。
大型软件系统的构建过程与建筑物修建很类似,都是由一个个小组件组成的。所以,如果说SOLID原则是用于指导我们如何将砖块砌成墙的房间的,那么组件构建原则就是用来指导我们如何将这些房间组成房子的。

接下来,我们会详细讨论软件组件是什么?它是由什么元素构成的?以及如何利用组件来构建系统?
以下是一些常见的组件构建原则:
单一职责原则(SRP):一个组件应该只有一个职责或功能。
开放封闭原则(OCP):一个组件应该对扩展开放,对修改关闭。
依赖倒置原则(DIP):一个组件应该依赖于抽象而不是具体实现。
接口隔离原则(ISP):一个组件应该只暴露必要的接口。
最小知识原则(LOD):一个组件应该只与它直接交互的组件发生耦合。
组合/聚合复用原则(CARP):一个组件应该通过组合或聚合来实现复用。
高内聚低耦合原则(LC-HC):一个组件应该内聚性高、耦合性低。

在实际开发过程中,通过遵循这些组件构建原则,可以提高组件的质量、可用性和维护性,并减少重复代码和不必要的耦合。

1、组件

组件是软件的部署单元,是整个软件系统在部署过程中可以独立完成部署的组小实体。

我们可以将多个组件链接成一个独立可执行文件,也可以将它们汇总成类似.war文件这样的部署单元,又或者,组件也可以被打包成.jar、.dll或者.exe文件,并可以可动态加载的插件形式来独立部署。但无论采用哪种部署形式,设计良好的组件都应该永远保持可独立部署的特性,这同时也意味着这些组件应该可以被单独开发。

组件化的插件式架构已经成为我们习以为常的软件构建形式了。

2、组件聚合

究竟哪些类应该被组合成一个组件呢?这是一个非常重要的设计决策,应该遵循优秀的软件工程师经验来行事。但不幸的是,很多年以来,我们对于这么重要的决策经常是根据当下面临的实际情况临时拍脑门决定的。

接下来我们会具体讨论以下三个与构建组件相关的基本原则:

  • REP:复用/发布等同原则
  • CCP:共同闭包原则
  • CRP:共同复用原则

2.1、复用/发布等同原则(REP)

软件复用的最小粒度应等同于其发布的最小粒度。

解释:

如果想复用某个组件的话,一般就必须要求该组件的开发由某种发布流程来驱动,并且有明确的发布版本号。

如果没有设定版本号,我们就没办法保证所有被复用的组件之间能够彼此兼容。另外更重的一点是,软件开发者必须要能够知道这些组件的的发布时间,以及每次发布带来的哪些变更。

只有这样软件工程师才能在收到相关组件新版本发布的通知之后,依据该发布所变更的内容来决定是继续使用旧版本还是做些相应的升级,这是很基本的要求。因此,组件发布的过程中还必须要能够产生适当的通知和发布文档,以便让它的用户根据这些信息做出有效的升级决策。

总结:
从软件设计和架构设计的角度来看,REP原则就是指组件中的类与模块必须是彼此紧密相关的。也就是说,一个组件不能由一组毫无关联的类和模块组成,它们之间应该有一个共同的主题或者大方向。

CCP和CRP原则会从相反的角度对这个REP原则进行有力的补偿。

2.2 、共同闭包原则(CCP)

我们应该知道将那些会同时修改,并且为了相同目的而修改的类放到同一个组件中,而将不会同时修改,并且不会为了相同目的而修改的那些类放到不同的组件中。

解释:

这其实就是SRP原则在组件层面上的再度阐述。正如SRP单一职责原则中提到的一个类不应该同时存在着多个变更原因一样,CCP原则也认为一个组件不应该同时存在着多个变更原因

对于大部分应用程序来说,可维护性的重要性要远远高于可复用性。如果某个程序中的代码必须要进行某些变更,那么这些变更都最好都体现在同一组件中,而不是分布于很多个组件中,因为如果这些变更都集中在同一个组件中,我们就只需要重新部署该组件,其他组件则不需要被重新验证、重新部署了。

总而言之,CCP的主要作用就是提示我们要将所有可能会被一起修改的类集中在一处。也就是说,如果两个类紧密相关,不管是源代码层面还是抽象理念层面,永远都会一起被修改,那么它们就应该被归属为同一个组件。通过遵守这个原则,我们就可以有效地降低因软件发布、验证及部署所带来的工作压力。

另外CCP原则和OCP开闭原则也是紧密相关的,CCP讨论的就是OCP中所指的闭包。OCP原则认为一个类应该便于扩展,而抗拒修改。w由于100%的闭包是不可能的,所以我们只能战略性地选择闭包范围。在这几类的时候,我们需要根据历史经验和预测能力,尽可能地将需要被一同变更的那些点聚合在一起。

总结:
CCP原则实际上就是SRP原则的组件版。在SRP原则的指导下,我们将会把变更原因不同的函数放入不同的类中。而CCP原则指导我们应该将变更原因不同的类放入不同的组件中。简而言之,者两个原则都可以用这句话概括:

将由于相同的原因而修改,并且需要同时修改的东西放在一起。将由于不同的原因而修改,并且不同时修改的东西分开。

2.3、 共同复用原则(CRP)

不要强迫一个组件的用户依赖他们不需要的东西。

解释:

共同复用原则(CRP)是另外一个帮助我们决策类和模块归属于哪一个组件的原则。该原则建议我们将经常共同复用的类和模块放在同一个组件中。

通常情况下,类很少被单独复用。更常见的情况是多个类同时作为某个可复用的抽象定义被共同复用。CRP原则指导我们将这些类放在同一个组件中,而在这样的组件中,我们应该预见到会存在许多相互依赖的类。

由于这种依赖关系的存在,每当被引用组件发生变更时,引用它的组件一般也需要做出相应的变更。即使它们不需要进行代码级的变更,一般也免不了需要被重新编译、验证、部署。哪怕引用组件根本不关心被引用组件中的变更,也要如此。

CRP原则指导我们:不是紧密相连的类不应该被放在同一个组件里。

总结:

CRP原则实际上就是ISP接口隔离原则的一个普适版。ISP原则是建议我们不要依赖带有不需要的函数的类,而CRP原则则是建议我们不要依赖带有不需要的类的组件。两个原则都可以用这句话概括:

不要依赖不需要的东西。

2.4、组件聚合张力图

REP和CCP原则是粘合性原则,它们会让组件变得更大,而CRP原则是排除性原则,他会尽量让组件变小。软件架构师的任务就是要在这三个原则中间进行取舍。
在这里插入图片描述

图1 组件聚合原则张力图

简而言之,只关注REP和CRP的软件架构师会发现,即便简单的变更也会同时影响到很多组件。相反,如果软件架构师过于关注CCP和REP,则会导致很多不必要的发布

优秀的架构师应该在上述三角张力区区中定位一个最合适目前研发团队目前状态的位置,同时,也会根据时间不停停调整。例如在项目早期,CCP原则会比REP原则更重要,因为这一阶段也会根据研发速度比复用性更重要。

一般来说,一个软件项目的重心会从该三角区域的右侧开始,先期主要牺牲的是复用性,然后,随着项目的逐渐成熟,其他项目会逐渐开始对其产生依赖,项目重心就会逐渐向该三角区域的左侧滑动。换句话说,一个项目在组件结构设计上的中心是根据该项目的开发时间和成熟度不断变动的,我们对组件结构的安排主要于项目开发的进度和它被使用的方式有关,与项目本身功能的关系其实很小。

当下适用的分割方式可能明年就不再适用了。所以,组件的构成安排应随着项目重心的不同,以及研发性与复用性的不同而不断变化。

3、组件耦合

这三条原则主要关注的是组件之间的关系。在这些原则中,我们同样会面临着研发能力和逻辑设计之间的冲突。

3.1、 无依赖环原则

组件依赖关系图中不应该出现环。

3.2、 稳定依赖原则

依赖关系必须指向更稳当的方向。

3.3、 稳定抽象原则

一个组件的抽象化程度应该与其稳定性保持一致。

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

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

相关文章

C++(6):函数

函数基础 典型的函数包括:返回类型、函数名字、由 0 个或多个形参组成的列表以及函数体。 通过调用运算符(call operator)来执行函数。 调用运算符的形式是一对圆括号,它作用于一个表达式,该表达式是函数或者指向函数…

1731_makefile编写小结1_编译同目录下的文件

全部学习汇总: GreyZhang/g_makefile: Learn makefile from all kinds of tutorials on the web. Happy hacking and lets find an common way so we may dont need to touch makefile code any more! (github.com) 欢迎路过的YUAN类朋友相互交流,以下是…

每日学术速递6.2

CV - 计算机视觉 | ML - 机器学习 | RL - 强化学习 | NLP 自然语言处理 Subjects: cs.CL 1.BiomedGPT: A Unified and Generalist Biomedical Generative Pre-trained Transformer for Vision, Language, and Multimodal Tasks 标题:BiomedGPT:用于…

chatgpt赋能python:Python反向99乘法表:简单易学的终极练习

Python反向99乘法表:简单易学的终极练习 Python是一门强大而又容易上手的编程语言,而反向99乘法表则是一个极佳的练手项目。不仅能锻炼Python的基本语法和逻辑思维,同时也能体现出代码的风格和美感。本文将以Python反向99乘法表为例&#xf…

基于matlab仿真L形金属块基于时间温度分布图

一、前言 此示例说明了如何使用 Simulink 3D 动画™和 MATLAB 接口来操作复杂对象。 在此示例中,矩阵类型的数据在 MATLAB 和虚拟现实世界之间传输。使用此功能,您可以实现大量的颜色变化或变形。这对于可视化各种物理过程很有用。 我们在L形金属块中使用…

Chain of Thought Prompting和Zero Shot Chain of Thought初步认识

1. 思维链提示(Chain-of-Thought Prompting) 思维链(Chain-of-Thought:CoT)提示过程是一种最近开发的提示方法,它鼓励大语言模型解释其推理过程。下图显示了 few shot standard prompt(左)与链式思维提示过程(右&…

ChatGPT提示词攻略之基本原则

下面是调用openai的completion接口的函数。但在本文中并不是重点。了解一下就好。 import openai import osfrom dotenv import load_dotenv, find_dotenv _ load_dotenv(find_dotenv())openai.api_key os.getenv(OPENAI_API_KEY)def get_completion(prompt, model"gp…

[LeetCode周赛复盘] 第 348场周赛20230604

[LeetCode周赛复盘] 第 348场周赛20230604 一、本周周赛总结6462. 最小化字符串长度1. 题目描述2. 思路分析3. 代码实现 6424. 半有序排列1. 题目描述2. 思路分析3. 代码实现 6472. 查询后矩阵的和1. 题目描述2. 思路分析3. 代码实现 6396. 统计整数数目1. 题目描述2. 思路分析…

10.全局配置 app.json 与页面配置

常用的配置项有 pages 小程序的所有页面window 小程序窗口的外观tabBar 小程序底部的tabBar效果,就是底部的切换那部分style 组件样式版本 目录 1 window 2 tabBar 3 页面配置 1 window 小程序由下面三个部分组成,window可以配置 导航栏区域 与…

JavaSE_day43(多线程单线程区别,图解main方法若是单多线程该如何执行,如何使用多线程2种方式)

1 A.java * 学习多线程之前,我们先要了解几个关于多线程有关的概念。 A:进程:进程指正在运行的程序。确切的来说,当一个程序进入内存运行,即变成一个进程,进程是处于运行过程中的程序,并且具有一定…

【生成数据】绘制简单的折线图

使用scatter绘制散点图并设置其样式 plt.scatter(2, 4, s200)#设置图表标题并给坐标轴加上标签 plt.title("Square Number", fontsize24) plt.xlabel("Value", fontsize14) plt.ylabel("Square of Value", fontsize14)#设置刻度标记的大小 plt.…

2022年,Rust与Go哪一个更好?

这是每一个程序员和开发人员都问过的问题,还有很多人仍然在问,即使他们已经做出了自己的决定。Rust vs. Go。2022年,我应该选择哪一个?或选择哪种语言--Golang或Rust。 Golang和Rust是目前使用的最年轻的编程语言。Go于2009年在谷…

最新ChatGPT4.0Plus开通教程-支付宝购买苹果礼品卡-亲测可用

2023.06.04亲测可用ChatGPT开通Plus教程 前言:一、准备工作二、购买苹果礼品卡一、官网购买礼品卡二、支付宝方式购买 三、AppStore充值礼品卡四、ChatGPT Plus 订阅五、iOS 端 ChatGPT Plus 订阅失败解决方法六、美区AppStore账号ID注册教程: 之前&…

【Svelte】一个简单的前端框架

Svelte.js的学习成本高吗? Svelte是新手编码初学者的完美平台。只需一个HTML/CSS和JavaScript技能组合,您就可以从头开始构建您的第一个网站,而无需额外的知识。 这使得学习曲线非常小,不像它的大多数替代方案。除此之外&#xf…

ChatGLM-6b 多任务微调

ChatGLM-6b也是一种预训练模型,它也可以通过微调来适应下游任务。实验表明,使用ChatGLM-6b微调和Bert类预训练模型微调的效果相近。如果采用多任务设计,ChatGLM-6b的效果会更好。你可以在这里了解更多关于ChatGLM-6B的信息: ChatGLM-6Bhttps:…

边缘化中FEJ图例的理解

如图所示,在解释为什么需要FEJ(First Estimation Jacobian)时,通常会将这个图拿出来说事。但是,很多时候只是一笔带过,这个图看的云里雾里的,不是非常明白(可能是我理解力的问题),所以&#xff…

AngularJs学习笔记--bootstrap

AngularJs学习笔记系列第一篇,希望我可以坚持写下去。本文内容主要来自 AngularJS 文档的内容,但也加入些许自己的理解与尝试结果。 一、总括 本文用于解释Angular初始化的过程,以及如何在你有需要的时候对Angular进行手工初始化。 二、An…

【云原生-K8s】k8s可视化管理界面安装配置及比较【Kubesphere篇】

总览 安装了k8s控制面板,方便日常的问题处理,查看资源状态信息,也可以增加子账号进行开放给其他人员使用,减少命令操作,提升工作效率 前置条件 须有一个正常使用的k8s集群附k8s v1.23版本搭建:https://…

JavaScript实例(Visual Studio Code)(一)

JavaScript程序本身不能独立存在 它是依附于某个HTML页面 在浏览器端运行的 基本语法&#xff1a; <script type"text/javascript" [src"外部js文件"]>... </script> 语法说明&#xff1a; script为脚本标记&#xff0c;它必须以<scri…

【小沐学Web】Rust实现Web服务器

文章目录 1、简介2、开发环境配置2.1 下载2.2 安装2.3 编辑工具2.4 构建工具2.5 自动化工具 3、Hello World4、TCP/UDP通信5、Web服务器结语 1、简介 https://www.rust-lang.org/ Rust: 一种使每个人都能够构建可靠且高效的软件的语言。 如今&#xff0c;全球有数百家公司在生…