软件架构导论

从设计模式到软件架构

过去十节课,我们走完了 GoF 二十多种设计模式——策略、工厂、状态、观察者、桥接、装饰、代理……每一种都是把「具体类」之间的关系拧到刚好的工艺。复合模式那一节,我们让五种模式在「鸭子模拟器」里协作起来,已经隐约触及了系统级的设计。

但当系统从「几十个类」扩展到「几百个模块、几千名工程师、十几年的演化」时,仅仅会用模式是不够的。你需要回答的不再是「这个类该不该实现这个接口」,而是:

  • 这个系统由哪些大块组成?它们怎么通信?
  • 哪些设计决策一旦定下来就改不动了?
  • 性能、可用性、安全性这些「非功能」需求,在哪里落地?
  • 八十名工程师怎么并行协作而不互相踩脚?

这些问题的答案,住在一个比设计模式更高的抽象层——软件架构(Software Architecture)。设计模式是单体建筑里的雕花门窗,软件架构是整个城市的规划图。本节是 SysArch 板块的开篇,我们先建立起架构的概念框架:什么是架构、为什么重要、架构师做什么、后续会学什么。

软件工程是什么样的工程

讨论架构之前,先退一步看「软件工程」本身。

人类与世界互动的两条路径,一条是科学(Science),一条是工程(Engineering)。科学研究既存事物——天文学研究恒星,生物学研究生命,化学研究物质——靠的是观察、测量、实验。工程创造从未存在之物——金字塔、轮船、汽车、电话——靠的是构造(Construction)和评估(Evaluation)。

flowchart TD
    H[人类与世界的互动]
    H --> S[科学之路]
    H --> E[工程之路]

    S --> SO[研究既存之物<br>天文/生物/化学]
    SO --> SM[观察 / 测量 / 实验]

    E --> EO[创造新生之物<br>金字塔/轮船/汽车]
    EO --> EM[构造 / 评估]

    SM -.相互滋养.-> T[更好的工具与认知]
    EM -.相互滋养.-> T

    classDef human fill:#f3e5f5,stroke:#4a148c,stroke-width:2px
    classDef science fill:#e3f2fd,stroke:#1565c0,stroke-width:2px
    classDef engineering fill:#e8f5e8,stroke:#2e7d32,stroke-width:2px
    classDef tool fill:#fff3e0,stroke:#ef6c00,stroke-width:2px

    class H human
    class S,SO,SM science
    class E,EO,EM engineering
    class T tool

科学和工程不是对立的,而是相互滋养:科学提供更好的对材料和测量的认知,工程提供更好的工具反哺科学。软件工程站在工程一侧——它的核心活动是「设计与构造前所未有的系统」,并对其行为进行评估。

这个视角解释了为什么软件设计本质上是创造性的。它没有「正确答案」,只有「在给定约束下足够好的方案」。架构正是这种创造性活动中最为关键、影响最深远的部分。

什么是软件架构

「软件架构」是一个被反复定义的术语,业界有两个最常被引用的版本。

软件架构(SEI 定义)

The software architecture of a program or computing system is the structure or structures of the system, which comprise software elements, the externally visible properties of those elements, and the relationships among them.

