软件架构--架构设计的整体介绍

1 介绍

1.1 概述

  • 架构就是对系统中的实体以及实体之间的关系所进行的抽象描述
  • 难懂的事物是具备较高的表面复杂度,超出人类的理解能力。如今社会的告诉发展,很多系统复杂度在快速增加。
  • 好的系统架构,具备必要的复杂度同时又不难懂
  • 复杂系统设计简单化,追求大道至简
    在这里插入图片描述
    在这里插入图片描述

1.2 复杂系统

  • 人体系统、生态系统、大气系统、水源系统
  • 机械系统、电子系统、操作系统、社会系统、航天平台系统、汽车控制系统、石油平台系统

1.3 架构目标

  • 软件架构最核心的问题是解决复杂性的问题,并且在解决问题的过程中,在时间(项目周期、行业发展速度)和空间(开发资源、护城河)上找到最佳的平衡点。
  • 架构师眼里第一件事不是多流行的技术,多高性能的框架,或者多完善的业务模型,而应该聚焦在利益活着并且活得好)之上。

1.4 架构过程(引用《系统架构:复杂系统的产品设计与开发》)

第一项任务:确定系统及其形式与功能。
第二项任务:确定系统中的实体、实体的形式与功能,以及系统边界和系统所处的环境。
第三项任务:确定实体之间的关系。
第四项任务:基于实体的功能以及实体之间的功能互动,来确定系统的涌现属性。

1.5 系统预测方式

经验

实验

建模

推理

1.6 设计工具

UML

在这里插入图片描述

1.7 架构师分类与能力要求

微软架构师分类

微软把架构师分为 4 种:

  • 企业架构师 EA(Enterprise Architect)
  • 基础结构架构师 IA(Infrastructure Architect)
  • 特定技术架构 TSA(Technology-Specific Architect)
  • 解决方案架构师 SA (Solution Architect)

《职业成长的逻辑模型》对架构师的能力要求

  • 现有资源评估盘点及资源编排能力
  • 消除歧义分清问题主次能力
  • 业务简化描述,用例抽象思维
  • 通用市场法务市场领域基础常识
  • 业务分析架构推导能力
  • 计算机基础理论知识体系
  • 通用技术栈原理认知
  • 工具使用熟练,排查定位问题能力
  • 技术深度广度
  • 分布式高并发性能调优技能
  • 产品思维

1.8 需求分析

架构师要做的就是简化系统的复杂度,消除业务歧义,致力于输出健壮兼容的系统架构。
在这里插入图片描述

利益分析

  • 公司利益、客户利益、团队利益会在系统构建中交织在一起。
  • 以公司的利益为本,客户利益为目标,最大程度去兼顾团队利益。
  • 定好原则,不忘初心。

资源评估

资源评估对项目经理来说很重要,资源是项目进度的支撑;
资源评估对架构师来说也很重要,资源是架构实现的支撑;

需求规范

系统的功能来自客户的需求,这二者如果出现歧义,架构师需要去消除。

  • 需求是什么?
  • 需求的价值?(利好客户?利好公司?)
  • 需求的代价?(客户付出?公司付出?)
  • 需求的紧迫性?

1.9 架构层级

在这里插入图片描述

1.10 软件架构的发展史

在这里插入图片描述

1.11 ​软件工程师的职业发展方向

在这里插入图片描述
软件岗位–CTO、技术VP、技术总监、首席架构师

2 架构分析

架构就是对系统中的实体以及实体之间的关系所进行的抽象描述

2.1 分类

分层架构:MVC,六边形架构,洋葱架构
事件驱动架构
微核架构
微服务架构
云原生架构

2.2 设计规范

  • GRASP 九大原则、SOLID 六大原则、GOF23 种设计模式。
  • GRASP 处于最上层,SOLID 基于它再进一步细化阐述,GOF 再根据这些原则进一步的归纳出更具体的模式。
  • GOF 模式是针对特定问题而提出的解决方案,而 GRASP 站在一个更高的角度来看待面向对象软件的设计,它是 GoF 设计模式的基础。GRASP 是对象职责分配的基本原则,其核心思想是职责分配,用职责设计对象。

