⭐⭐⭐ Spring Boot 项目实战 ⭐⭐⭐ Spring Cloud 项目实战
《Dubbo 实现原理与源码解析 —— 精品合集》 《Netty 实现原理与源码解析 —— 精品合集》
《Spring 实现原理与源码解析 —— 精品合集》 《MyBatis 实现原理与源码解析 —— 精品合集》
《Spring MVC 实现原理与源码解析 —— 精品合集》 《数据库实体设计合集》
《Spring Boot 实现原理与源码解析 —— 精品合集》 《Java 面试题 + Java 学习指南》

摘要: 原创出处 jianshu.com/p/312af3e8b94a 「猿码架构」欢迎转载,保留摘要,谢谢!


🙂🙂🙂关注**微信公众号:【芋道源码】**有福利:

  1. RocketMQ / MyCAT / Sharding-JDBC 所有源码分析文章列表
  2. RocketMQ / MyCAT / Sharding-JDBC 中文注释源码 GitHub 地址
  3. 您对于源码的疑问每条留言将得到认真回复。甚至不知道如何读源码也可以请教噢
  4. 新的源码解析文章实时收到通知。每周更新一篇左右
  5. 认真的源码交流微信群。

0 前言

在软件研发这个领域,程序员的终极目标都是想成为一名合格的架构师。然而梦想很美好,但现实却很曲折。

在实际工作中,程序员会分很多种,有的擅长编码实现,有的擅长底层原理,有的擅长逻辑实现等等,在各自的领域都表现不俗、担当核心,然而,面临更高层架构设计时,很多优秀的程序员却折戟沙场,未能完成华丽转身。

架构的真谛是什么呢?架构真的如此难把控吗?难道真的只有天资聪慧、天赋异能的程序员才能驾驭架构吗?

不要气馁,平常心,其实人人都是架构师,可能你做的任一一件事已无形中用到了架构。

本篇文章将带您慢慢走进架构,揭秘架构的真谛。正如,架构不是神秘物,吸取真谛即了然

1 架构的背景

如果想要深入理解某一事物的本质,最好的方式就是去追寻这个事物出现的历史背景和推动因素。所以我们先来梳理一下软件开发的进化史,探索一下软件架构出现的历史背景。

1.1 机器语言

最早的软件开发使用的是“机器语言”,其直接使用二进制码0和1来表示机器可以识别的指令和数据。

比如:为了完成“将寄存器 BX 的内容送到 AX 中”,机器语言如下:

1000100111011000

面对上面的1&0的字符串,不用多说,程序员心里肯定会万马奔腾吧,更别说输入错误要去定位问题,求程序员的心里阴影面积?

归纳一下,机器语言的主要问题是三难:

太难写、太难读、太难改!

1.2 汇编语言

为了解决机器语言编写、阅读、修改复杂的问题,汇编语言应运而生。汇编语言又叫“符号语言”,用助记符代替机器指令的操作码,用地址符号(Symbol)或标号(Label),代替指令或操作数的地址

比如:为了完成“将寄存器 BX 的内容送到 AX 中”,汇编语言如下:

mov ax,bx

相比机器语言来说,汇编语言就清晰得多了。汇编语言虽然解决了机器语言读写复杂的问题,但本质上还是面向机器的,因为写汇编语言需要我们精确了解计算机底层的知识

面向机器的语言,带来的问题就是

汇编语言需要针对不同 CPU 的汇编指令和结构,代码编写多份。

1.3 高级语言

为了解决汇编语言的问题,前辈们又设计出了一个“高级语言”。为什么会叫“高级语言”呢?原因在于这些语言让程序员不需要关注机器底层的低级结构和指令,只需要关注具体的问题和业务即可

比如:以4+6=?这个加法为例,如果用Lisp语言,只需要简单一行代码:

(+ 4 6)

除此以外,通过编译程序的处理,高级语言可以被编译为适合不同CPU指令的机器语言。程序员只要写一次程序,就可以在不同的机器上编译运行,无须根据不同的机器指令重写整个程序