程序或计算系统的软件架构是该系统的结构或结构集合,由软件元素、这些元素对外可见的性质,以及它们之间的关系所组成。 ——卡内基梅隆大学软件工程研究所(Software Engineering Institute, SEI

软件架构(IEEE 1471-2000 定义)

The fundamental organization of a system, embodied in its components, their relationships to each other and the environment, and the principles governing its design and evolution.

系统的根本组织,体现在其组件、组件之间及组件与环境之间的关系,以及指导其设计与演化的原则中。 ——IEEE 1471-2000《软件密集型系统架构描述推荐实践》

把两段定义剥到骨头,会发现它们说的是同一件事——架构由三类要素构成:

  1. 元素 / 组件(Elements / Components):系统的「积木」,可以是模块、子系统、服务等
  2. 关系(Relationships):组件之间如何连接、通信、依赖
  3. 性质 / 原则(Properties / Principles):组件对外可见的行为约定,以及指导系统演化的规则

注意 SEI 定义中的限定词「对外可见」(externally visible)——架构关心的是组件的接口承诺,而不是组件内部如何实现。这是「黑盒」思维的早期体现,后面我们会反复回到这一点。

架构、设计与结构

「架构」「设计」「结构」三个词在日常使用中常被混用,但在课程语境下需要区分清楚。

架构 vs. 设计

软件架构和软件设计不是两件事,而是同一活动的两个层次:

  • 所有架构都是软件设计,但并非所有设计都是软件架构
  • 「架构」(Architecting)是设计过程的一部分,专指其中最早期、最高层、最难变更的那部分

可以把架构理解为「高层设计」(High-level Design)或「关键设计决策的集合」(A Set of Design Decisions)。一个常用的判别问题是:「如果这个决策错了,要修正它需要重写整个系统吗?」如果答案是「是」,那它属于架构层面的决策。

flowchart TD
    SD[软件设计的全集]
    SD --> A[架构<br>关键的、难改的决策]
    SD --> D[详细设计<br>类、方法、算法]
    SD --> I[实现细节<br>变量命名、代码风格]

    A -.约束.-> D
    D -.约束.-> I

    classDef arch fill:#ffebee,stroke:#c62828,stroke-width:3px
    classDef design fill:#fff3e0,stroke:#ef6c00,stroke-width:2px
    classDef impl fill:#e8f5e8,stroke:#2e7d32,stroke-width:2px
    classDef root fill:#eee,stroke:#495057,stroke-width:2px

    class SD root
    class A arch
    class D design
    class I impl

架构 vs. 结构

「结构」是把系统分解成组件、模块、子系统这一过程的产物。架构在结构之上更进一步,它要回答关于这些组件的三个问题:

维度 问题
接口(Interface) 这个组件能做什么?
通信(Communication) 组件之间如何对话?依赖谁?
职责(Responsibility) 当你请求它时,它具体做什么?

光画一张分模块的方框图——「这是 UI 层、这是业务层、这是数据层」——还称不上架构。只有当你说清楚「UI 层通过 REST API 同步调用业务层」「业务层通过仓库接口读取数据层」「业务层不能直接访问数据库」时,才算把架构讲清楚了。

元素 + 关系 + 性质

架构的三要素也可以这样记:

  • 元素(Elements):组件(components)和连接件(connectors)
  • 关系(Relationships):静态关系(如依赖)和动态关系(如调用流)
  • 性质(Properties):单个元素的、一组元素的、整个系统的对外属性

架构关注的两类内容

架构师的笔触落在两个地方:组件如何通信,以及系统满足哪些非功能需求

通信机制

组件之间的对话有两个维度——数据怎么传控制怎么走

flowchart LR
    C[组件通信]
    C --> D[数据传递]
    C --> F[控制流]

    D --> D1[函数调用<br>Function Call]
    D --> D2[远程方法调用<br>RMI]
    D --> D3[异步消息<br>Message]

    F --> F1[顺序执行<br>Sequential]
    F --> F2[并发/并行<br>Concurrent]
    F --> F3[同步<br>Synchronization]

    classDef root fill:#e3f2fd,stroke:#1565c0,stroke-width:2px
    classDef data fill:#e8f5e8,stroke:#2e7d32,stroke-width:2px
    classDef flow fill:#fff3e0,stroke:#ef6c00,stroke-width:2px

    class C root
    class D,D1,D2,D3 data
    class F,F1,F2,F3 flow

数据传递可以是同进程的函数调用(轻、快、紧耦合),跨进程跨主机的远程方法调用(Remote Method Invocation, RMI),或基于消息队列的异步消息(松耦合、可扩展、但有延迟)。控制流则刻画消息在组件间流动的方式——顺序执行(一步接一步)、并发并行(多个组件同时工作)、同步(两个并发流的会合点)。

不同的通信选择对应着不同的架构风格。同样是「订单服务调用库存服务」,做成函数调用就是单体应用,做成远程调用就是微服务,做成异步消息就是事件驱动架构——三者的可扩展性、容错性、复杂度天差地别。

非功能需求

如果说功能需求回答「系统能做什么」,那么非功能需求(Non-Functional Requirements, NFRs)回答「系统做得有多好」。

非功能需求

非功能需求(NFRs)刻画系统的质量属性、约束条件等「做得多好」的维度,而非「能做什么」。

NFRs 很少出现在功能需求文档里,常被称为架构需求(Architecture Requirements),需要架构师主动去挖掘和确认。

NFRs 大致分三类:

  • 技术约束(Technical Constraints):必须运行在 ARM 架构上、必须兼容 Java 8、必须使用公司既有的消息中间件
  • 业务约束(Business Constraints):上线时间不能晚于六月、预算上限两百万、必须支持五年以内的硬件
  • 质量属性(Quality Attributes):性能、可用性、安全性、可修改性、可测试性……

想想看

你能列出多少种质量属性?性能、可用性、安全性、可修改性、可移植性、可测试性、可用性(usability)、可扩展性……下一节课我们会系统讨论这些。

NFRs 之所以是架构师的核心关注点,是因为它们无法在某个组件内部「局部解决」——你没法靠优化一段代码让整个系统变得「高可用」。可用性、性能、安全性这些属性是从架构层面渗透到每个组件的全局性质。

设计是一种抽象

架构对设计的另一个核心贡献是抽象(Abstraction)。

架构提供一个比详细设计更高的抽象视角:

  • 隐藏具体设计的复杂度和实现细节
  • 架构元素与软件元素之间,不一定存在直接的一一映射——一个架构组件可能对应几十个类,一个类也可能跨多个架构组件

抽象有两种风格:

  • 黑盒设计(Blackbox Design):只描述组件做什么、对外有哪些接口,不关心内部如何实现
  • 白盒设计(Whitebox Design):除了对外行为,还描述内部结构和实现思路

架构层面通常更偏黑盒——它给出系统的结构和交互的非正式描绘,体现架构所蕴含的设计哲学,但不规定每个组件的内部实现。

为什么设计需要抽象?

一个架构师的脑容量是有限的,一个项目相关方的耐心也是有限的。如果一上来就把整个系统铺开到代码细节,没人能看清整体。抽象让我们能在不同层次上谈论系统:和老板谈业务模块、和架构师谈接口契约、和工程师谈类设计。每一层都只暴露当前对话需要的复杂度。

多视图:架构的「平面图」

一栋建筑有楼层平面图、立面图、电气图、给排水图、暖通图——每张图回答不同问题,没有哪张图能独自描述整栋建筑。软件架构是同样复杂的产物,需要多张「图」从不同视角共同描绘。

flowchart TD
    B[一栋建筑的图纸]
    B --> B1[平面图]
    B --> B2[立面图]
    B --> B3[电气图]
    B --> B4[给排水图]
    B --> B5[暖通图]

    A[一个软件架构]
    A --> A1[逻辑视图<br>Logical]
    A --> A2[过程视图<br>Process]
    A --> A3[物理视图<br>Physical]
    A --> A4[开发视图<br>Development]
    A --> A5[用例视图<br>+1]

    classDef building fill:#fff3e0,stroke:#ef6c00,stroke-width:2px
    classDef software fill:#e3f2fd,stroke:#1565c0,stroke-width:2px

    class B,B1,B2,B3,B4,B5 building
    class A,A1,A2,A3,A4,A5 software

最经典的多视图建模框架,是 Philippe Kruchten 在 1995 年提出的 4+1 视图模型(4+1 View Model)。

Kruchten 的 4+1 视图模型

一个软件架构可以从五个互补的视角描述,每个视角回答不同的问题:

  • 逻辑视图(Logical View):刻画架构上重要的元素及其关系——回答「系统由哪些功能模块组成」
  • 过程视图(Process View):刻画并发与通信元素——回答「运行时有哪些进程/线程,如何交互」
  • 物理视图(Physical View):刻画主要进程和组件如何映射到硬件——回答「部署在哪些机器上」
  • 开发视图(Development View):刻画软件组件的内部组织(如配置管理工具中的结构)——回答「代码仓库怎么组织、模块怎么打包」
  • 架构用例(Use Cases):捕获架构需要满足的需求场景,是贯穿其他四个视图的「+1」

为什么需要多个视图?因为不同的相关方(Stakeholder)关心不同的问题。运维关心物理视图,开发关心开发视图,业务方关心用例视图。一个完整的架构文档需要覆盖所有这些维度。

后续课程会反复用到 4+1 视图——画一张架构图时要先问自己「这是哪个视图」,否则容易把所有信息塞进一张乱糟糟的图,谁都看不懂。

怎么开展设计

当面对一个新系统时,架构师手里有一组通用的设计策略可以反复使用:

策略 直觉
分解(Decomposition) 把大问题切成多个小问题
抽象(Abstraction) 忽略当前层次不关心的细节
逐步求精(Stepwise Refinement) 「分而治之」,每一步只解决一个层次
生成与测试(Generate and Test) 先草稿出方案,再用质量场景验证
迭代(Iteration) 增量式精化,承认第一稿一定不完美
复用(Reusable Elements) 借用既有的组件、模式、框架

这些策略不是互斥的——一个架构通常先分解再抽象,逐步求精中迭代,并积极复用。复用是其中最具杠杆效应的一项,模式(Patterns)和战术(Tactics)就是为复用而存在的成熟方案,后续几节课会重点讲。

通用设计模型

把前面的策略形式化,可以画出软件设计的通用流程:

flowchart TD
    R[需求规格<br>Requirements Specification]
    C[约束<br>资源/组织/经验/已有软件复用]
    P[设计过程<br>Design Process]
    D[设计师的决策<br>Designer's Decisions]
    PD[程序描述<br>Program Description]

    R --> P
    C --> P
    P --> D
    D --> PD

    classDef input fill:#e3f2fd,stroke:#1565c0,stroke-width:2px
    classDef process fill:#fff3e0,stroke:#ef6c00,stroke-width:2px
    classDef output fill:#e8f5e8,stroke:#2e7d32,stroke-width:2px

    class R,C input
    class P process
    class D,PD output

设计的输入有两类:显式的需求规格(需要做什么),和隐式的约束(资源限制、组织结构、团队经验、可复用的既有软件)。设计过程把这些输入加工成「设计师的决策」,再具体化为「程序描述」。

注意:约束往往比需求更隐蔽,也更容易被忽略。「我们团队没人会 Rust」这样的现实约束,对架构选型的影响可能比「需要支持每秒一万次查询」更大。

软件设计本身可以拆成更细的过程:

flowchart LR
    R0[需求]
    R1[需求规格]
    A[分析需求<br>构造黑盒模型]
    L[逻辑设计细节]

    R0 --> R1
    R1 --> A
    A --> L

    classDef req fill:#e3f2fd,stroke:#1565c0,stroke-width:2px
    classDef ana fill:#fff3e0,stroke:#ef6c00,stroke-width:2px
    classDef des fill:#e8f5e8,stroke:#2e7d32,stroke-width:2px

    class R0,R1 req
    class A ana
    class L des

第一步先把模糊的需求精化成可写下来的规格;第二步分析需求并构建系统的「黑盒模型」——只关心系统对外的行为;第三步才是把黑盒拆成内部的逻辑组件。这个流程刻意把「做什么」和「怎么做」分开,避免一上来就钻到实现细节里。

架构活动:架构师的工作清单

把上面的过程具体到架构层面,架构师要做的事情大致是:

  • 为系统建立商业理由(Business Case)——为什么要做?谁出钱?给谁用?
  • 理解需求——功能需求 + 非功能需求 + 约束
  • 创建并选择架构——多个候选方案,从中权衡选择
  • 沟通架构——向利益相关方(包括开发者)传达架构
  • 分析或评估架构
    • 整体方法学(如 ATAM 等综合评估方法)
    • 质量属性专项技术
  • 实现架构——把决策落实到代码
  • 保证架构一致性(Conformance)——确保实现没有偏离架构
flowchart TD
    B[商业理由]
    R[理解需求]
    C[创建/选择架构]
    Co[沟通架构]
    E[分析/评估架构]
    I[实现架构]
    Cf[保证一致性]

    B --> R --> C --> Co --> E --> I --> Cf
    Cf -.反馈.-> C

    classDef early fill:#e3f2fd,stroke:#1565c0,stroke-width:2px
    classDef mid fill:#fff3e0,stroke:#ef6c00,stroke-width:2px
    classDef late fill:#e8f5e8,stroke:#2e7d32,stroke-width:2px

    class B,R early
    class C,Co,E mid
    class I,Cf late

最后一步「保证一致性」常被忽略,但极其关键——再好的架构图,如果代码实际上没遵守它,等于没有架构。这就是为什么后续会专门讨论架构评审、静态分析、ADL(Architecture Description Language)等工具:它们让「图」和「代码」可以被机械地对比。

架构过程的高层视角

把上面的活动拼成一张大图,整个软件架构过程长这样:

flowchart LR
    SH[利益相关方<br>Stakeholders]
    RC[需求与约束<br>Requirements,<br>Constraints]
    QA[优先级化的质量属性场景<br>Prioritized Quality<br>Attribute Scenarios]
    ASR[规约 ASR<br>Architecturally<br>Significant Requirements]
    PT[模式与战术<br>Patterns & Tactics]
    AV[候选视图的草图<br>选择并组合]
    AE[架构评估<br>Architecture Evaluation]

    SH --> RC
    RC --> QA
    QA --> ASR
    ASR --> PT
    PT --> AV
    AV --> AE
    AE -.迭代.-> ASR

    classDef stake fill:#f3e5f5,stroke:#4a148c,stroke-width:2px
    classDef req fill:#e3f2fd,stroke:#1565c0,stroke-width:2px
    classDef pat fill:#fff3e0,stroke:#ef6c00,stroke-width:2px
    classDef view fill:#e8f5e8,stroke:#2e7d32,stroke-width:2px
    classDef eval fill:#ffebee,stroke:#c62828,stroke-width:2px

    class SH stake
    class RC,QA,ASR req
    class PT pat
    class AV view
    class AE eval

几个关键术语先记住,后面几节会系统展开:

  • ASR(Architecturally Significant Requirements,架构上显著的需求):那些会决定架构走向的需求,往往不是功能需求
  • 质量属性场景(Quality Attribute Scenarios):把抽象的质量属性写成可验证的具体场景,例如「在峰值负载下,95% 请求的响应时间小于 200 毫秒」
  • 战术(Tactics):实现某个质量属性的可复用设计技巧,比单个模式更细粒度

整个过程不是线性的,评估的结果会反馈回 ASR 的修订,迭代多轮才能收敛。

架构生命周期

把过程压缩成最简版本,就是三个阶段循环:

flowchart LR
    D[架构设计<br>Architectural Design]
    E[架构评估<br>Architectural Evaluation]
    I[架构实现<br>Architectural Implementation]

    D --> E --> I -.演化.-> D

    classDef stage fill:#e8f5e8,stroke:#2e7d32,stroke-width:2px
    class D,E,I stage

每一轮迭代都包括设计、评估、实现三步——这是架构持续演化的基本节律。

架构师:从建筑师到软件架构师

「架构师」(Architect)这个职业最早属于建筑业。1972 年,建筑历史学家 James Marston Fitch 留下一句话:

Architects design structures to meet human needs.(架构师设计结构以满足人类的需求。)

软件架构师与建筑架构师的角色高度类似——只是把「钢筋混凝土」换成了「类、组件、协议」:

  • 倾听客户,理解他们的全部需求(不只是嘴上说的那些)
  • 审视可行性——技术可行、预算可行、时间可行
  • 形成实用的愿景,画出蓝图
  • 监督建造过程,确保实施符合蓝图
  • 在设计变更、危机和模糊性的「风暴」中保持愿景

软件架构师监督的「建造工人」是程序员、工程师、设计师。

历史上几位著名的软件架构师:

名字 身份
Bill Gates 微软首席软件架构师
Tim Berners-Lee 万维网(WWW)发明人和首席架构师
Roy Fielding REST(Representational State Transfer)的提出者

架构师每天在做什么

理论上的角色描述容易让人觉得架构师就是「画图的」,但实际工作要复杂得多:

  • 联络人(Liaison)
    • 在客户、技术团队、业务/需求分析师之间传话
    • 与管理层、市场部门对接
  • 软件工程
    • 推行软件工程的最佳实践
  • 技术专家
    • 对所在技术领域有深入理解
  • 风险管理
    • 识别设计、技术选型上的风险并提前应对

简而言之,架构师既是技术专家,也是组织里的「翻译官」和「风险预警员」。光懂技术做不好架构师——你还得懂业务、懂人。

架构为什么重要

这是本节最重要的部分——理解架构的价值,是后面所有内容的动机。

架构的角色

软件架构在系统的整个生命周期中扮演四个核心角色:

  1. 早期决策的固化:架构是第一批表达「需求如何被满足」的产物。它体现的是项目最早期的设计决策,而最早期的决策也是最难变更的——它们值得最仔细的考虑。
  2. 产品线工程的基石:成功的产品线工程(Product Line Engineering)依赖于一个统一的架构——用更小的成本、更短的时间、更低的风险开发一系列相似的系统。一个架构对应许多系统。
  3. 新人理解系统的入口:当某人开始接手一个系统时,他最先要看的就是架构
  4. 维护与修改的参照框架:架构是后续做维护决策时的判断依据。

架构的重要性

进一步展开,架构在六个维度上具有不可替代的价值。

1. 沟通的载体

架构是各方识别和谈判利益冲突的参照框架

  • 与用户协商需求时
  • 让客户了解进展、成本时
  • 实施管理决策和资源分配时

没有架构图,开会就只能靠「想象」——每个人脑子里的系统都不一样,争论起来像盲人摸象。

2. 早期设计决策的载体

架构约束实现和开发者:

  • 实现必须符合架构
  • 资源分配决策约束着各组件的实现方式

这种约束不是限制,而是保证一致性的脚手架

3. 决定组织结构

架构反过来决定开发与维护的组织结构。康威定律(Conway's Law)的另一面:

用途 说明
团队划分 一个组件一支团队
预算与计划 按组件分配资源
工作分解结构(WBS Work Breakdown Structure 的基础
文档组织 文档按架构层次组织
配置管理(CM)库 代码仓库按组件划分
集成与测试 测试边界沿组件边界划分
维护 维护团队按组件分工

4. 推动或阻碍质量属性

架构促进或阻碍可修改性、安全性、可用性等质量属性的实现:

  • 架构影响质量,但不保证质量——还有很多其他因素在起作用
  • 这是架构「能做到什么、做不到什么」的关键边界

5. 关于变更的讨论平台

架构引发「未来可能怎么变」的讨论。这条尤其重要,因为:

80% 的成本来自部署后

一个系统大约有 80% 的工作量发生在部署之后——维护、修改、扩展、迁移。如果架构没有为这些变化预留空间,后期的成本会以指数级膨胀。

架构把变更分为三类,从局部到全局:

flowchart LR
    L[局部变更<br>Local]
    NL[非局部变更<br>Non-local]
    A[架构性变更<br>Architectural]

    L -->|影响范围扩大| NL
    NL -->|影响范围扩大| A

    classDef local fill:#e8f5e8,stroke:#2e7d32,stroke-width:2px
    classDef nonlocal fill:#fff3e0,stroke:#ef6c00,stroke-width:2px
    classDef arch fill:#ffebee,stroke:#c62828,stroke-width:3px

    class L local
    class NL nonlocal
    class A arch
类型 含义 成本
局部变更(Local) 单个组件的修改
非局部变更(Non-local) 多个组件的修改
架构变更(Architectural) 系统的基本结构、通信、协调机制的修改 极高

一个好的架构能让大多数变更停留在「局部」层级,避免轻易触发架构变更。这就是「为变化而设计」的具体含义。

6. 可迁移、可复用的抽象

最后,架构本身就是一种一对多映射的资产:

  • 一个架构可以被多个系统复用——架构是可迁移的
  • 整个产品线可以共享同一个架构——架构是产品共性的基石
  • 系统可以通过整合独立开发的组件来构建——这就是 CBSE(Component-Based Software Engineering,基于组件的软件工程)
flowchart TD
    A[一个架构]
    A --> S1[系统 1]
    A --> S2[系统 2]
    A --> S3[系统 3]
    A --> S4[系统 4]

    S1 -.同款架构.-> P[产品线]
    S2 -.同款架构.-> P
    S3 -.同款架构.-> P
    S4 -.同款架构.-> P

    classDef arch fill:#ffebee,stroke:#c62828,stroke-width:3px
    classDef sys fill:#e3f2fd,stroke:#1565c0,stroke-width:2px
    classDef line fill:#e8f5e8,stroke:#2e7d32,stroke-width:2px

    class A arch
    class S1,S2,S3,S4 sys
    class P line

架构的现实样貌

抽象概念终归要落到具体例子。课件里给了几个示意性的例子,我们简单看一下它们的形状。

移动电话系统

移动电话系统的架构涉及资源管理(Resource Management)、切换决策(Handoff Decision)、切换失败处理(Handoff Failure Actions)等组件,以及它们之间的协作关系。这是一个典型的实时控制系统架构——核心关注点是资源调度和故障容错。

洗衣机系统

洗衣机的嵌入式系统也有架构——传感器、控制器、电机驱动、用户界面之间的关系。这个例子说明架构存在于一切「软件密集型系统」中,不只是云端服务器。

AI 护栏架构

最具时代特色的例子——AI 系统的护栏架构(Guardrail Architecture):

flowchart TD
    I[输入护栏<br>Input Guardrails]
    R[RAG 护栏<br>RAG Guardrails]
    EX[执行护栏<br>Execution Guardrails]
    M[多模态护栏<br>Multimodal Guardrails]
    O[输出护栏<br>Output Guardrails]

    F[基础模型<br>Foundation Models]
    N[窄域 AI 模型<br>Narrow AI Models]

    I --> F
    R --> F
    F --> EX
    F --> M
    F --> O

    F <--> N

    classDef guard fill:#fff3e0,stroke:#ef6c00,stroke-width:2px
    classDef foundation fill:#e3f2fd,stroke:#1565c0,stroke-width:2px
    classDef narrow fill:#f3e5f5,stroke:#4a148c,stroke-width:2px

    class I,R,EX,M,O guard
    class F foundation
    class N narrow

输入端有输入护栏RAG 护栏(Retrieval-Augmented Generation,检索增强生成的护栏),中间是基础模型窄域 AI 模型的协作,输出端有执行护栏多模态护栏输出护栏。这种架构正是为应对大模型的安全、合规、可靠性这些「质量属性」而生——和洗衣机的故障容错本质上是同一类问题,只是放在了 AI 的语境下。

这些例子告诉我们:架构不是某个特定领域的专属概念任何复杂的软件密集型系统都需要架构,从 IC 卡到航天器,从单机游戏到 ChatGPT。

知识地图:本课程会教什么

架构是一个庞大的话题,本课程会按以下知识区域展开。

软件设计与架构知识体系

flowchart TD
    SDA[软件设计与架构]

    SDA --> BC[设计基本概念]
    BC --> BC1[通用设计概念]
    BC --> BC2[软件生命周期上下文]
    BC --> BC3[设计过程:策略/角色/活动]

    SDA --> KI[关键技术议题]
    KI --> KI1[并发]
    KI --> KI2[控制与事件处理]
    KI --> KI3[分布]
    KI --> KI4[异常处理]
    KI --> KI5[交互系统]
    KI --> KI6[持久化]

    SDA --> SA[结构与架构]
    SA --> SA1[架构结构与视点]
    SA --> SA2[架构风格与模式<br>宏观架构]
    SA --> SA3[设计模式<br>微观架构]

    SDA --> DM[设计方法]
    DM --> DM1[架构方法<br>如 ADD]
    DM --> DM2[设计方法<br>如 DDD]

    SDA --> QE[质量分析与评估]
    QE --> QE1[质量属性]
    QE --> QE2[评估方法<br>如 ATAM]
    QE --> QE3[静态/动态分析]
    QE --> QE4[仿真与原型]
    QE --> QE5[度量与指标]

    SDA --> MR[建模与表示]
    MR --> MR1[ADL]
    MR --> MR2[UML]
    MR --> MR3[Views & Beyond]
    MR --> MR4[ACME / Rapide 等]

    classDef root fill:#ffebee,stroke:#c62828,stroke-width:3px
    classDef level1 fill:#e3f2fd,stroke:#1565c0,stroke-width:2px
    classDef level2 fill:#e8f5e8,stroke:#2e7d32,stroke-width:2px

    class SDA root
    class BC,KI,SA,DM,QE,MR level1
    class BC1,BC2,BC3,KI1,KI2,KI3,KI4,KI5,KI6,SA1,SA2,SA3,DM1,DM2,QE1,QE2,QE3,QE4,QE5,MR1,MR2,MR3,MR4 level2

注意「架构风格与模式」是宏观架构(macro-architecture),而前十节学的「设计模式」是微观架构(micro-architecture)——两者都是「模式」,但作用层次不同。

几个关键术语先建立印象:

  • ADD(Attribute-Driven Design):属性驱动设计,一种面向质量属性的架构设计方法
  • DDD(Domain-Driven Design):领域驱动设计,一种面向业务领域建模的设计方法
  • ATAM(Architecture Trade-off Analysis Method):架构权衡分析方法,SEI 提出的架构评估方法学
  • ADL(Architecture Description Language):架构描述语言,用形式化语言描述架构(如 ACME、Rapide)

后续课程预告

课程 主题
本节(Lecture 1) 软件架构概念导论
Lecture 1/2 质量属性与架构战术
Lecture 3 架构模式
Lecture 4/5 架构设计方法(ADD
Lecture 6 微服务架构
Lecture 7 软件架构课程复习

每一节都会回到本节建立的概念框架——架构由元素、关系、性质组成;架构关注通信、NFRs、抽象;架构活动是设计、评估、实现的循环;架构的价值在于沟通、约束、组织、质量、变更、复用。这些都是后续讨论的脚手架。

小结

本节是 SysArch 板块的开篇,我们从「设计模式之外」迈入了更高层次的软件设计。核心要点:

  • 软件工程是「创造新事物」的工程活动,架构是其中最早期、最关键、最难变的部分
  • 软件架构 = 元素(组件) + 关系 + 性质,且只关心对外可见的接口承诺
  • 架构 ⊂ 设计,但不等于详细设计;架构关注结构、通信、非功能需求、抽象
  • 架构是多视图的——4+1 视图(逻辑/过程/物理/开发 + 用例)刻画不同维度
  • 架构师既是技术专家,也是联络人和风险管理者
  • 架构的价值贯穿系统生命周期:沟通载体、决策固化、组织依据、质量推动、变更框架、复用基础

下一节我们会深入讨论质量属性(Quality Attributes)——把「系统做得有多好」从抽象概念变成可写下来、可验证的场景。这是架构设计真正落地的入口。