GRASP 9大原则

  • 它由《UML 和模式应用》(Applying UML and Patterns)一书作者 Craig Larman 提出
  • GRASP是通用职责分配软件模式(General Responsibility Assignment Software Patterns)的缩写,能够帮助我们理解基本对象的设计,提高面向对象设计(OOD)的觉悟。GRASP总共有9中模式。GRASP是学习使用设计模式的基础
    在这里插入图片描述

信息专家(Information Expert)

我们设计对象(类)的时候,如果某个类拥有完成某个职责所需要的所有信息,那么这个职责就应该分配给这个类来实现。这时,这个类就是相对于这个职责的信息专家。
eg: 常见的网上商店的购物车(ShopCar),需要让每种商品(SKU)只在购物车内出现一次,购买相同商品,只需要更新商品的数量即可。
在这里插入图片描述

创建者(Creator)

实际应用中,符合下列任一条件的时候,都应该由类 A 来创建类 B,这时 A 是 B 的创建者:
a、A 是 B 的聚合
b、A 是 B 的容器
c、A 持有初始化 B 的信息(数据)
d、A 记录 B 的实例
e、A 频繁使用 B
如果一个类创建了另外一个类,那么这两个类之间就有了耦合,也可以说产生了依赖关系。依赖或耦合本身是没有错误的,但是他们带来的问题就是在以后的维护中产生连锁反应,而必要的耦合是逃不掉的,我们能做的就是正确的创建耦合关系,不要随便建立类之间的依赖关系,那么该如何去做呢?就是要遵守创建者模式规定的基本原则,凡是不符合以上条件的,都不能随便用 A 创建 B。
eg:因为订单(Order)是商品(SKU)的容器,所以应该由订单来创建商品。如下图:
在这里插入图片描述

低耦合(Low coupling)

低耦合模式的意思就是要我们尽可能地减少类之间的连接。
其作用非常重要:
a、低耦合降低了因一个类的变化而影响其他类的范围。
b、低耦合使用类更容易理解,因为类会变得简单,更内聚
下面这些情况会造成类 A、B 之间的耦合:
a、A 是 B 的属性
b、A 调用 B 的实例的方法
c、A 的方法中引用的 B,例如 B 是 A 方法的返回值或参数。
d、A 是 B 的子类,或者 A 实现 B
关于低耦合,还有下面一些基本原则:
a、Don’t Talk to Strangers 原则
意思就是说,不需要通信的两个对象之间,不要进行无谓的连接,连接了就有可能产生问题,不连接就一了百了了。
b、如果 A 已经和 B 有连接,如果分配 A 的职责给 B 不合适的话(违反信息专家模式),那么就把 B 的职责分配给 A。
c、两个不同模块的内部类之间不能连接,否则比招报应!
eg:Creator 模式的例子里,实际业务中需要另一个出货人来清点订单(Order)上的商品(SKU),并计算出商品的总价,但是由于订单和商品之间的耦合已经存在了,那么把这个职责分配给订单更合适,这样可以降低耦合,以便降低系统的复杂性。如下图:
在这里插入图片描述

高内聚(High Cohesion)

高内聚的意思是给类尽量分配内聚的职责,也可以说成是功能性内聚的职责。即功能性紧密相关的职责应该放在一个类里,并共同完成有限的功能,那么就是高内聚合。这样更有利于类的理解和重用,也便于类的维护。
高内聚也可以说是一种隔离,就像人体由很多独立的细胞组成,大厦由很多砖头、钢筋、混凝土组成,每一个部分(类)都有自己独立的职责和特性,每一个部分内部发生了问题,也不会影响其他部分,因为高内聚的对象之间是隔离开的。
eg:一个订单数据存取类(OrderDAO),订单即可以保存为 Excel 模式,也可以保存到数据库中;那么,不同的职责最好由不同的类来实现,这样才是高内聚的设计,如下图:
在这里插入图片描述

控制器(Controller)

用来接受和处理系统事件的职责,一般应该分配给一个能够代表整个系统的类,这样的类通常被命名为“XX处理器”、“XX协调器”或“XX会话”。
关于控制器类,有如下原则:
a、系统事件的接收与处理通常由一个高级类来代替。
b、一个子系统会有很多控制类,分别处理不同的事务。

多态性(Polymorphism)

