UML图到底要画几张?删掉37张图后,我总结的「三图原则」(附PlantUML 5分钟上手)

🔑 关键词:UML, PlantUML, 类图, 时序图, 软件设计

📖 摘要:接手老项目时收到37张导成JPG的UML图,半年只有5张被打开过。这篇不讲教科书的14种图,讲我实际用过8年剩下的3张图,外加PlantUML 5分钟上手步骤和7个高频踩坑记录。

UML图到底要画几张?删掉37张图后我总结的「三图原则」

图片

一、先说个丢人的事

2019年我接手一个电商中台项目,前任架构师交接时甩给我一个压缩包,解压出来37张UML图,全是JPG,命名从 图1.jpg 一路排到 图37.jpg。那次交接会开了两个小时,我一个类名都没看清——图是从4K屏上直接截的,塞进A4纸里类名大概三号字。后来我自己做了个很土的统计(就是挨个问同事),半年内这37张图被真正点开看过的只有5张,剩下32张躺在Wiki第三层目录里,站内搜索都搜不出来,因为标题叫「设计文档V2最终」。

这件事之后我对UML的看法就变了。UML 2.5定义了14种图,7种结构图7种行为图,我当年软考背得滚瓜烂熟,但工作8年真正动手画过的就三种:类图、时序图、状态机图。用例图我也画过,画完发现它本质上是给产品经理和甲方看的,跟工程师之间的沟通效率关系不大——你把用例图画得跟花一样,后端该不懂的还是不懂,因为他不关心actor是谁,他关心的是这个接口失败了要不要重试。

二、14种图和现实的差距,摆个表

先把结论撂这儿:UML 2.5那14种图里,能活着进Git仓库的不到三分之一。我按自己的使用频率列了个表,纯个人数据,不权威:

图类型 我最近3年画过几次 主要问题
类图 约40次 超过25个类就看不清了
时序图 约70次 画一次改三次,维护成本最高
状态机图 约15次 订单/工单场景真香,其他场景用不上
用例图 3次 甲方爱看,工程师不看
活动图 5次 流程图工具能替代,没必要上UML
部署图 2次 一次是画给运维看的,一次是画给领导看的
通信图/时序图旧版 0次 没人用,真的
其余7种 0次 我甚至想不起全名

图片

对比一下就更明显:教科书花两章讲组合(Composition)和聚合(Aggregation)的实心菱形和空心菱形,我上一次在真实项目里看到有人正确使用空心菱形,是2017年一个从IBM出来的老哥,那是我唯一一次见。大部分团队的实际做法是——全部画成关联线,不标箭头。你说这不规范?是不规范,但它能跑通,而且没人误解。

三、我的「三图原则」

我现在的做法很简单,一个模块最多三张图,多一张都要写理由:

第一张,类图,但只画接口层。 上限15个类,超过就拆模块。类图里只保留字段名和方法签名,不写getter/setter(这玩意儿占了类图60%的面积,信息量为零)。字段类型如果一眼能看出来(比如status),不写类型。

第二张,时序图,只画异常路径。 正常流程代码本身就能读懂,不需要图。真正需要图的是「支付回调超时了会怎样」「库存扣减失败要不要回滚」这种。我画时序图的判断标准是:如果这段逻辑我口头讲需要超过3分钟,就画;3分钟能讲完,不画。

第三张,状态机图,只在状态超过4个的时候画。 一个订单如果只有「待支付/已支付/已取消」三个状态,画图纯属浪费;一旦变成「待支付/支付中/已支付/部分退款/全额退款/已关闭/超时关闭」七个状态,不画图必出bug,这个我有血泪教训——2021年一个退款状态机漏了「部分退款后再次退款」的路径,线上多了十几笔错账。

图片

这三张图加起来,一个中等模块大概40到80行PlantUML代码,渲染出来一张A4能印下。

四、工具横评,这块我踩的坑最多

