架构师 - 2.软件架构设计
软件架构设计:把一套系统想清楚的四步
顺着一条主线往下走:先认识架构(是什么、怎么表达),再搭建架构(用什么方法、选什么风格),然后评估架构(质量属性怎么权衡),最后复用架构(怎么不重复造轮子)。四个动作连起来,就是面对新系统时的完整思考链。
贯穿全篇的比方
盖一栋楼,最先动笔的不是某块砖怎么砌,而是总平面图——几层、水电怎么走、哪面墙能拆、以后要不要加电梯。软件架构干的正是这件事:不关心某行代码怎么写,却决定了这套系统能不能住得舒服、改得动、扛得住压力。
所有内容都能放回"盖楼"场景对齐。四句话即可收束:
- 画清楚:用视图和描述语言,把系统讲给不同的人听;
- 搭对路:用方法论和风格,把系统的骨架立起来;
- 评到位:用质量属性和评估方法,看清骨架的强项和代价;
- 别重造:用产品线、构件、中间件,把别人的好零件直接拿来用。
第一步:把系统"画"出来
1.1 架构指什么
准话是:架构 = 一组计算构件 + 把它们连起来的连接件 + 它们之间的交互关系、约束、行为和部署环境。
四重身份:
- 团队沟通的通用语言——聊的是同一张图;
- 早期关键决策的载体——方向定了,后面少返工;
- 质量属性的根基——性能、可改、可扩都从这里长出来;
- 复用与演化的支点——骨架稳,换零件才不塌。
架构不等于详细设计:架构看宏观结构与决策(墙怎么隔),设计看模块内部怎么实现(砖怎么砌)。架构像人的骨架加神经布线——骨架决定站多稳,布线决定信息传多快;换块肌肉(模块)不影响整体,动骨架要命。
1.2 用 4+1 视图讲给五类人听
同一套系统,用户、程序员、集成工程师、运维关心的点完全不同。Kruchten 用五个视角描述,再用"场景"串起来验证,即 4+1 视图:
| 视图 | 看什么 | 主要给谁看 |
|---|---|---|
| 逻辑视图 | 功能、类的关系 | 最终用户 |
| 开发视图 | 模块、包的组织 | 程序员 |
| 进程视图 | 并发、性能、线程 | 集成者 |
| 物理视图 | 怎么部署到机器 | 系统工程师 |
| 场景视图(+1) | 用用例把前四个串起来验证 | 所有人 |
给同一栋楼画四张图加一条带看路线——平面图(逻辑)、施工图(开发)、人流图(进程)、选址图(物理),最后用一条"业主动线"(场景)走一遍,验证四张图对不对得上。场景视图是把四张图粘在一起的线,没有它,图各画各的,迟早对不上。
1.3 用 ADL 把图讲给机器听
视图是给人看的,要机器能算、能分析,得用架构描述语言(Architecture Description Language, ADL):形式化地描述构件、连接件、配置、约束和语义。好处是能交给工具做分析、甚至自动生成骨架代码——偏"描述/分析",不等于写代码。
ADL 像建筑的 CAD(计算机辅助设计, Computer-Aided Design)图纸:比手绘精准,机器能算承重、能直接下料,但 CAD 不等于砖头。关注架构级(构件/连接件),不是代码级。
第二步:把系统"搭"出来
2.1 先有方法,再上风格
ABSD(基于架构的软件开发方法, Architecture-Based Software Design) 是总的方法论:以架构为中心,由用例和质量场景驱动,迭代增量地往前走。六个过程:需求 → 设计 → 文档化 → 复审 → 实现 → 演化。
传统做法是边砌墙边想,ABSD 是先把户型图定下来,再一点点添砖加瓦。最值钱的地方,是让"架构"在最早就被显式设计、复审,而非等代码堆出来才返工。DSSA(领域特定软件架构, Domain-Specific Software Architecture)正是 ABSD 在"某一领域"里的落地版本。
2.2 架构风格:先选套路,再写代码
风格的本质,是一套可复用的组织模式与约束——词汇表加组合规则。选错了风格,后面处处别扭,就像装修选了工业风却想住出温馨感,怎么改都拧。
风格分七大类,逐个讲清"长什么样、什么时候用、靠什么换来了什么":
(1) 数据流风格
- 批处理序列:数据整体传,前一步全跑完才进下一步;
- 管道-过滤器:边产边消费、各级可并行,过滤器无状态、管道只传数据。
判别窍门:要不要等上一步全部完成?要等=批处理,不等=管道。前者像年底一次性对账(必须等全部账单到齐),后者像净水器滤芯(水一级级过,每级只管自己那段,换滤芯不影响其他级)。
(2) 调用/返回风格
主程序-子程序、面向对象、层次结构、C/S(客户端/服务器, Client/Server)都在此类。重点在层次结构:上层只调下层、禁止跨层,换掉某一层下面浑然不知。像公司职级——员工找主管、主管找总监,别越级;靠"稳定接口 + 禁止跨层"换来可修改性和可移植性。
(3) 独立构件风格
构件彼此独立(进程/线程),靠消息或过程调用通信。松耦合、高并发、易扩展,难点在消息的顺序和可靠。像公司各部门——各干各的,靠邮件协作,互不关心对方内部怎么运转。多为显式消息,要和"事件系统"区分开。
(4) 事件系统(隐式调用)
事件源 → 事件总线/管理器 → 订阅者,即发布-订阅。极强解耦、易扩展,代价是控制流隐式、难调试。像小区广播——物业一广播(事件),所有订阅的居民各自反应,物业根本不知道谁在听。关键在"隐式":事件源不直接调处理器。
(5) 虚拟机风格
自己定义一套中间指令/规则,交给解释引擎执行,换来可移植、可扩展,代价是效率偏低。典型是解释器和规则引擎。像同声传译——说英语(高级指令),翻译(引擎)实时翻成中文(机器码),换个国家(平台)换翻译即可。本质是"为某种特定语言造一台虚拟机"。
两个子风格展开:
- 解释器:解释引擎(解析+执行)+ 被解释程序 + 当前状态/工作内存 + 用户接口,逐步执行并维护状态。像读菜谱做菜——菜谱(程序)+ 厨师(引擎)+ 灶台状态(工作内存),一步步照做。
- 规则系统:规则集(if-then)+ 规则引擎 + 事实/工作内存 + 议程/推理机,事实进内存后推理机匹配规则触发动作。像红绿灯指挥——"如果路口有车且绿灯,就放行",交警(推理机)盯着路况不断套规则。业务规则与代码分离,非技术人员也能维护,但怕规则爆炸。
(6) 仓库风格
中央数据共享仓库为核心,外围构件围绕它读写,彼此不直接通信。两个子风格要分清:
- 数据库:仓库被动,构件主动存取;
- 黑板:仓库主动,数据一变就通知相关构件。
像公司公共云盘——各部门都从云盘取/存文件,彼此不直发邮件;黑板就是云盘的"更新提醒",文件一变就推给相关人。主动通知还是被动存取,是两者最大区别。
| 维度 | 数据库风格(被动存取) | 黑板风格(主动通知) |
|---|---|---|
| 仓库状态 | 呆板的账本 | 活跃的广播站 |
| 交互方式 | 外围构件:我去查查看 | 仓库:大家注意,数据变了! |
| 实时性 | 差(有延迟,靠轮询) | 好(实时推送) |
| 耦合度 | 较低(只依赖数据库表结构) | 极低(发布者根本不知道谁在订阅) |
| 典型技术 | MySQL、Oracle、传统 CRUD | Redis Pub/Sub、Kafka、事件总线、响应式编程 |
(7) 闭环风格
来自控制论:传感器采集 → 控制器计算 → 执行器动作 → 反馈。自适应、稳,适合实时和物理系统。像空调恒温——温度计报 28℃,空调启动制冷,降到 26℃ 又停,来回逼近设定值。有"反馈"才算闭环,时延会影响稳定性。
(8) C2 风格
基于网络拓扑,构件-连接件分层、异步消息;构件不直接通信,全由连接件路由。高度松耦合、可动态增删组件。像前台转接台——员工之间不直拨,所有电话经前台转接,加人减人改改路由即可。连接件负责路由,是它区别于直接调用的根本。C2 是 Component-Connector(构件-连接件) 的缩写,由 Taylor 等人提出,强调"以连接件为中心"的异步消息通信。
落到软件工程上,最典型的例子是企业服务总线(ESB)或 API 网关:微服务里前端(构件 A)要调订单服务(构件 B),它并不直接请求订单服务的 IP,而是把请求发给 API 网关(连接件);网关按路由规则异步转发给订单服务,订单服务处理完把结果交回网关,网关再推回前端。哪天要把"订单服务"换成"新订单服务",前端一行代码都不用改,只在网关改一下路由配置即可——这正是 C2"构件不直接通信、全由连接件路由"带来的松耦合价值。
(9) MDA(模型驱动架构, Model Driven Architecture)
把平台无关性提到更高抽象:CIM(计算无关模型, Computation Independent Model)→ PIM(平台无关模型, Platform Independent Model)→ PSM(平台相关模型, Platform Specific Model)→ 代码,用映射规则自动转换。像万能户型模板——同一张理想户型(PIM),换到北京/上海(PSM)各自落地成施工图,不用重画。换平台只改 PSM,核心模型不动。
落到软件工程上,最典型的例子是低代码平台(Low-Code)或 UML 建模工具:业务人员先画业务流程图,比如"用户下单、扣减库存",这是 CIM;架构师在低代码平台拖拽出一个"订单表",包含订单号、金额、状态,属于逻辑设计,这是 PIM;点一下"生成代码"按钮,平台根据选定的目标技术栈(如 Java Spring Boot + MySQL)自动生成对应的 Entity 类、SQL 建表语句和 Controller 接口,映射规则自动转换,得到 PSM。哪天公司决定从 Java 迁移到 Go,不必重写业务逻辑,只需把 PSM 的目标平台切换成 Go、重新生成一次代码即可,PIM(核心模型)纹丝不动。
选风格口诀:先判特征(数据驱动?控制流?高并发?可移植?控制回路?),再配对风格。两个坑:把"事件系统"误当"调用-返回",把"黑板"误当"数据库"。
第三步:把系统"评"出来
3.1 为什么非评估不可
架构决策影响深远,必须在实现之前把风险降下来——图纸阶段改一根梁只要一笔,楼盖到 20 层再改就是推倒重来。质量属性常常互相打架:性能要快,安全要验,两者天然冲突,必须显式权衡,不能假装两全。
3.2 用"六要素"把质量说准
质量属性分两类:运行期(性能、可用、安全)和开发期(可修改、可测试、易用)。光说"要快"没用,得用六要素写成可度量场景:
- 刺激源(谁提的)、刺激(要啥)、环境(什么条件下)、制品(作用于哪个对象)、响应(系统怎么做)、度量(用什么衡量)。
像点外卖备注:谁点的、点啥、几点、哪道菜、多久到、超 30 分钟免单——把"要快"翻译成可验收的标准,才能评估。
关键属性与它们的"战术"(达成手段):
- 性能:减需求、资源管理(并发/缓存/复制/调度)、资源仲裁(优先级/队列)。像餐厅翻台——多开窗口(并发)、提前备菜(缓存)、VIP 先上(优先级)。优先级反转用优先级继承解决。度量看响应时间、吞吐率、利用率。
- 可用性:可用度 = MTBF/(MTBF+MTTR),其中 MTBF 为平均无故障时间(Mean Time Between Failures),MTTR 为平均修复时间(Mean Time To Repair);靠检测(心跳/ping)、恢复(冗余/回滚/降级)、避免(事务/监视)。像双发动机飞机——一台熄火,另一台顶上照样飞,修好再并回。分清主动冗余与被动冗余,必要时降级保核心。
- 安全性:抵抗(认证/授权/加密/完整性/不可抵赖)、检测(审计/入侵检测)、恢复。像小区门禁——刷卡(认证)、权限(授权)、监控(检测)、失窃后调录像追责(恢复/审计)。加密强度重要,密钥管理更重要。
- 可修改性:局部化变更(信息隐藏/泛化)、防连锁反应(稳定接口/中介)、推迟绑定(配置/多态/运行时注册)。一句话——想改哪就只改那。像模块化家具:换沙发不拆墙(信息隐藏),螺丝通用(稳定接口),想换布套随时换(推迟绑定)。信息隐藏加稳定接口是高可改性的根本。
- 易用性与可测试性:易用靠反馈/撤销/聚合/提示;可测试靠记录 I/O、接口可访问、内部可监视。可测试性像给电路留测试点——设计时没预留,万用表都夹不上;易用性像遥控器有"返回"键,按错能撤。可测试性是设计时埋点,不是事后补。
3.3 四个"点":评估产出什么
- 敏感点:牵一发动全身的属性(多米诺第一张,推倒它全塌);
- 权衡点:影响多个属性的决策(鱼与熊掌,要鲜就难保存);
- 风险点:还没验证过的决策;
- 非风险点:已论证无虞的部分。
3.4 属性之间的相关性
属性间有协同也有冲突:性能↔安全、可用↔性能、可修改↔性能,常常此消彼长。像预算分配——钱给安全就少给性能,没有白来的好事。评估时要场景化、赋优先级,再取舍。
3.5 效用树、SAAM 与 ATAM
- 质量效用树:把质量目标层层分解——根(总目标)→ 属性类别 → 具体场景(带刺激/响应)→ 优先级。像装修预算表:总预算分到水电/硬装/软装,每项再列具体花销并标"必做/可选"。是 ATAM(架构权衡分析方法, Architecture Tradeoff Analysis Method)的核心工具。
- SAAM(软件架构分析方法, Software Architecture Analysis Method):轻量、以场景为中心——场景生成 → 分类 → 评估 → 出敏感/权衡/风险点。适合评估可修改性与功能覆盖。像请朋友帮忙看方案:列需求,他逐条说哪好改哪难改。
- ATAM(Architecture Tradeoff Analysis Method,架构权衡分析方法):以质量属性为中心、以权衡为重点,四阶段九步,核心是效用树。像正式专家评审会——不只看能不能用,还把性能、安全掰开揉碎比权重。必产出效用树、四类点、以及风险主题。
一句话区分:SAAM 重场景、较简单;ATAM 重属性与权衡、必有效用树。
第四步:把系统"复用"出来
4.1 从复用上升到产品线
复用对象:代码、设计、文档、测试、经验;形式有库、框架、构件、模式、产品线、COTS(商用现货软件, Commercial Off-The-Shelf)。核心理念是别重复造轮子——别人造好的轮子装上就跑。成熟复用不止"捡零件",而是产品线:
软件产品线 = 核心资产库 + 派生出的一类产品。分两步:领域工程(先把通用资产建起来)+ 应用工程(用资产开发具体产品)。像乐高套装——一套通用零件(核心资产),拼出消防车、城堡(不同产品)。顺序:领域工程在前,应用工程在后。
4.2 构件与中间件:复用的两个支柱
- 构件:可独立部署、可替换、接口明确的复用单元(黑盒、信息隐藏)。复用过程:获取 → 适配(包装/桥接)→ 集成 → 管理(构件库)。像标准件——螺丝按国标买,拧得上就能用,不合规就加转接头(适配)。前提是接口稳定、文档完整。
- 中间件:操作系统与应用之间的系统软件,屏蔽异构,提供通信/事务/安全等通用服务。像万能转接头——让不同牌子的模块也能拼一起,是构件运行和通信的支撑平台。
中间件按需求选类型:消息队列(MQ, Message Queue,异步解耦)、事务处理监控器(TP Monitor, Transaction Processing Monitor,保障 ACID(原子性、一致性、隔离性、持久性, Atomicity/Consistency/Isolation/Durability)事务)、对象请求代理(ORB, Object Request Broker,分布式对象,如 CORBA(公共对象请求代理架构, Common Object Request Broker Architecture))、数据访问(ODBC, Open Database Connectivity)、应用服务器(J2EE, Java 2 Platform Enterprise Edition/.NET)。像各种适配器——出国插头转换器(异构屏蔽)、快递柜(异步解耦)、银行清算(事务)。
4.3 构件标准:让零件能即插即用
构件标准定义接口与互操作规范,共性是用 IDL(接口定义语言, Interface Definition Language)/接口描述契约:
- CORBA(IDL+ORB,跨语言跨平台)、
- EJB(企业级 JavaBean, Enterprise JavaBeans)(服务端构件,容器管)、
- COM/DCOM(组件对象模型/分布式组件对象模型, Component Object Model/Distributed Component Object Model)(Windows)、
- Web Services/SOA(面向服务架构, Service-Oriented Architecture)(XML(可扩展标记语言, Extensible Markup Language)/WSDL(Web 服务描述语言, Web Services Description Language),松耦合)。
像插头国标——都按同一规格做才能即插即用;SOA 更像"通用插座",谁都能接。
汇总:架构是取舍的艺术
4+1 视图教怎么把系统画清楚;架构风格教怎么把系统搭对路;质量属性与 ATAM 教怎么同时追"性能、可用、安全、可修改"这几只兔子,并看清它们互相打架;产品线、构件、中间件教怎么别重复造轮子。
面对一个新系统,先在心里问三句:
- 该用什么风格立骨架?
- 最看重哪个质量属性、愿意牺牲哪个?
- 哪些零件能直接复用、不必自己造?
三句问清楚,系统就从"一堆需求"变成"一个有主张的设计"。


浙公网安备 33010602011771号