程序员特有的画图方式——语绘工具小入门.
黑客与画家
虽然程序员多数时候都在与字符打交道,但偶尔也会像建筑或制造业的工程师一样,画一些图,比如:
- 为了表达多个系统如何协作以实现业务需求,会画时序图;
- 为了表达存储到数据库中的业务实体间的关系,会画ER图;
- 为了表达复杂的业务实体在整个生存期中状态的变化,会画状态图。
除此之外,还有流程图、甘特图、火焰图,等等。
尽管软件开发过程中产出的这些图不一定逼真、漂亮,或严谨,但凭着图上不同的形状、颜色,以及布局,也可以做到一图胜千言的效果。
图很有用,画图的工具也同样举足轻重。如果是本地的桌面应用,多数人可能会选择用Windows平台的Visio或macOS平台的OmniGraffle;若说到作图网站,则可能会选择ProcessOn或Draw.io。
但比起用鼠标拖拖拉拉,我更喜欢用代码来画图。
用代码画图?
用代码画图大致上可以分为两类:
- 用具体的编程语言控制某种绘图的API画出想要的图形,比如OpenGL、HTML5中的Canvas;
- 用DSL描述想要画的图,然后用程序根据DSL生成图片。
我所说的用代码画图指的是上述的第二类。
百闻不如一见,以最容易上手的DOT
语言为例,将下列内容保存在名为hello.dot
的文件中
digraph G { Hello -> World }
然后在shell中运行如下命令
dot -Tpng hello.dot -o hello.png
便得到了相应的PNG文件
更多的栗子
下面就带各位读者走马观花地看看不同的图可以用哪些工具来绘制。
流程图
说到程序员画的图,最出名的当属流程图了。依稀记得在高中的时候,某一册的数学课本中讲到了算法(也许是辗转相除法),并且给出了图示,那应当就是我第一次见到流程图。上大学后也有一段时间痴迷于寻找能够绘制流程图的DSL,不过一直未果。直到遇到Boostnote后,才知道的确有这样的DSL,那便是flowchart.js。
flowchart.js
是一个JS编写的、用来绘制流程图的库。比如下面这张图
便是依据下列的DSL生成的
st=>start: Start op=>operation: Your Operation cond=>condition: Yes or No? e=>end st->op->cond cond(yes)->e cond(no)->op
flowchart.js
生成的是SVG格式的图片文件,但SVG文件不方便嵌入到Markdown或Confluence的文档中,因此我会把它转换为PNG格式。折腾了一番后,发现在Mac上最靠谱的方法,是将SVG文件嵌入一个HTML文档,再用浏览器打开这个HTML,然后复制图片到预览程序上保存下来。
遗憾的是,不管是Emacs还是VSCode,似乎都没有辅助编辑flowchart.js
的DSL的插件。
有限状态机
有限状态机的示意图也是很常见的图形,尤其是在讲解编译器的书的语法分析章节中。在Graphviz项目官网的Gallery板块中,便有一个有限状态机的例子
它由如下的DOT
代码描述
digraph finite_state_machine { rankdir=LR; size="8,5" node [shape = doublecircle]; LR_0 LR_3 LR_4 LR_8; node [shape = circle]; LR_0 -> LR_2 [ label = "SS(B)" ]; LR_0 -> LR_1 [ label = "SS(S)" ]; LR_1 -> LR_3 [ label = "S($end)" ]; LR_2 -> LR_6 [ label = "SS(b)" ]; LR_2 -> LR_5 [ label = "SS(a)" ]; LR_2 -> LR_4 [ label = "S(A)" ]; LR_5 -> LR_7 [ label = "S(b)" ]; LR_5 -> LR_5 [ label = "S(a)" ]; LR_6 -> LR_6 [ label = "S(b)" ]; LR_6 -> LR_5 [ label = "S(a)" ]; LR_7 -> LR_8 [ label = "S(b)" ]; LR_7 -> LR_5 [ label = "S(a)" ]; LR_8 -> LR_6 [ label = "S(b)" ]; LR_8 -> LR_5 [ label = "S(a)" ]; }
不少工具将DOT
语言作为中间媒介来实现绘图的功能。
与flowchart.js
不同,Emacs和VSCode都可以很好地支持DOT
代码的编辑和预览。Emacs上有dot-mode
,VSCode则有Graphviz (dot) language support for Visual Studio Code这个插件。
时序图
我画得最多的当属时序图。在旧文《时序图绘制工具走马观花》中,提到了三个工具:
- WebSequenceDiagrams,一个在线绘制时序图的网站;
- sdedit,一个本地的命令行兼GUI绘图工具;
- SequenceDiagram,也是一个网站。
当时倾向于使用sdedit
。时过境迁,如今的WebSequenceDiagrams
变得更好看了,而我也选择了PlantUML作为绘制时序图的主力工具。下面这张图是PlantUML
官网给出的例子
它依据如下的代码生成
@startuml 用户 -> 认证中心: 登录操作 认证中心 -> 缓存: 存放(key=token+ip,value=token)token 用户 <- 认证中心 : 认证成功返回token 用户 -> 认证中心: 下次访问头部携带token认证 认证中心 <- 缓存: key=token+ip获取token 其他服务 <- 认证中心: 存在且校验成功则跳转到用户请求的其他服务 其他服务 -> 用户: 信息 @enduml
Emacs的plantuml-mode
,以及VSCode的PlantUML插件都可以为PlantUML
的DSL提供语法高亮。
下载了PlantUML
的jar
包后,在Emacs中添加如下的配置,就可以不依赖远程服务器来生成PNG格式的图片了
(setq plantuml-default-exec-mode 'jar) (setq plantuml-jar-path "/path/to/plantuml.jar")
UML用例图
在《架构整洁之道》一书中,作者提出了一个软件架构模式,其中有一层便是用例。看完这本书后,我越发地喜欢作者这一套架构模式,渐渐开始在设计文档中给出需求的典型用例——尽管是文字描述。再后来,才知道原来UML中已经有一类专门用于描述用例的图形方法——用例图。
用于画用例图的依然是PlantUML
。下列这张图
便是依据如下的源代码生成的
@startuml left to right direction actor 员工 as yg actor 顾客 as gk actor 餐厅员工 as ctyg actor A2 as a2 actor 送餐员 as scy rectangle cos { note "没注册工资\n支付的采用\n送餐时收费" as mzc usecase 查看菜单 as ckcd usecase 注册 as zc usecase 登录 as dl usecase 订餐 as dc usecase "预约/覆盖预约" as yy usecase 备餐 as bc usecase 请求送餐 as qqsc usecase 记录送餐 as jlsc usecase 打印送餐说明 as dyscsm usecase 记录收费 as jlsf zc .> dl : <<extends>> dl .> dc : <<extends>> } actor A1 as a1 note bottom of a1 : 已注册工资支付 yg <|-- gk gk <|-- ctyg ctyg <|-- a2 ctyg <|-- scy yg -- ckcd yg ---- zc yg --- dl gk -- dc gk ---- yy ctyg -- bc ctyg --- qqsc scy -- jlsc scy --- dyscsm scy -- mzc jlsf -- mzc @enduml
比较遗憾的是,PlantUML
自动排版的结果显得不那么整齐,左下角有一个明显的三角形空白区域——这也是DSL大法的一个缺点,即无法完美地控制最终的排列效果。
UML类图
最开始接触UML的时候,学习的便是类图——尽管接触得最早,画得却最少。比起类图,ER图反而画得更多一点。
如果要画类图,首选的工具是mermaid
。跟PlantUML
一样,mermaid
也是一个大而全的东西,除了画UML类图,也可以画流程图、时序图,以及UML状态图等。下面这张图
便是mermaid-cli
依据如下的源代码生成的
classDiagram Image <|-- BMP Image <|-- GIF Image <|-- JPEG Image: +setImpl() Image: +parseFile() ImageImpl <|-- WinImpl ImageImpl <|-- LinuxImpl ImageImpl: +doPaint() Image ..> ImageImpl
Emacs用户可以安装mermaid-mode
,VSCode用户则可以使用Mermaid Preview这个插件,来辅助编辑mermaid
的源文件。
方才提到的mermaid-cli
是一个命令行程序,用于在本地根据mermaid
的源文件产生PNG格式的图片,安装也很简单
npm install -g mermaid.cli
总结
还有许多的图可以用DSL来绘制,感兴趣的读者可以到mermaid
或PlantUML
的官网了解一番,这里不再一一举例。
用DSL来绘图有一些优点:
- 不需要借助鼠标工具,纯键盘党的福音;
- 源代码为纯文本,生成器跨多平台,可以在多个平台甚至网页上编辑和查看,不受单一软件厂商的约束;
- 方便修改,改完不需要来回调整各个图形的位置。
但也有一些缺点:
- 不直观,生成图片前不好猜测最终的效果;
- 无法准确地控制图中所有元素的排列和位置,有时候得不到想要的效果;
- 需要学习不同的DSL,学习成本比可视化工具要高。
就像软件开发中没有银弹一样,画图工具也没有万金油,关键还是要因地制宜地选择最合适的工具来解决眼前的问题。
原文地址:https://segmentfault.com/a/1190000022573007
相关推荐
-
OffscreenCanvas-离屏canvas使用说明 服务器
2020-7-1
-
超全的数据库分类介绍 服务器
2019-9-11
-
征服诱人的Vagrant! 服务器
2019-5-13
-
SVN – Linux下SVN详细配置文档 服务器
2019-10-16
-
Signal:安全、开源的聊天应用 服务器
2020-5-25
-
Linux (CentOS 7 )下搭建局域网SVN服务器+SVN权限配置 服务器
2019-3-11
-
RabbitMQ死信队列另类用法之复合死信 服务器
2019-3-10
-
SQLServer中间接实现函数索引或者Hash索引 服务器
2019-7-8
-
高并发架构系列:Redis缓存和MySQL数据一致性方案详解 服务器
2020-5-31
-
MySQL 事务机制 服务器
2019-5-20