工具 上手成本 能否Git diff 价格(我印象中的) 适合谁
PlantUML 中,要装Java 能,纯文本 免费 后端、写文档的人
Mermaid 低 能,纯文本 免费 前端、写Markdown的人
draw.io 极低 不能,除非存xml 免费,桌面版也免费 临时画一张发给别人
StarUML 低 不能 3.x之后转订阅了 学生交作业
Sparx EA 极高 不能 Professional版印象里三百美元上下 航空、军工那种要过审计的

我的实际组合是:日常用VS Code + PlantUML插件,快速画个图贴群里用draw.io网页版,别的不碰。draw.io有个隐藏好处是它能直接打开别人发来的vsdx,不用装Visio。

五、PlantUML 5分钟上手(真·5分钟)

步骤我按最小可运行来写,不废话:

图片

  1. 装JDK,8以上就行,java -version 能看到版本号。PlantUML 1.2024.x 要求Java 8+。
  2. VS Code装插件「PlantUML」,作者是jebbs,装完重启一下。
  3. 建议顺手装Graphviz(Windows下是graphviz-12.x的msi),不装也能渲染,但类图布局会难看,箭头会绕圈。
  4. 新建一个 order.puml,粘下面这段:
@startuml
skinparam classAttributeIconSize 0

interface OrderService {
  +createOrder(userId: Long, skuId: Long): Long
  +cancelOrder(orderId: Long): Boolean
}

class OrderServiceImpl {
  -inventoryClient
  -paymentClient
  +createOrder(userId, skuId): Long
}

OrderService <|.. OrderServiceImpl
OrderServiceImpl --> InventoryClient : 扣减库存
OrderServiceImpl --> PaymentClient : 预支付
@enduml
  1. 按 Alt+D 预览,右边出图。要导出PNG就 Ctrl+Shift+P 搜 PlantUML: Export Current Diagram。

图片

一张15个类的类图渲染大概一两秒,我MacBook M1上实测基本瞬开。这段代码丢进Git,别人改了哪个字段,git diff 一行就能看出来——这是图片格式永远做不到的事。

六、7个高频问题和坑

Q1:组合和聚合到底怎么分? 说实话,除了面试,我不建议你花时间在这上面。真要用,记住一句话:整体没了部件还能活,是聚合;不能活,是组合。但实际项目里我建议你全画关联线,把生命周期的判断写到旁边注释里,比一个菱形清楚十倍。

Q2:时序图箭头实线虚线傻傻分不清? 同步调用是实心箭头,返回是虚线空心箭头,异步是开放箭头。记不住就记:有返回值的是虚线。

Q3:Mermaid能替代PlantUML吗? 类图不行,Mermaid的类图不支持嵌套分组,复杂继承关系画出来一团糟;时序图可以,而且GitHub、GitLab原生渲染,不用装任何东西。我的分工是:时序图用Mermaid,类图和状态机用PlantUML。

Q4:图会过时怎么办? 会过时,一定会。我的做法是在图的顶部写一行 最后更新: 2024-05-xx,然后每季度删一次,超过6个月没人动的图直接删掉。别心疼,烂图比没图危害大。

图片

Q5:要不要画中文? 画中文。我见过太多团队用英文类名画图,结果新人看着 OrderAggregateRoot 一脸懵。UML规范不禁止中文,PlantUML对中文支持也没问题,唯一注意是别用生僻字,导出PDF偶尔会变方块。

Q6:图要进代码仓库还是放Wiki? 进仓库。放Wiki的图99%会烂,因为改代码的人不会去Wiki同步。放仓库虽然会让PR多几个文件,但至少改代码的那个人顺手就改了。

Q7:老板要全套设计文档怎么办? 给他三张图加一段文字说明,比37张JPG有用。如果非要37张,那就先画三张,剩下的慢慢补——反正最后也没人看,这话我说的。

七、最后

图的生命周期比代码短得多,这是我这几年最真切的感受。代码可以活五年,图一般活三个月。所以画图的目标不是「画得全」,而是「在它烂掉之前,把该传递的信息传递到位」。

我现在画图前会问自己一句:这张图三个月后还有谁会看?如果答案是「没人」,那我就画在白板上,拍张照发群里,聊完擦掉。真实一点说,白板照片的使用率,比我那37张JPG高多了。

🏷️ 标签: