专业的编程技术博客社区

网站首页 > 博客文章 正文

Diagrams as Code —— PlantUML,不再“画”图

baijin 2024-12-09 11:20:19 博客文章 7 ℃ 0 评论

作为开发人员,我们在软件开发生命周期的不同阶段,经常需要画各种图来讨论问题和解决方案的复杂部分,或者将各种图作为文档来作为组织资产的一部分,其中UML图被作为常见的工具之一。画UML图的工具有很多,例如EA,drawio,StarUML等,当然最简单的方式,就是用PPT画UML图。但使用这类工具有以下几个缺点:

  • 排版需要花费大量的时间
  • 需要特定的软件工具编辑,因此源代码几乎没有可读性
  • 源文件被作为SCM(SVN, GIT)管理并在团队里协作时,处理冲突是一个非常棘手的问题
    Diagrams as Code(即用编写代码的方式来生成图)就是用来解决以上问题的,本文将结合实际案例介绍如何应用PlantUML。

PlantUml简介

PlantUML可以通过简单的文本描述创建出各种 UML 图。从序列图到部署图等等,它提供了一种创建复杂系统可视化表示的简单方法。

目前支持的UML图有:

  • 序列图
  • 用例图
  • 类图
  • 对象图
  • 活动图
  • 组件图
  • 部署图
  • 状态图
  • 定时图

同时它还支持非UML图:

  • JSON 数据
  • YAML 数据
  • EBNF(扩展巴科斯范式)
  • Regex(正则表达式)
  • 网络图 (nwdiag)
  • Salt(线框图形界面或 UI 模型)
  • Archimate 图
  • SDL(规范和描述语言)
  • Ditta图
  • 甘特图
  • 年表图
  • 思维导图
  • WBS(工作分解结构)
  • 数学符号(AsciiMath、JLaTeXMath)
  • 实体关系 (ER) 图

PlantUML序列图应用

在做业务建模时,BA需要分析业务流程,这时候可以使用序列图

以上是一个真实的问诊系统的预约流程:问诊系统代号为Samoyed,医生在问诊系统维护预约计划表,病人使用问诊系统预约看病。
plantuml在序列图语法上,支持业务建模一些关键词,如actor, participant, entity等,你可以用这些关键词声明变量。例如,声明actor病人:

actor "病人" as patient
entity "Samoyed" as samoyed
participant "医生" as doctor
entity "处方系统" as prescription_system
participant "药房服务员" as pharmacy_attendant

病人在系统上预约:

patient -> samoyed: 预约

时序图的核心语法差不多就是这样。

本例完整的plantuml代码如下:

@startuml
actor "病人" as patient
entity "Samoyed" as samoyed
participant "医生" as doctor
entity "处方系统" as prescription_system
participant "药房服务员" as pharmacy_attendant

doctor -> samoyed: 制定预约计划

patient -> samoyed: 查看近一周预约列表
samoyed --> patient
patient -> samoyed: 预约
samoyed -> samoyed: 登记
samoyed --> patient: 预约成功
patient -> samoyed: 填写问诊单
samoyed --> patient

doctor -> samoyed: 查询下一个待诊预约单
doctor -> patient: 呼叫下一个待诊病人

patient -> doctor: 看病
doctor -> samoyed: 查看问诊单
doctor -> prescription_system: 录入问诊单
prescription_system -> prescription_system: 建议病症处方
prescription_system --> doctor: 病症处方
doctor -> doctor: 诊断
doctor -> prescription_system: 开处方
prescription_system -> prescription_system: 打印处方
prescription_system --> doctor: 处方单
doctor -> samoyed: 完成预约单
doctor --> patient: 处方单

patient -> pharmacy_attendant: 取药
pharmacy_attendant --> patient: 药品

patient -> pharmacy_attendant: 支付
pharmacy_attendant -> pharmacy_attendant: 找零
pharmacy_attendant --> patient

@enduml

PlantUML用例图应用

在分析业务流程后,我们需要分析系统需要支持哪些功能,这时候会使用用例图来捕捉。

