概念、演进与设计目的
一、程序员的架构师之梦
几乎每个程序员内心,都拥有成为架构师的理想。但很多人在走向架构师的路上,会遇到重重困惑。很多技术能力扎实、业务理解到位的工程师,往往会卡在架构设计这一关。
作者结合自身经历发现,从接触架构设计,到初步掌握架构设计,需要数年实战沉淀。这并非个人天赋问题,而是架构设计本身具备三个显著特征:
- 思维模式差异巨大:程序开发核心是逻辑与实现;架构设计核心是判断与取舍。很多开发人员做架构时,依旧沿用写代码的思维,容易陷入困境。
- 缺少体系化训练资料:高校几乎没有专门的软件架构课程;市面上大部分书籍只讲解某一个技术点,缺少完整、体系化的方法论,学习者只能自行摸索,效率低下。
- 大量普遍认知误区:很多人觉得架构师需要极高天赋、必须充满创造性;认为架构一定要追求高大上,系统必须天然做到高性能、高可用。这些误解让不少技术人员还没开始实践就心生畏惧。
架构学习不是背诵一堆中间件与技术名词,而是掌握一套通用的方法论。无论业务场景、编程语言如何变化,都可以依靠这套方法论完成架构设计、评审、分析工作。
专栏知识体系主要分为五大模块:架构基础、高性能架构模式、高可用架构模式、可扩展架构模式、架构实战。通过学习,可以理清架构相关概念,掌握通用设计原则、标准设计流程,理解各类成熟架构模式,学会架构演进与开源系统使用技巧。
二、厘清核心概念:到底什么是软件架构
日常工作中 “架构” 一词被高频提及,但多数人无法给出清晰准确的定义。要理解架构,先要区分三组极易混淆的概念:系统与子系统、模块与组件、框架与架构。
2.1 系统与子系统
系统:由一批相互关联的个体组成,遵循既定规则运行,能够产生单个个体无法实现的全新能力。三个关键点:存在关联、遵循运行规则、具备整体涌现的新能力。
子系统:本质也是系统,只是观察层级不同。一个大系统,可以拆分为若干子系统;而子系统内部,还可以继续拆分更小的子系统。
举例:微信是完整系统,聊天、登录、支付、朋友圈属于它的子系统;朋友圈子系统内部,又可以拆分评论、点赞、动态子系统。
2.2 模块与组件
二者都是系统拆分出来的单元,拆分视角不一样:
- 模块:逻辑视角拆分,目标是职责分离,按照业务逻辑进行划分。例如登录注册模块、成绩管理模块。
- 组件:物理视角拆分,目标是单元复用,代表可独立、可替换的物理单元。例如 Nginx、MySQL、Redis。
案例:学生信息管理系统逻辑拆分(模块):登录注册模块、个人信息模块、成绩模块;物理拆分(组件):Nginx、Web 服务、MySQL 数据库。
2.3 框架与架构
- 框架:代表规范,同时提供基础实现。MVC、MVP 属于规范;Spring MVC 是落实 MVC 规范、附带基础功能的开发产品。
- 架构:代表系统的结构,描述系统如何组织、各部分如何协作。
同一个系统,可以从多个不同维度描述架构:业务逻辑维度、物理部署维度、开发规范维度,这也就是 RUP“4+1 视图” 思想的来源。
2.4 架构重新定义
软件架构,指软件系统的顶层结构。
这个定义包含三层含义:
- 明确系统由哪些子系统、模块、组件等个体构成;
- 明确各个个体之间的协作、交互、运行规则;
- “顶层结构” 用来区分不同层级,避免混淆系统架构、子系统架构。
【此处插入图 1 MVC 架构示意图】图题:MVC 架构逻辑示意图
思考题:你之前理解的架构是什么,对比本定义存在哪些差异?
三、软件架构设计的历史演进
软件架构不是凭空诞生,它是软件开发发展到一定规模之后的产物。梳理编程语言与软件工程的演进,能够理解架构出现的底层动因。
- 机器语言(1940 年代前):直接二进制编码,缺点:难写、难读、难修改,调试成本极高。
- 汇编语言(1940 年代):助记符替代二进制指令。虽然可读性提升,但依旧绑定 CPU 硬件,需要熟悉底层硬件细节,不同处理器代码不能复用。
- 高级语言(1950 年代起):Fortran、LISP、Cobol 相继诞生。开发者不用关心硬件细节,聚焦业务问题;一份代码可编译运行于多种硬件平台。
第一次软件危机:催生结构化程序设计(60‑70 年代)
软件规模快速膨胀,出现质量低下、项目延期、预算超支等大量问题,代表案例 IBM System/360 操作系统项目,该项目的经验催生经典著作《人月神话》。
- 应对方案:软件工程思想;结构化程序设计,抛弃 goto,采用自顶向下、逐步细化、模块化思路。诞生 “模块” 的概念,用来管控逻辑复杂度。
第二次软件危机:催生面向对象(80 年代)
硬件飞速迭代,业务需求持续变化。结构化编程能够处理逻辑复杂,但难以应对业务持续扩展带来的变更问题。面向对象思想迎来大规模普及,C++、Java 推动其成为主流开发范式,诞生 “对象” 概念,解决业务扩展的复杂度。
软件架构正式流行(90 年代)
当软件规模继续变大,算法、数据结构不再是最大难题;真正的问题变成大量组件如何组织在一起:系统耦合过重、改动牵一发而动全身、排查修复故障困难。
卡内基梅隆大学研究观点:当系统由大量部件组成时,系统整体组织方式,也就是软件架构,带来了全新的设计挑战。
发展脉络总结:
- 60 年代危机 → 结构化编程,模块;
- 80 年代危机 → 面向对象,对象;
- 90 年代大规模系统 → 软件架构,组件。
本质上三者都是软件的拆分手段,只是随着系统复杂度上升,拆分粒度变得越来越粗,层级越来越高。
软件行业不存在 “银弹”,没有任何一种技术、方法论可以一劳永逸解决所有软件问题,每种方案都只是对应特定时代、特定问题的解法。
四、架构设计真正的目的:对抗软件复杂度
很多人对架构设计存在不少认知误区:
- 误区 1:因为架构很重要,所以要做架构设计。
反驳:小型创业项目,没有专门架构设计也可以快速上线运行;架构设计本身要投入人力时间,盲目做架构反而拖慢进度。
- 误区 2:所有系统都必须完整做架构设计。
反驳:盲目照搬大厂架构,很容易出现水土不服,削足适履,反复重构。
- 误区 3:架构设计就是要做到高性能、高可用、高扩展。
反驳:不分业务场景一味追求各种 “高”,会造成架构过度复杂,项目落地遥遥无期。
架构设计真正目的
架构设计,核心目的就是解决软件系统复杂度带来的各类问题。
这条原则可以指导架构师的绝大多数决策:
- 面对繁多需求:优先识别业务系统的复杂点,针对复杂点开展设计,不需要面面俱到;
- 参考业界方案:要理解别人架构要解决的是什么复杂点,对比自己业务的复杂点,再决定是否借鉴,而不是直接复制;
- 抵制技术炫技:不能单纯为了使用新技术、追赶潮流引入架构方案,如果业务并不存在对应的复杂度,引入就是多余负担。
实战案例:学生管理系统
以一所大学学生管理系统举例,分析它的复杂度分布:
- 性能:访问量很低,MySQL、Nginx 就足够,性能不是复杂点;
- 可扩展性:业务功能稳定,扩展需求少;
- 高可用:服务短暂宕机 2 小时对业务影响不大;但是学生数据绝对不能丢失,存储可靠性是核心复杂点;
- 安全性:具备隐私,但不属于金融级强保密;做好账号权限、访问控制即可;
- 成本:服务器数量少,成本压力很小。
因此本系统架构重点解决存储可靠性,设计 MySQL 主备 + 跨机房备份策略,不需要引入缓存、负载均衡、异地多活等复杂组件。
【此处插入图 2 学生管理系统架构图】图题:学生管理系统参考架构(主机房 + 备份机房 MySQL 主备方案)
架构没有绝对好坏,只有是否适配业务的复杂度。架构师最重要的工作,就是识别业务主要矛盾,针对性取舍,而不是堆砌高大上技术。
五、小结
- 架构师的核心思维是取舍判断,区别于普通开发聚焦逻辑实现;
- 分清系统 / 子系统、模块 / 组件、框架 / 架构,是理解架构的基础;软件架构是系统的顶层结构;
- 软件工程演进历史,本质就是人类不断对抗软件复杂度的历史,模块‑对象‑组件代表不同时代的拆分思想;不存在万能银弹;
- 架构设计的根本目的,解决软件系统复杂度,一切脱离业务复杂度的架构设计都是过度设计。
思考题:拿你现在工作接触的业务系统,按照 “识别系统复杂度” 思路做一次分析,思考哪些是真正复杂的地方,哪些属于多余的设计。