UML(统一建模语言)是软件的「工程制图标准」,十四种图覆盖结构与行为。它的名声也两极:有人画全套图交作业,有人极度反感「图不等于代码」。本章的立场是:图是思考的脚手架,不是交付物。挑最常用的四种图(用例、类图、时序图、状态图)讲透,配现代的替代品(轻量记号、代码即文档),目标是你「该画图时会画,画完知道画图的边界」。
先立边界。画图的三种正当理由:
不画图的正当理由也明确:图会过期(代码改了图没人维护)、图不参与编译(错误编译器不报)、全套 UML 是体力税。「代码 + 测试 + 少量关键图」是现代默认;需要重图的领域(嵌入式状态机、复杂协议)才全套上。
用例图最简单:人形是角色(actor),椭圆是用例(系统为角色做的事),连线是关系。它回答「系统给谁、提供什么价值」,是需求章(第 3 章)用户故事的图形化。
学生 ──── (借书)
│ ──── (还书)
│ ──── (查询馆藏)
馆员 ──── (催还)
画它的价值在收敛讨论:「报修系统」的用例图一挂白板,「管理员要不要能代学生提交」这类边界问题当场暴露。它不表达流程细节(那是 6.4 时序图的事),保持粗粒度。
类图是面向对象设计(Java 课第 7、8 章)的主图:类名、字段、方法三层框,类间关系四种:
| 关系 | 含义 | UML 记号 | 例 |
|---|---|---|---|
| 关联 association | 持有引用 | 实线箭头 | 订单 →→ 客户 |
| 聚合 aggregation | 整体-部分(可分离) | 空心菱形 | 班级 ◇ 学生 |
| 组合 composition | 整体-部分(同生共死) | 实心菱形 | 订单 ◆ 订单项 |
| 泛化 generalization | 继承 | 空心三角 | 学生 ▷ Person |
组合与聚合的区分(生命周期)在面试高频;对应到代码,组合 = 字段里 new 出来的、随容器生死(Java 的组合默认靠构造里创建),聚合 = 注入进来的外部对象。
画类图的实操要点:只画「讲设计必需」的成员。类图的价值是让 reviewer 看见「职责划分与依赖方向」(第 4 章),不是把 IDE 自动生成的 UML 导出来打印。
时序图是最「值回票价」的行为图:纵向是对象的生命线,横向箭头是一次次方法调用(自上而下按时间),回执用虚线:
用户 Controller Service Repository
│ POST /orders │ │ │
│ ─────────────▶│ createOrder() │ │
│ │──────────────▶│ validate() │
│ │ │───save()────▶ │
│ │ │◀───orderId────│
│ ◀── 201 {id} ─│◀───orderId────│ │
它强迫你回答所有「中间环节」:谁调用谁、参数是什么、返回什么、异常路径怎么走。画一张「下单」的时序图,架构的接口设计(第 4 章)顺手就完成了大半。画完再检查一次依赖方向:Service 认识 Repository,Repository 不认识 Service,反向箭头 = 设计问题。
对象的生命有明确状态且状态迁移有规则时,状态图(state machine)是唯一不丢信息的描述:
[待支付] ──支付成功──▶ [已支付] ──发货──▶ [已发货] ──签收──▶ [已完成]
│──超时──▶ [已取消] │──退款──▶ [已退款]
订单、工单、审批流、游戏角色(待机/攻击/受击),全是状态图的领地。它的工程价值:迁移规则显式化(什么状态能到什么状态),直接变成测试用例(每条边至少一条测试,第 8 章)和数据库的状态字段校验。漏掉状态图的状态机代码,几乎必然出现「已取消的订单被发货」这类事故。
全套 UML 工具(Enterprise Architect)重得离谱,现代工程常用轻量替代:
本 wiki 自己就用 Mermaid 的理念(能文本的不画图)。工具越轻,画图的门槛越低,「画在白板上讨论完就擦」其实是最高频的真实用法。