这里的多态跟 OO 三大基本特征之一的“多态”是一个意思。
eg:我们想设计一个绘画程序,要支持可以画不同类型的图形,我们定义一个抽象类 Shape,矩形(Rectangle)、圆形(Round)分别继承这个抽象类,并重写(override)Shape 类里的Draw() 方法,这样我们就可以使用同样的接口(Shape抽象类)绘制出不同的图形,如下图:
在这里插入图片描述

纯虚构(Pure Fabrication)

这里的纯虚构跟我们常说的纯虚构函数意思相近。高内聚低耦合,是系统设计的终极目标,但是内聚和耦合永远都是矛盾对立的。高内聚以为这拆分出更多数量的类,但是对象之间需要协作来完成任务,这又造成了高耦合,反过来依然。该如何解决这个矛盾呢?这个时候就需要纯虚构模式,由一个纯虚构的类来协调内聚和耦合,可以在一定程度上解决上述问题。
eg:上面多态模式的例子,如果我们的绘图程序需要支持不同的系统,那么因为不同系统的API结构不同,绘图功能也需要不同的实现方式,那么该如何设计更合适呢?如下图:
在这里插入图片描述
这里我们可以看到,因为增加了纯虚构类AbstractShape,不论是哪个系统都可以通过AbstractShape 类来绘制图形,我们即没有降低原来的内聚性,也没有增加过多的耦合,可谓鱼肉和熊掌兼得。

间接性(Indirection)

“间接”顾名思义,就是这个事不能直接来办,需要绕个弯才行。绕个弯的好处就是,本来直接会连接在一起的对象彼此隔离开了,一个变动不会影响另一个。就像我在前面的低耦合模式里说的一样,“两个不同模块的内部类之间不能直接连接”,但是我们可以通过中间类来间接连接两个不同的模块,这样对于这两个模块来说,他们之间仍然是没有耦合/依赖关系的。

防止变异(Protected Variations)

预先找出不稳定的变化点,使用统一的接口封装起来,如果未来发生变化的时候,可以通过接口扩展新的功能,而不需要去修改原来旧的实现。也可以把这个模式理解为 OCP(开闭原则),就是说一个软件实体应当对拓展开发,对修改关闭。在设计一个模块的时候,要保证这个模块可以在不需要被修改的前提下可以得到拓展。这样做的好处就是通过拓展给系统提供了新的职责,以满足新的需求,同时又没有改变系统原来的功能。

SOLID 6大原则

  • Single Responsibility Principle:单一职责原则
  • Open Closed Principle:开闭原则
  • Liskov Substitution Principle:里氏替换原则
  • Law of Demeter:迪米特法则
  • Interface Segregation Principle:接口隔离原则
  • Dependence Inversion Principle:依赖倒置原则
    把这六个原则的首字母联合起来(两个 L 算做一个)就是 SOLID (solid,稳定的),其代表的含义就是这六个原则结合使用的好处:建立稳定、灵活、健壮的设计。

单一职责原则(Single Responsibility Principle)

There should never be more than one reason for a class to change.
一个类更改的原因不应该超过一个。
eg:参考下图中的设计,图形计算程序只使用了正方形的Area()方法,永远不会使用Draw()方法,而它却跟Draw方法关联了起来。这违反了单一原则,如果未来因为图形绘制程序导致Draw()方法产生了变化,那么就会影响到本来毫不关系的图形计算程序。
在这里插入图片描述
那么我们该怎么做呢?如下图,将不同的职责分配给不同的类,使单个类的职责尽量单一,就隔离了变化,这样他们也不会互相影响了。
在这里插入图片描述

开闭原则(Open Closed Principle)

Software entities like classes, modules and functions should be open for extension but closed for modification.
一个软件实体,如类、模块和函数应该对扩展开放,对修改关闭。
eg:如下图,有一个客户端程序通过数据访问接口操作数据,对于这套系统来说,一开始计划使用的是SQL Server或Oracle数据库,但是后来考虑到成本,改用免费的mysql;那么对于客户端程序来说,后来数据的扩展对它没有任何影响,它在不知不觉间就用上了免费好用的MySQL数据库,这全要感谢OCP原则。
在这里插入图片描述

里氏替换原则(Liskov Substitution Principle)

Functions that use use pointers or references to base classes must be able to use objects of derived classes without knowing it.
所有引用基类的地方必须能透明地使用其子类的对象。

迪米特法则(Law of Demeter)