1.4 两次软件危机

  1. 第一次软件危机与结构化程序设计

    高级语言的出现,解放了程序员,但好景不长,随着软件的规模和复杂度的大大增加,软件质量低下,质量把控难度高,项目无法如期完成,严重超支等现象。例如,1963 年美国的 水手一号火箭发射失败事故,就是因为一行 FORTRAN 代码错误导致的。

    所以,为了解决上面的问题,针对性的提出了解决方法“软件工程”,虽然“软件工程”提出之后也曾被视为软件领域的银弹,但后来事实证明,软件工程同样无法根除软件危机,只能在一定程度上缓解软件危机

    差不多同一时间,“结构化程序设计” 作为另外一种解决软件危机的方案被提了出来。结构化程序设计的主要特点是抛弃 goto 语句,采取“自顶向下、逐步细化、模块化”的指导思想

    结构化程序设计本质上还是一种面向过程的设计思想,但通过“自顶向下、逐步细化、模块化”的方法,将软件的复杂度控制在一定范围内,从而从整体上降低了软件开发的复杂度。

  2. 第二次软件危机与面向对象

    结构化编程的风靡在一定程度上缓解了软件危机,然而随着硬件的快速发展,业务需求越来越复杂,以及编程应用领域越来越广泛,第二次软件危机很快就到来了。

    第二次软件危机的根本原因还是 在于软件生产力远远跟不上硬件和业务的发展

    第一次软件危机的根源在于 软件的“逻辑”变得非常复杂

    第二次软件危机主要体现在 软件的“扩展”变的非常复杂

    结构化程序设计虽然能够缓解软件逻辑的复杂性,但是对于业务变化带来的软件扩展却无能为力。软件领域迫切希望找到新的银弹来解决软件危机,在这种背景下,面向对象的思想开始流行起来。

    虽然面向对象开始也被当做解决软件危机的银弹,在一定程度上解决了软件“扩展”带来的复杂性。但事实证明,和软件工程、结构化程度设计一样,面向对象也不是银弹,而只是一种新的软件方法而已

1.5 软件架构的产生

与之前的各种新方法或者新理念不同的是,“软件架构”出现的背景并不是整个行业都面临类似相同的问题,“软件架构”也不是为了解决新的软件危机而产生的,这是怎么回事呢

随着软件系统规模的增加,计算相关的算法和数据结构不再构成主要的设计问题。当系统由许多部分组成时,整个系统的组织,也就是所说的“软件架构”,产生了一系列新的设计问题。比如:

  1. 系统规模庞大,内部耦合严重,开发效率低;
  2. 系统耦合严重,牵一发动全身,后续修改和扩展困难;
  3. 系统逻辑复杂,容易出问题,出问题后很难排查和修复;

“软件架构”的出现有其历史必然性。第一次软件危机引出了“结构化编程”,创造了“模块”概念;第二次软件危机引出了“面向对象编程”,创造了“对象”概念;直到“软件架构”的产生,创造了“组件”概念

“模块”、“对象”和“组件”本质上都是对达到一定规模的软件进行拆分,差别只是在于随着软件的复杂度不断增加,拆分的粒度越来越粗,拆分的层次越来越高。

2 架构指什么

对于技术人员来说,“架构”是一个再常见不过的词了。当提起“架构”这个词时,如果去深究一下:“架构”到底指什么?大部分人也许并不一定能够准确地回答。1000个人心中可能有1001种架构的含义。

那么如何才能准确的理解架构呢?理解架构首先理解三个有关系而又相似的概念,包括:系统与子系统、模块与组件、框架与架构

2.1 系统与子系统

关于“系统”的定义,我们先来看维基百科的定义:

系统泛指由一群 有关联 的个体组成,根据某种 规则运作能完成 个别元件不能单独完成的工作的群体。它的意思是“总体”、“整体”或“联盟”。

