当前位置: 首页 > news >正文

架构整洁之道摘录

软件架构

软件架构规则和其他变量完全⽆关。
软件设计的终极⽬标是⽤最⼩的成本来满⾜构建和维护系统的需求。
程序设计重要的是软件架构的灵活性⽽不是先实现功能。
软件系统的第⼀价值体系是系统⾏为,第⼆价值体系是系统架构

编程范式

结构化编程

利⽤if/else while等替代goto的使⽤,结构化编程对程序控制权的直接转移进⾏了限制和规范。

⾯向对象编程

利⽤多态限制⽤户对函数指针的使⽤,⾯向对象编程对程序控制权的间接转移进⾏了限制和规范。

函数式编程

函数式编程⼀般不可以修改变量的值,因此函数式编程对于变量的赋值进⾏了限制和规范。
⽤顺序结构、分⽀结构和循环结构就可以构造出任何程序。
架构设计时,对于功能的降解拆分仍然很重要。

⾯向对象编程

⾯向对象编程是⼀种对真实世界进⾏建模的⽅式。
封装性对于⾯向对象编程语⾔实际是削弱了。例如c++需要将变量定义在头⽂件中,java,c#由
于没头⽂件⽽分不清申明和定义。
完美的封装性存在于c语⾔中,struct定义在其他头⽂件,使⽤时前置申明好再使⽤。

继承性

继承特性在c语⾔中通过数据结构的内部变量的顺序控制以及强制类型转换实现。但是⾯向对象
的编程语⾔还是提供了更加易⽤的使⽤⽅式,⽐如多重继承的实现以及隐式的转换。

多态性

多态性使⽤c语⾔的函数指针也可以实现,但是对于易⽤和安全上,⾯向对象编程语⾔还是更加优秀。
⾯向对象编程通过多态实现依赖反转,这样可以完全控制系统中源码的依赖关系。使得架构师可以构建出插件式架构,每个组件实现独⽴部署。

不变性

函数式编程语⾔的变量是不可变的。这主要是为了避免造成多线程、死锁、并发等等的问题。

可变性隔离

将可变的组件和不可变的组件进⾏分离,不可变的组件使⽤纯函数的⽅式来执⾏任务,期间状态不可更改。不可变的组件将通过⼀个或者多个⾮函数式组件通信的⽅式来修改状态。
状态的修改⼀般使⽤事务型内存来保护可变变量,避免同步或者竞争状态的发⽣。
⼀个架构设计良好的应⽤程序应该将状态修改的部分和不需要修改的部分隔离或者独⽴成单独的组件,然后使⽤合适的机制来保护可变量。应该将逻辑尽可能的放在不可变组件中,可变组件中的逻辑越少越好。

SOLID原则

SRP:单⼀职责原则,每个软件模块有且只有⼀个被改变的理由
任何⼀个软件模块应该只对⼀类⾏为者负责
反⾯案例:⼀个⼯资管理程序的Employee类中包含三个函数calculatePay、reportHours、save,但这三个函数不属于⼀类calculatePay是财务部⻔制定、reportHours有HR使⽤、save由DBA制定。因此解决⽅法是将不同的⾏为者进⾏切分。

OCP原则

开闭原则,软件系统想要更加容易被改变的话,就需要允许增加代码来实现模块功能⽽⾮
修改现有的代码。⼀个好的计算机软件应该易于扩展,抗拒修改。模块单向依赖,限制每次修改的影响范围。实现⽅式是通过将系统划分为⼀系列的组件,将这些组件按照层次结构进⾏划分,使得低层次组建的修改不会影响⾼层次组件。

LSP原则

⾥⽒替换原则,软件最好遵守同⼀个约定,这样组件之间可以相互替换。
⼀个类依赖于另⼀个类的⽗类,这样⼦类不同,依赖的类不需要修改。
LSP原则不仅仅适⽤于继承类型,它适⽤于所有有统⼀的接⼝,并且期望可以相互替换的接⼝。