Talk only to your immediate friends and not to strangers.
只与你的直接朋友交谈,不跟“陌生人”说话。

接口隔离原则(Interface Segregation Principle)

Clients should not be forced to depend upon interfaces that they don`t use.
The dependency of one class to another one should depend on the smallest possible.
客户端不应该依赖它不需要的接口。
类间的依赖关系应该建立在最小的接口上。
eg:参考下图的设计,在这个设计里,取款、存款、转帐都使用一个通用界面接口,也就是说,每一个类都被强迫依赖了另两个类的接口方法,那么每个类有可能因为另外两个类的方法(跟自己无关)而被影响。拿取款来说,它根本不关心“存款操作”和“转帐操作”,可是它却要受到这两个方法的变化的影响。
在这里插入图片描述
为每个类都单独设计专门的操作接口,使得它们只依赖于它们关系的方法,这样就不会互相影响。
在这里插入图片描述

依赖倒置原则(Dependence Inversion Principle)

High level modules should not depend upon low level modules. Both should depend upon abstractions.
Abstractions should not depend upon details. Details should depend upon abstractions.
上层模块不应该依赖底层模块,它们都应该依赖于抽象。
抽象不应该依赖于细节,细节应该依赖于抽象。
eg:参考下图的设计,一个开关跟灯直接连接在一起了,也就是说开关依赖于灯的打开和关闭方法,那么如果我想用这个开关也可以打开其他东西呢,比如电视、音响。显然这个设计是无法满足这个要了,因为我们依赖了细节而不是抽象,这个开关已经等价于“灯的开关”。
在这里插入图片描述
如下设计我们不仅可以打开灯,还可以打开电视和音响,甚至未来任何实现了“开关接口”的任何东西。
在这里插入图片描述

GOF 23种设计模式

GoF 23种设计模式一般分为三大类。

创建型模式

创建型模式,就是创建对象的模式,抽象了实例化的过程。
它帮助一个系统独立于如何创建、组合和表示它的那些对象。
关注的是对象的创建,创建型模式将创建对象的过程进行了抽象,也可以理解为将创建对象的过程进行了封装,作为客户程序仅仅需要去使用对象,而不再关心创建对象过程中的逻辑

  • 工厂方法模式(Factory Method)
  • 抽象工厂模式(Abstract Factory)
  • 单例模式(Singleton)
  • 创建者模式(Builder)
  • 原型模式(Prototype)

结构型模式

结构型模式是为解决怎样组装现有的类,设计他们的交互方式,从而达到实现一定的功能的目的。
结构型模式包容了对很多问题的解决。例如:扩展性(外观、组成、代理、装饰)封装性(适配器,桥接)。

  • 适配器模式(Adapter)
  • 外观模式(Facade)
  • 享元模式(Flyweight)
  • 组合模式(Composite)
  • 装饰器模式(Decorator)
  • 代理模式(Proxy)
  • 桥接模式(Bridge)

行为型模式

行为型模式涉及到算法和对象间职责的分配。
行为模式描述了对象和类的模式,以及它们之间的通信模式。
行为型模式刻划了在程序运行时难以跟踪的复杂的控制流可分为行为类模式和行为对象模式

  • 策略模式(Strategy)
  • 状态模式(State)
  • 职责链模式(Chain of Responsibility)
  • 观察者模式(Observer)
  • 模板方法模式(Template Method)
  • 命令模式(Command)
  • 备忘录模式(Memento)
  • 迭代器模式(Iterator)
  • 调停者模式(Mediator)
  • 解释器模式(Interpreter)
  • 访问者模式(Visitor)

参考

1、
2、林振华–架构设计的本质
3、软件架构–《系统架构:复杂系统的产品设计与开发》笔记
4、UML概述
5、GRASP模式概述
6、GRASP----(职责分配原则)
7、GRASP 设计原则
8、六大设计原则(SOLID)
9、软件架构–《设计模式–GoF》理解
10、软件架构(software architecture)
11、Software Architecture软件架构是啥
12、架构师之路 — 软件架构 — Overview
13、软考分类精讲-软件架构设计(一)
14、软件岗位–CTO、技术VP、技术总监、首席架构师
15、如何成为更好的软件架构师

  • 2
    点赞
  • 27
    收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:技术黑板 设计师:CSDN官方博客 返回首页
评论

打赏作者

worthsen

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值