经常写完文章, 收到的第一个问题是: 你的图是用啥画的; 其实自己也经常问别人. 最近强化了一下这方面的知识, 总结一下.
特指写文章或者做架构设计中用到的图.
画图的场景
个人将画图的场景分为两种: PPT/文章中使用和系统中使用
- PPT/文章中使用, 特指在 PPT 演示或者技术文章/文档中使用, 这种画图场景有几个特点
- 美观. 审美能力不行也不能作为马虎了事的借口,用心与不用心总是有差别的
- 一次性. 基本上一个场景仅需要画一次
- 手动. 可以使用任何工具, 手动各种摆放, 着色.
- 系统中使用, 特指在自己的系统中需要通过程序, 将一些流程通过可视化的方式展现. 这种场景有如下特点:
- 程序画图, 因此选择的是画图的 library 而不是 GUI 软件(感觉是废话)
- 调色/摆位等需求, 必须要 library 支持, 但对于我这种对前端 GUI 相关开发能力极度弱的人来说, library 不支持也只有换一个, 找不到替代也只有忍了; 而使用画图软件, 大不了自己手动摆放, 虽然耗时费力, 但至少是可以完成的.
可能有人觉得系统中画图
需求不多, 个人感觉还是有必要的. 经常遇到费劲开发了一个系统, 遇到各路用户问问题. 如果有办法在系统中将执行流程直接生成流程图, 你好我好大家好.
PPT/文章画图
GUI 画图工具有很多可选, 个人比较推荐的是 OmniGraffle, 在线工具推荐 lucidchart. 当然, 我也见过用 KeyNote 画出漂亮的系统图的, 工具不重要, 关键看人(说多了都是泪)
程序画图
重点说一下程序画图. 最近反省了一下, 画图最多的就是那几个:
-
块图. 经常用来表示系统间关系的.
-
序列图. 用来表示程序间调用关系
-
网络图. 用于网络相关的领域.
没了. 真的没了. 会这几个就可以行走江湖了.
然后, 推荐两个 library: blockdiag 和 graphviz.
blockdiag
blockdiag 是一个神奇的 python libary. 可以通过使用类似 graphviz 的语法, 画出 块图, 序列图, 网络图, 活动图. 还提供了一个交互式的 shell, 用于调试上述几种图. 例如, shell 中输入:
blockdiag {
A -> B -> C;
B -> D;
}
立即的到如下图:
点击右上角切换成序列图, 输入如下内容:
seqdiag {
// simple notation
browser -> webserver [label = "GET /index.html"];
browser <-- webserver;
browser -> webserver [label = "POST /blog/comment"];
webserver -> database [label = "INSERT comment"];
webserver <-- database;
browser <-- webserver;
}
有可以轻松得到如下序列图:
但是说好的 library 呢? 以 seqdiag 为例,
安装
$ pip install seqdiag
命令行使用
$ seqdiag -Tsvg simple.diag
程序使用
import tempfile
from seqdiag import parser, builder, drawer
import os
def generate_svg_sequence_diagram(text):
"""
:param text:
:return:
"""
tree = parser.parse_string(text)
_, filename = tempfile.mkstemp(suffix='.svg')
diagram = builder.ScreenNodeBuilder.build(tree)
draw = drawer.DiagramDraw("SVG", diagram, filename=filename)
draw.draw()
draw.save()
with open(filename) as f:
svg_content = f.read()
os.remove(filename)
return svg_content
Graphviz
Graphviz 可谓是一代画图神器, 通过官网的示例图就知道有多强大. blockdiag 也是参考 Graphviz 的实现. 通过类似的语法描述, 生成所需的图形. 对于颜色的选择, 可以参考文档中 Colors 一节, 非常全面.
程序方面, 同名的 graphviz
library 可以使用 pip install graphviz
安装, 非常方便. 示例python 程序如下:
from graphviz import Digraph
dot = Digraph(comment='demo dot graph', format='svg')
dot.node('A', 'King Arthur')
dot.node('B', 'Sir Bedevere the Wise')
dot.node('L', 'Sir Lancelot the Brave')
dot.edges(['AB', 'AL'])
dot.edge('B', 'L', constraint='false')
总结
既然有了 library 可以画图, 强烈建议在自己的系统中将一些复杂的流程化的事情通过根据当前系统状态画出图的方式展现给用户, 可以避免很多疑惑.