ISP原则

接⼝隔离原则,设计中避免不必要的依赖。类与类之间依赖只涉及必要的接⼝,⽆关的接⼝
不要依赖。

DIP

依赖反转原则,⾼层策略性的代码不应该依赖底层实现的代码,反之底层实现的代码应该依赖⾼层策略性的代码对于软件系统中经常变动的模块应该提供⼀个稳定的抽象接⼝。
代码中多使⽤抽象接⼝,尽量避免使⽤那些多变的具体实现类。不要在具体实现类派衍⽣类。不要覆盖包含具体实现的函数。应避免今年在代码中写任何与具体实现有关的名字,或者其他容易变动的名字。但具体实现调⽤的组件也不是不能出现,⼀般⼀个模块中会有⼀个调⽤具体实现的main组件。

组件

组建是指在软件部署时的最⼩单元。⽆论采⽤哪种部署形式,设计良好的组件应该保持可以单独部署的属性。

重定位技术

重定位技术出现是为了解决函数需要通过源代码的形加载使⽤的代码中,并且地址固定。
通过修改程序输出⼆进制⽂件的格式,由⼀个智能加载器加载到任意的内存。程序员需要指加载到的内存位置可重定位的代码中添加了⼀些记号,加载器在加载时会对这些制定的位置进⾏⼀些修改,⼀般是递增。这样的话,程序员可以⽤加载器来修改库函数加载的位置,并且还可以同时加载多个。

链接加载器

将库中的函数存储起来,⼀段程序调⽤了库中函数会被定义为外部引⽤,并将库中函数的名字称为外部定义,将两者链接起来。这样可以让程序员实现将程序分为多个可以被分别编译的代码段。
但是对于代码量较⼤的程序来说,这个过程⾮常缓慢,因此只能将加载和链接分离。链接过程放到链接器中进⾏。
现代程序由于内存和运算速度的⼤幅提⾼,链接过程已经⼤幅减少时间。
组件的形式在动态链接⽂件加载的应⽤场景中⾮常典型。⽬前插件式的架构已经被⼴泛使⽤。

组件聚合

REP 复⽤/发布等同原则

软件复⽤的最⼩粒度等同于发布的最⼩粒度。组建中的类与模块是密切相关的。

CCP 共同闭包原则

将可能同时修改以及有相同修改⽬的的类放在⼀个组件中。

CRP 共同复⽤原则

不要强迫⽤户⽤他们不需要的东⻄

⾯向服务架构

将系统拆分为⼀个个服务,服务之间进⾏隔离。服务需要⽀持单独编译和部署。

耦合的谬论

即使拆分为每个服务,但是进程之间的通信以及共享资源还是会将服务耦合在⼀起。所以如果想做到真正的耦合需要考虑如何避免这些问题。

独⽴部署的谬论

数据形式和⾏为形式的耦合,仍然会导致独⽴部署的困难。

横跨型变更

⽐如⼀个功能变更影响到许多的服务,这样也⽆法避免逻辑耦合的服务⼀起变更。
解决横跨型问题的⼀个⽅案是采⽤⾯向对象的组件式的模型,将逻辑放在基类中,特定的功能放在⼦类中。
服务边界不能代表系统的架构边界,服务内部的组件边界才是。

测试也是⼀种系统组件

可以将测试代码视为系统最外圈的程序。始终向内依赖,但其他组件不依赖它。
为了防⽌系统组件的修改引起⼤量的测试程序改变,需提⾼系统的可测试性,原则就是尽量少的依赖多变的东⻄。

整洁的嵌⼊式架构