来提炼下里面的关键信息:

  1. 关联:系统是由一群有关联的个体组成的,没有关联的个体堆在一起不能成为一个系统,例如:把一个发动机和一台PC放在一起不能称之为一个系统,把发动机、底盘、轮胎、车架组合起来才能成为一台汽车。
  2. 规则:系统内的个体需要按照指定的规则运作,而不是单个个体各自为政。规则规定了系统内个体分工和协作的方式。例如:汽车发动机负责产生动力,然后通过变速器和传动轴,将动力输出到轮胎上,从而驱动汽车前进。
  3. 能力:系统能力和个体能力有本质的差别,系统能力也不是个体能力之和,而是产生了新的能力。例如:汽车能够载重前进,而发动机、变速器、传动轴、车轮本身都不具备这样的能力。

再来看下子系统的定义:

子系统也是由一群有关联的个体所组成的系统,多半会是更大系统中的一部分。

其实子系统和系统的定义是一样的,只是观察的角度有差异,一个系统可能是另外一个更大系统的子系统。

按照这个定义,系统和子系统比较容易理解。以微信为例来做一个分析:

  1. 微信本身是一个系统,包含聊天、登录、支付、朋友圈等子系统;
  2. 朋友圈这个系统又包括动态、评论、点赞等子系统;
  3. 评论这个系统可能又包括防刷子系统、审核子系统、发布子系统、存储子系统等;
  4. 评论审核子系统不再包含业务意义上的子系统,而是包括各个模块或者组件,这些模块或者组件本身也是另外一个维度上的系统,例如:MySQL、Redis等存储系统,但不是业务子系统。

2.2 模块与组件

从逻辑的角度来拆分系统,得到的单元就是“模块”;从物理的角度来拆分系统,得到的单元就是“组件”。划分模块的主要目的是职责分离;划分组件的主要目的是单元复用。其实,“组件”的英文“component”也可以翻译成中文的“零件”一词,“零件”更容易理解一些,“零件”是一个物理的概念,并且具备“独立且可替换”的特点。

2.3 框架与架构

单纯从定义的角度来看,框架关注的是“规范”,架构关注的是“结构”。框架的英文是“Framework”,架构的英文是“Architecture”。

我们经常会说,比如:“工程采用的是MVC架构”、“工程使用的是SSH框架”等。所以,第一句话是站在结构的层面来说明,第二句话是站在规范的层面来说明。

同时,如果是以不同的角度来说明结构,会得出不同的架构描述,比如:

  1. 从业务逻辑的角度分解,“学生管理系统”的架构

    “学生管理系统”的架构

  1. 从物理部署的角度分解,“学生管理系统”的架构

    “学生管理系统”的架构

  1. 从开发结构的角度分解,“学生管理系统”的架构

    “学生管理系统”的架构

2.4 重新定义架构

软件架构指软件系统的顶层结构

首先,“系统是一群关联个体组成”,这些“个体”可以是“子系统”、“模块”、“组件”等;架构需要明确系统包含哪些“个体”

其次,系统中的个体需要“根据某种规则”运作,架构需要明确个体运作和协作的规则

3. 架构的目标

架构其实就是为了应对软件系统复杂度而提出的解决方案。架构关键思维即为判断与取舍

正如,在一个有约束的盒子里去求解或接近最合适的解。这个约束的盒子可能会包含团队经验、成本、资源、时间、业务阶段等因素掺杂在一起的综合体,针对这个综合体,分析出系统架构的复杂度,进行合适的判断与取舍,从而设计出恰当的架构用在合适的软件系统中。

文章目录
  1. 1. 0 前言
  2. 2. 1 架构的背景
    1. 2.1. 1.1 机器语言
    2. 2.2. 1.2 汇编语言
    3. 2.3. 1.3 高级语言
    4. 2.4. 1.4 两次软件危机
    5. 2.5. 1.5 软件架构的产生
  3. 3. 2 架构指什么
    1. 3.1. 2.1 系统与子系统
    2. 3.2. 2.2 模块与组件
    3. 3.3. 2.3 框架与架构
    4. 3.4. 2.4 重新定义架构
  4. 4. 3. 架构的目标