mermaid 简介
Mermaid 是一个支持 UML 及 C4 等多种建模/图形语言的建模及沟通工具, 官网文档, 同时它也是一个开源项目, Github 地址.
判断一个工具好坏的必要非充分条件是它必须能够随时随地都可使用, Mermaid 有许多插件支持, 包括 github/gitlab/gitea 的插件支持, 以及多种本地编辑器的直接渲染支持(比如 VSCode, idea), 同时提供 mmdc
命令行工具可以将模型渲染为图片.
同时官方提供了一个 Live 编辑器: https://mermaid.live/
如下是一个简单的 mermaid 建模示例:
上图由下方描述得到, 将 markdown 代码块标记为 mermaid
即可:
flowchart LR
a --> b & c--> d
推荐阅读书籍: creating-software-diagramming-techniques - Ashley Peacock
本文主要分为两部分:
- mermaid 工具使用
- 系统建模引导
Part1 Mermaid 工具使用引导
在 VSCode 或官方 Live 网页中均可使用 Mermaid.
参考官方文档: https://mermaid.js.org/intro/n00b-syntaxReference.html
Mermaid 支持的图类型
-
普通图:
-
时序图:
-
甘特图:
-
类图:
-
状态图
-
饼状图
-
其他详见官方文档
语法和配置
Mermaid 语法如下所示:
erDiagram
...
第一行总是有一个用于表示当前图/模型类型的字段, 比如这里的 erDiagram
.
Part2 系统建模引导
即对领域进行建模, 再使用 Mermaid 将模型渲染为图片输出. 在 UML 中可以使用 class diagram 来建立类或领域模型.
UML 部分
识别重要的实体
在创建领域模型时, 需要先列出业务中所有重要实体. 实体即业务中的核心概念. 比如图书管理系统中的概念: book, chapter, author, 并且在实体中有data和logic, 比如 book 有 title, 并且支持计算章节的 word 数量. 实体之间有关系.
创建实体及关系
如下是一个简单关联关系示例:
classDiagram
PC -- Mac
实体间关系的前三种是:
classDiagram
PC -- Mac // 关联
PC *-- CPU // 组合
PC o-- GPU // 聚合
-
关联(association): 关联关系的两个实体可以独立存在, 有各自独立的生命期. 在关联关系中没有 "owner", 实体间仅是 "linked". 可以将关联理解为一个实体会使用另外一个实体.
-
组合(Composition): 描述实体间的组成关系. 组合关系的实体无法独立存在, 一个实体需要依赖另外实体而存在. 上图中, 菱形所在的实体表示该实体持有被组合实体的引用, 也可以将其理解为父子关系(子不能没有父而存在). 并且在组合关系中, "父" 还有 "owner" 的含义.
Mermaid 中描述组合时, 菱形可以写在任意一端, 比如
*--
或--*
, 推荐总是将 owner 端写在左侧. 但有时如果需要手动控制图形展示样式, 可以左右变化. 在 Mermaid 中的注释使用%%
, 即两个百分号进行. -
聚合(Aggregation): 聚合关系是弱组合, 聚合的两端可以独立存在, 一端作为 owner 只持有 "弱引用"
上述即实体间关系的三种类型.
在实践中, 实体间的关系应如何选择? 如下是一些原则:
- 关联关系: 最弱的关系, 关系双方可独立存在, 双方不存在所有者(owner), 仅描述二者可通信.
--
- 聚合关系: 中等强度的关系, 关系双方可独立存在, 有 owner. 弱引用.
o--
- 组合关系: 最强关系, 双方依赖对方存在, 有 owner, 强引用.
*--
实体间关系除了上述外, 还包括:
-
继承关系:
--|>
, 用于描述泛化关系. 比如下面的 2080 显卡继承自 GPU
C4 模型部分
C4 模型用于表达软件架构, 它有 4 层逐步细化的视图层级, 每层包含了针对这个软件系统的不同视图, 主要优点是:
- 让开发者可以快速描述/理解软件系统是如何工作的
- 极大缩小软件架构模型或架构描述与源代码之间的差异
C4 模型包含如下四个视图层级, 越后面的视图描述越细化:
- System Context
- Container
- Component
- Code
C4 模型 - 1 System Context
顶层视图, 是对系统的最高抽象层级描述, 它用于描述用户和软件系统之间, 或此系统和其他系统间的交互, 即这个视图主要描述如下三方的关系(它应该是非技术的):
- 用户
- 本系统
- 其他系统
为建立 C4 模型的 System Context, 可以使用 flowchat :
上述是系统上下文中表示用户的方法, 其中三行的含义:
- 这个上下文元素的标题
- 上下文元素的类型
- 上下文元素的描述
再创建一个此系统的节点:
下一步就是将参与者连接起来:
这里箭头指向表示的是依赖方向, 即用户依赖列表服务, 或用户使用列表服务.
列表服务要能正常工作, 还需要依赖外部提供的服务:
C4 模型 - 2 System's Container
System Context 作为和非技术人员的沟通途径, 而 Container 视图则作为和开发人员的沟通途径, 从这层视图开始, 已经转到了技术细节层面上.
在 C4 模型中, 一个 Container 表示单一的可部署单元, 比如一个独立服务 app, 一个数据库等. 在 Container 视图中, 仍然会表示交互关系, 但关系是从 Container 语义而言的.
可以将 Container 理解为技术视图层级的顶层.
除此以外, 其他服务也需要列出:
C4 模型 3 组件图
组件模型(Component)是对系统的更详细描述, 用于描述每个 Container 的内部细节. 虽然组件这个词在软件工程中有各种含义, 但在 C4 中, 组件代表的是一个较高层级的名空间或模块, 或类似于 Library/Package 的概念, 包含在一个 Container 中.
C4 模型 4 代码图
代码图是 C4 模型的最低层级, 用于表示一个组件内部的代码结构(静态结构).
如果是 upfront 阶段, 不建议手动形成完整代码图, 因为这样太费时且代码的更新速度是很快的. 而如果是成熟工程的理解阶段, 画这个图是有意思的. 这个在后面会讲到.
目前版本 的 Mermaid 已支持 C4 模型语法, 但还在 Beta 未稳定, 因此上述均使用 flowchart 进行.
对数据库的 Schema 设计, 推荐使用 DBML 进行.
代码流的可视化
代码的可视化有两个方面:
- 关于组件交互的动态结构: 使用时序图进行
- 判断
- 循环
- 并发
- 关于组件依赖的静态结构: 使用类图进行
- 自动生成
- 手动画
关于动态结构的自动生成, 目前有办法是通过执行单元测试进行.
使用类图可以正确描述依赖, 组合, 继承等关系.
C 代码中, 如果函数参数是某个类型的指针或引用, 可能会根据上下文确认该函数是否理解为该类型的成员方法.
AI 工具是否可以根据代码直接输出 Mermaid 对应的静态 UML?
antlr
使用 ANTLR 解析代码并生成静态结构
- 官网: https://www.antlr.org/
- Github: https://github.com/antlr/grammars-v4
- 语法文件: https://github.com/antlr/grammars-v4
- 书籍:
The Definitive ANTLR 4 Reference
Swift 建议使用官方工具进行: https://github.com/apple/swift-syntax
使用上应做到简单易用:
关于命令行的具体结构如下所示:
在上述结构中:
- 针对不同语言处理, 因此不同语言的支持放到解析器中进行.
- 前处理器会根据不同语言有不同.
- 后处理器统一接口, 即前处理器给出的数据在后处理器看到的都是同一种类型.
- 可视化器需要支持不同类型的模型工具输出, 因此需要不同种类的可视化器
- 前端展示时, 应能直接展示不同可视化器的输出结果(集成对应支持的模型工具展示库即可)
- 支持导入老数据, 对比数据差异, 这样在代码 Review 时的差异可以非常明显地进行可视化