软件不会随着时间推移⽽磨损,但是硬件会,因此硬件变更时软件可能也需要随之变更。因此需要通过好的架构设计来避免固件更迭带来的软件不适配问题,延⻓代码的有效使⽤⽣命周期。
嵌⼊式系统设计⼀般采⽤分层的⽅法。HAL是硬件抽象层,这⼀层将会给业务提供软件接⼝,因此会对硬件进⾏抽象。HAL的上层业务不需要知道底层硬件具体的实现细节,这样测试也可以通过HAL接⼝灌⼊值对软件接⼝进⾏测试。
硬件绑定很深的代码,例如硬件⼚商提供的读写寄存器、IO中断等的代码需要限制在固件层。和软件隔离之上层业务才能做到更好的移植性和可测试性。
软件和固件之间还需要操作系统层来防⽌上层代码和操作系统产⽣依赖。
整洁的嵌⼊式架构会引⼊操作系统抽象层,OSAL兼容以前的接⼝,并且可以让应采⽤定义好的公⽤结构。OSAL还可以为应⽤提供⽬标平台外的测试⽀撑点,是的测试也不依赖操作系统。

⾯向接⼝编程与可替代性

⾯向接⼝的交互式使得服务的可替代性提⾼。⽬前的普适规则是使⽤头⽂件充当接⼝的定义,但这样的话就需要保证头⽂件内容只包括函数声明以及函数使⽤到的结体和变量。数据库
数据库终究只是在硬盘与内存之间相互传输数据的⼀种⼿段⽽已,它真的可以被认为只是⼀个⻓期存储数据的、系统架构应该对磁盘本身的存在完全不关⼼。

相关文章:

架构整洁之道摘录

软件架构 软件架构规则和其他变量完全⽆关。 软件设计的终极⽬标是⽤最⼩的成本来满⾜构建和维护系统的需求。 程序设计重要的是软件架构的灵活性⽽不是先实现功能。 软件系统的第⼀价值体系是系统⾏为,第⼆价值体系是系统架构 编程范式 结构化编程 利⽤if/else…...

流程引擎-自定义函数的应用

背景: 某些业务需求比较特殊,需要在表单中校验或实现一些功能,泛微流程表单配置时实现的方式多种多样:JS脚本、SQL语句、公式以及其他一些标准化拖拽功能,本次给大家分享一下流程表单中的公式实现的一些需求场景。泛微…...

ChatGLM系列二:ChatGLM2的介绍及代码实践

一、介绍 2023年06月25日,清华大学开源了 ChatGLM2-6B 模型,是 ChatGLM 模型的升级版本。ChatGLM2-6B 在多个方面有显著提升:模型性能更强,在各种测试集上的表现更好;支持更长的上下文,最大上下文长度提升…...

JDBC对数据库进行操作

一.使用JDBC查询数据库表t_user的所有数据 1.User表 名称 数据类型 主键 是否为空 说明 ID number 是 用户编号 NAME Varchar2(50) 用户名 AGE varchar2(5) 用户年龄 BIRTH date 用户生日 PWD varchar2(20) 否 用户密码 import java.sql.Connection; import java.sql.Date; …...

unity 使用Image的RectTransform来进行判断是否点击到

