简介
Graphviz 是 AT&T 实验室开发的一个开源软件,它以一种文本语言去描述图(graph),然后自动排布节点和边去生成图片。它已有近 30 年历史。
UML(unified modeling language,统一建模语言)是一种常用的面向对象设计的方法。其中最常用的是类图(class diagram),用于表示类的构成以及类之间的关系。
利用 Graphviz 去生成 UML 类图有几个好处:
- 用文本表示图,容易更新,容易做版本管理。
- 能自动排布节点位置,在大型复杂的图特别方便。
- 统一文档风格。
实际上,文档生成工具Doxygen 也是采用 Graphviz 生成类图的。不过,我们在软件设计中,经常以类图表示系统中某个部分,并且按需展示某些重点,而不是简单地全部列出,所以还是需要手工去描述我们想要画什么,表示我们的软件设计。
使用 Graphviz dot
首先,下载 Graphviz 安装包。
- macOS 用户可以 brew install graphviz。
- linux可以yum install graphviz。
建立一个测试源文件 hello.dot(DOT语言为 Graphviz 的图形描述语言):
digraph {
Hello -> World
}
在命令行执行就可以生成文件:
dot -Tpng hello.dot -o hello.png
结果如下:
作为程序员,我们可以用常用的 GNU make 去做这个生成,以下的 makefile 也展示生成 PDF 矢量格式:
DOTFILES = $(basename $(wildcard *.dot))
all: \
$(addsuffix .png, $(DOTFILES)) \
$(addsuffix .pdf, $(DOTFILES))
%.png: %.dot
dot $< -Tpng -o $@
%.pdf: %.dot
dot $< -Tpdf -o $@
类图
UML 类图(class diagram)是最常见的图,用于表示系统的静态结构。UML 中类是以矩形表示。我们可以在 dot 文件中预设节点的形状,并且设置一些如字体等属性:
digraph {
node [shape=box, fontname="Inconsolata, Consolas", fontsize=10, penwidth=0.5]
Foo
Bar
}
稍后我们再谈如何加入类的成员。
继承
继承(inheritance)是类之间很重要的关系,在 UML 中又称其为泛化(generalization)关系,以空心箭头表示派生类指向基类。在 DOT 语言中,可以设置边的箭头形状,不过要注意,通常我们会把基类放在上面,因此我通常会这样设置:
digraph {
node [shape=box, fontname="Inconsolata, Consolas", fontsize=10, penwidth=0.5]
Animal, Mammal, Reptile, Dog, Cat, Snake
/* inheritance */
{
edge [arrowtail=onormal, dir=back]
Animal -> {
Mammal, Reptile }
Mammal -> {
Dog, Cat}
Reptile -> Snake
}
}
关联
UML 中的关联(association)描述两个类的关系,以类之间的实线表示。例如人和杂志的关系是订阅:
digraph {
node [shape=box, fontname="Inconsolata, Consolas", fontsize=10, penwidth=0.5]
Person, Magazine
/* Association */
{
edge [dir=none]
Person -> Magazine [label=" subscribe"]
}
}
我们经常会表示关联之间的多重性(multiplicity),例如 Person 类的实例最多可订阅 5 本杂志,而每本杂志可被任意