上图是我们通过分析时序图上问诊系统Samoyed的端点,识别到问诊系统需要支持哪一些操作,得到一系列用例。
PlantUML声明Actor:

:病人: as patient
:医生: as doctor

在系统边界内声明用例:

rectangle "Samoyed" {
(预约) as (book)
}

病人预约用例:

patient --> (book)

本例完整的plantuml代码如下:

@startuml
:病人: as patient
:医生: as doctor
rectangle "Samoyed" {
(制定预约) as (create_treatment)
(查看近一周预约列表) as (get_latest_treatments)
(查询下一个待诊预约单) as (get_next_reservation)
(预约) as (book)
(完成预约) as (complete_order)
(提交问诊单) as (commit_order)
(查看问诊单) as (view_order)
}

patient --> (get_latest_treatments)
patient --> (book)
patient --> (complete_order)
patient --> (commit_order)

doctor --> (get_next_reservation)
doctor --> (create_treatment)
doctor --> (view_order)

@enduml

PlantUML类图应用

在识别到用例之后,BA会编写系统用例规格,我们就需要进一步分析系统用例规格,得到领域模型,可以使用UML类图来表达领域模型。

plantuml声明实体类订单和问卷:

class Order {
    - date
}
class QA {
    - question
    - answer
}

表达订单和问卷的一对多关联关系:

Order - " * " QA

- 表示关联,其后可以跟着用双引号描述多重性。
使用聚合:

Order o-- Prescription

使用组合:

Treatment *- Availability

如果表达泛化(继承),则可以使用 ^--

本例完整的plantuml代码如下:

@startuml

class Doctor {
}
class Patient {
}
class Treatment {
    - date: LocalDate
    - range : TimeRange
}
class Availability {
    - capacity : int
    - numberAvailable : int
}

Treatment -- Doctor
Treatment *- Availability

class Reservation {
    - status
}
enum Category {
    A,
    B,
    C
}

Reservation -- Patient
Reservation - Category
Reservation o-- Order

class Order {
    - date
}
class Profile {
    - name
    - gender
    - mobile
    - address
    - age: int
    - married : boolean
    - height
    - weight
}
class Disease {
    - history
    - current
    - allergy
}
class QA {
    - question
    - answer
}
class Prescription {

}

Order -- Patient
Order -- Profile
Order -- Disease
Order - " * " QA
Order o-- Prescription
Prescription -- Doctor

@enduml

PlantUML状态图

仅有领域模型有时候还不足以帮助团队理解,在一些关键模型上需要指导它们的生命周期,这时候就需要用到状态图。

上图是Order的生命周期所经历的状态,分别为初始、已预约、已完成、已取消和结束状态。
plantuml以
[*] 表示初始和结束状态,表达状态流转:

[*] --> Reserved
Reserved --> Completed: complete

本例完整的plantuml代码如下:

@startuml
  [*] --> Reserved
  Reserved --> Completed: complete
  Reserved --> Canceled: cancel
  Completed --> [*]
  Canceled --> [*]
@enduml

如何渲染出图?

说了这么多,关键问题来了,如何渲染出图片呢?主要以下几种方式:

  • 在线网站,如https://plantumleditor.com/webedit/
  • 部署在本地、服务器或者私有云,使用web方式访问
  • Visual Studio Code,安装plantuml插件
  • Jetbrains系列产品,也支持安装plantuml插件,如Idea, Rider, WebStorm等等

以上几种都可以即时在屏幕上渲染出图片,也支持导出图片。如果你发现排版上需要调整,可以通过简单的把 - 调整为 -- 或者 --- 即可搞定,plantuml在渲染时会自动调整线条长度并重新布局。

总结

本文结合实际案例,介绍了PlantUML时序图、用例图、类图和状态图如何应用在软件开发生命周期的不同阶段,这4种图也是最常用的工具。PlantUML还支持其他非常多图表,期待你来挖掘。
Tips: 记得把PlantUML代码放到SCM工具(如git)以支持团队协作。

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表