public RectTransform LeftTouchArea;public RectTransform RightTouchArea;private void Update(){if (Input.GetMouseButtonDown(0)){//获取鼠标的位置Vector2 mousePos Input.mousePosition;//判断Image的坐标是否包含点击的坐标if (RectTransformUtility.RectangleContain…...

【C++】类与对象 第一篇(class,this)

目录 什么是类? 类的引入 class 类的两种定义方式: 声明与定义分离 类的访问限定符号 访问限定符​编辑 C中struct和class的区别是什么? 封装 类的作用域 类的实例化 类对象模型 如何计算类对象的大小 this指针 C语言和C实现Stack的对比 C语言实现…...

嵌入式软件工程师面试题——2025校招专题(四)

说明: 面试题来源于网络书籍,公司题目以及博主原创或修改(题目大部分来源于各种公司);文中很多题目,或许大家直接编译器写完,1分钟就出结果了。但在这里博主希望每一个题目,大家都要…...

actual combat 21——华为云从零开始项目部署(附nginx转发域名方式)

一、IP地址方式: 后端: 确保项目本地跑通建立并运行华为云流水线 前端: 打包(测试环境)手动上传 nginx: 配置一下即可 华为云: 安全组:暴露后端网关端口安全组:暴…...

@CallSuper注解方法学习

CallSuper注解是什么? CallSuper 是 Android 开发中使用的一个注解,它的主要用途是确保在子类重写父类的方法时,调用 super 方法。这在某些情况下是非常有用的,例如当你希望在重写方法时保留父类的默认行为,或者确保子…...

03_Flutter自定义下拉菜单

03_Flutter自定义下拉菜单 在Flutter的内置api中,可以使用showMenu实现类似下拉菜单的效果,或者使用PopupMenuButton组件,PopupMenuButton内部也是使用了showMenu这个api,但是使用showMenu时,下拉面板的显示已经被约定…...

如何查看多开的逍遥模拟器的adb连接端口号

逍遥模拟器默认端口号为:21503。 不过,使用多开器多开的时候,端口就不一定是21503了。 如何查看? 进入G:\xiaoyao\Microvirt\MEmu\MemuHyperv VMs路径中 每多开一个模拟器,就会多出一个文件夹。 进入你要查找端口号…...

2023年中国道路扫雪车分类、市场规模及发展前景分析[图]

道路扫雪车是一种专门用于清除道路上积雪和冰雪的机动车辆,通常配备有雪铲、扫雪刷、除冰剂喷洒系统等装置,用于在雪季或寒冷气候条件下,对道路进行清扫、除雪、除冰等作业,以确保道路的通行安全。 道路扫雪车行业分类 资料来源&…...

【机器学习】迁移学习(Transfer)详解!

1. 什么是迁移学习 迁移学习(Transfer Learning)是一种机器学习方法,就是把为任务 A 开发的模型作为初始点,重新使用在为任务 B 开发模型的过程中。迁移学习是通过从已学习的相关任务中转移知识来改进学习的新任务,虽然大多数机器学习算法都是…...

软件测试面试题

软件测试面试时一份好简历的重要性 软件的生命周期(prdctrm) 计划阶段(planning)-〉需求分析(requirement)-〉设计阶段(design)-〉编码(coding)->测试&am…...

分治算法解决归并排序问题

分治算法定义:分治算法是一种问题解决方法,它将一个大问题划分为多个相同或相似的子问题,然后递归地解决这些子问题,最后将子问题的解合并得到原问题的解 作用: 排序算法分治算法在排序算法中得到广泛应用。例如&…...

Spring Security漏洞防护—HttpFirewall和 HTTPS

一、HttpFirewall Spring Security有几个领域,你所定义的 pattern 会针对传入的请求进行测试,以决定应该如何处理请求。这发生在 FilterChainProxy 决定请求应该通过哪个过滤链时,以及 FilterSecurityInterceptor 决定哪些安全约束适用于请求…...

Makefile泛谈

Makefile工作原理 1、检查规则中的依赖文件是否存在。 2、若依赖文件不存在,则寻找是否有规则用来生成该依赖文件。 譬如,执行文件会先寻找.o文件是否存在,如果不存在,就会再寻找是否有规则可以生成该依赖文件。如果缺少了main.…...

Python的快捷键

Python Python使用的小快招关于注释关于格式写主函数如何看函数源代码 Python使用的小快招 本文主要记录了写python代码的时候提高效率的一些小妙招 关于注释 选中要注释的代码,然后按下Ctrl /即可对多段代码注释。 关于格式 对于python代码的格式&#xff0c…...

css为盒子设置滚动条隐藏滚动条

省流:为盒子设置宽高,设置滚动条方向,隐藏滚动条。 首先,要为需要添加滚动条的盒子设置固定的高度和宽度,这样才能让内容超过盒子的边缘。 .box {width: 300px;height: 300px; }然后,给盒子加入overflow属…...

音视频开发常见问题(四):视频花屏和绿屏

摘要 本文介绍了视频视频花屏/绿屏问题的常见原因,如丢失关键帧、metadata的变化、硬件编解码的兼容性问题和颜色格式不一致问题。以及排查方法和解决策略,包括检查视频数据格式、排查自采集/自渲染模块问题、联系第三方音视频SDK技术支持等。最后&…...

浏览器访问 AWS ECS 上部署的 Docker 容器(监听 80 端口)

✅ 一、ECS 服务配置 Dockerfile 确保监听 80 端口 EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]或 EXPOSE 80 CMD ["python3", "-m", "http.server", "80"]任务定义(Task Definition&…...

Linux 文件类型,目录与路径,文件与目录管理

文件类型 后面的字符表示文件类型标志 普通文件:-(纯文本文件,二进制文件,数据格式文件) 如文本文件、图片、程序文件等。 目录文件:d(directory) 用来存放其他文件或子目录。 设备…...

23-Oracle 23 ai 区块链表(Blockchain Table)

小伙伴有没有在金融强合规的领域中遇见,必须要保持数据不可变,管理员都无法修改和留痕的要求。比如医疗的电子病历中,影像检查检验结果不可篡改行的,药品追溯过程中数据只可插入无法删除的特性需求;登录日志、修改日志…...

基于Uniapp开发HarmonyOS 5.0旅游应用技术实践

一、技术选型背景 1.跨平台优势 Uniapp采用Vue.js框架,支持"一次开发,多端部署",可同步生成HarmonyOS、iOS、Android等多平台应用。 2.鸿蒙特性融合 HarmonyOS 5.0的分布式能力与原子化服务,为旅游应用带来&#xf…...

(二)原型模式

原型的功能是将一个已经存在的对象作为源目标,其余对象都是通过这个源目标创建。发挥复制的作用就是原型模式的核心思想。 一、源型模式的定义 原型模式是指第二次创建对象可以通过复制已经存在的原型对象来实现,忽略对象创建过程中的其它细节。 📌 核心特点: 避免重复初…...

《通信之道——从微积分到 5G》读书总结

第1章 绪 论 1.1 这是一本什么样的书 通信技术,说到底就是数学。 那些最基础、最本质的部分。 1.2 什么是通信 通信 发送方 接收方 承载信息的信号 解调出其中承载的信息 信息在发送方那里被加工成信号(调制) 把信息从信号中抽取出来&am…...

linux 下常用变更-8

1、删除普通用户 查询用户初始UID和GIDls -l /home/ ###家目录中查看UID cat /etc/group ###此文件查看GID删除用户1.编辑文件 /etc/passwd 找到对应的行,YW343:x:0:0::/home/YW343:/bin/bash 2.将标红的位置修改为用户对应初始UID和GID: YW3…...

土地利用/土地覆盖遥感解译与基于CLUE模型未来变化情景预测;从基础到高级,涵盖ArcGIS数据处理、ENVI遥感解译与CLUE模型情景模拟等

🔍 土地利用/土地覆盖数据是生态、环境和气象等诸多领域模型的关键输入参数。通过遥感影像解译技术,可以精准获取历史或当前任何一个区域的土地利用/土地覆盖情况。这些数据不仅能够用于评估区域生态环境的变化趋势,还能有效评价重大生态工程…...

Mysql8 忘记密码重置,以及问题解决

1.使用免密登录 找到配置MySQL文件,我的文件路径是/etc/mysql/my.cnf,有的人的是/etc/mysql/mysql.cnf 在里最后加入 skip-grant-tables重启MySQL服务 service mysql restartShutting down MySQL… SUCCESS! Starting MySQL… SUCCESS! 重启成功 2.登…...

代码规范和架构【立芯理论一】(2025.06.08)

1、代码规范的目标 代码简洁精炼、美观,可持续性好高效率高复用,可移植性好高内聚,低耦合没有冗余规范性,代码有规可循,可以看出自己当时的思考过程特殊排版,特殊语法,特殊指令,必须…...