架构
概念
系统、模块、组件、框架和架构
系统和子系统:
有关联的个体, 根据某种规则运行, 共同完成独特的功能, 子系统是系统的组成部分
模块和组件:
模块和组件都是系统的组成部分, 只是从不同角度拆分系统.
从逻辑角度拆分是模块, 模块从逻辑上将系统分解, 即分而治之, 将复杂问题简单化
模块的粒度可大可小, 可以是系统、子系统、某个服务、函数、类、方法、功能等
从物理角度拆分是组件, 组件可以包括应用服务、数据库、网络、物理机, 还可以是 MQ、容器、Nginx 等技术组件
模块是为了实现职责分离, 组件是为了实现复用
框架:
为了实现某个业界标准或完成特定基本任务的软件组件规范, 按照规范提供所要求基础功能的软件产品
架构:
顶层设计
架构分层和分类
分层
业务架构
包括业务规划、业务模块、业务流程, 对整个系统的业务进行拆分, 对领域模型进行设计, 将现实的业务转化成抽象对象
应用架构
承接业务架构和技术架构, 应用架构的本质是通过系统拆分, 平衡业务和技术复杂性, 保证系统形散神不散
应用架构定义系统有哪些应用、以及应用之间如何分工和合作
技术架构
确定组成应用系统的实际运行组件(技术选型), 这些组件之间的关系, 以及部署到硬件的策略
技术架构主要考虑系统的非功能性特征, 对系统的高可用、高性能、扩展、安全、伸缩性、简洁等做系统级的把握
分类
逻辑架构
逻辑架构关注功能, 不仅包括用户可见的功能, 还包括为实现用户功能而必须提供的 辅助功能模块
开发架构
开发架构关注程序包, 不仅包括要编写的源程序, 还包含可以直接使用的第三方 SDK和框架、类库, 以及开发的系统将运行于其上的系统软件或中间间
运行架构
运行架构关注进程、线程、对象等运行时概念, 以及相关的并发、同步、通信等问题, 运行架构关注运行期间各个单元的交互
物理架构
物理架构关注‘目标程序及其依赖的运行库和系统软件’最终如何安装或部署到物理机器, 以及如何部署机器和网络来配合软件系统的可靠性、可伸缩性等要求
数据架构
数据架构关注持久化数据的存储方案, 不仅包含实体及实体关系的存储格式、还包括数据传递、数据复制、数据同步等策略
常见的架构设计
书籍摘录
架构整洁之道
要想提高软件架构的质量, 就需要先知道什么是优秀的软件架构. 而为了在系统构建过程中采用好的设计和架构以便减少构建成本, 提高生产力, 有需要先了解系统架构的各种属性与成本和生产力的关系
平衡系统架构的重要性与功能的紧急程度这件事, 是软件开发人员自己的职责
三种编程范式: 结构化编程、面向对象编程、函数式编程
- 结构化编程
结构化编程对程序控制权的直接转移进行了限制和规范
主张使用控制语句(顺序结构、选择结构(if-else、 switch)、循环结构(for、 while)) 来组织程序逻辑, 避免使用无序的跳转(GOTO语句)
结构化编程范式最有价值的地方在于, 它赋予了我们创造可证伪程序单元的能力
- 面向对象编程
面向对象编程对程序控制权的间接转移进行了限制和规范
- 函数式编程
函数式编程对程序中的赋值进行了限制和规范
它将计算视为数学函数的求值, 强调使用纯函数和避免可变状态和副作用
核心思想是以函数为基本单位, 通过组合函数来构建程序
- 不可变性
所有的竞争问题、死锁问题、并发更新问题都是由可变变量导致
如果变量永远不会被修改, 那就不可能产生竞争或者并发更新问题
如果锁状态是不可变的, 那就永远不会产生死锁问题
一个架构设计良好的应用程序应该将状态修改的部分和不需要修改状态的部分隔离成单独的组件, 然后用合适的机制来保护可变量
事件溯源
只存储事务记录, 不存储具体状态. 当需要具体状态时, 从头开始计算所有的事务
- SOLID 原则的主要作用就是告诉我们如何将数据和函数组织成为类, 以及如何将这些类链接起来成为程序
这里虽然用到了 '类' 这个词, 但是并不意味着我们将要讨论的这些设计原则仅仅适用于面向对象编程
这里的类仅仅代表了一种数据和函数的分组, 每个软件系统都会有自己的分类系统, 不管他们各自是不是将其称为 '类', 事实上都是 SOLID 原则的适用领域
- SOLID 原则
- SRP: 单一职责原则
一个软件系统的最佳结构高度依赖于开发这个系统的组织的内部结构, 每个软件模块都有且只有一个需要被改变的理由
- OCP: 开闭原则
如果软件系统想要更容易被改变, 那么其设计就必须允许新增代码来修改系统行为, 而非只能靠修改原来的代码
- LSP: 里氏替换原则
如果想用可替换的组件来构建软件系统, 那么这些组件就必须遵守同一个约定, 以便让这些组件可以相互替换
- ISP: 接口隔离原则
在设计中避免不必要的依赖
- DIP: 依赖反转原则
高层策略性的代码不应依赖实现底层细节的代码, 恰恰相反, 那些实现底层细节的代码应该依赖高层策略性的代码
SRP: 任何一个软件模块都应该只对某一类行为者负责
OCP: 设计良好的计算机软件应该易于扩展, 同时抗拒修改
在一般情况下, 任何层次的软件设计如果依赖于不需要的东西, 都是有害的
任何层次的软件设计如果依赖了它并不需要的东西, 就会带来意料之外的麻烦
程序规模上的墨菲定律: 程序的规模会一直不断地增长下去, 直到将有限的编译和链接时间填满为止