无垠之码

深度剖析代码之道


绘图工具

PlantUML和Mermaid类似都是基于文本的绘图工具,但基于Java运行环境的PlantUML更专注于软件工程图表且需要本地安装或服务器渲染,而基于Javascript运行环境的Mermaid支持更广泛的图表类型(包括甘特图、饼图等非UML图表),并且可以直接在现代浏览器中运行(需要引用mermaid-js渲染)。

其实图表的绘制语法,官方网站都有详尽介绍,本文对两者的使用方法及部分关键功能进行概述和实践示例,不做语法细节的全面展开。

1.PlantUML


标准库

在使用PlantUML绘制图标之前需要了解其提供的标准库,使用stdlib或者%get_all_stdlib命令可以展示当前版本PlantUML支持的标准库及其对应的源码项目。这里的标准库指PlantUML内置图元和功能模块的集合。具体标准使用请直接跳转至官方文档,https://plantuml.com/zh/stdlib。

  • Archimate

    Archimate是一种开放且独立的企业体系结构建模语言,它支持在业务领域内部和跨业务领域的架构描述,分析和可视化。结构化表示企业的各个组成部分,它们的相互关系及其与IT基础架构的集成关系。下图显示了ArchiMate Core框架的元素。

    image

  • Awslib|Aws

    AWS库提供了用于绘制Amazon Web Services服务和资源的图元(sprites)、宏(macros)以及其他包含文件(includes)。所有元素均基于官方的AWS架构图标生成,并结合PlantUML和C4模型,是以代码形式表达设计、部署和拓扑结构的极佳方式。Aws库功能一致,后续可能不再会支持(Warning: We are thinking about deprecating this library.)

  • Azure

    Azure库囊括一系列关于微软云相关的图标,在使用过程中可以首先包含!include <azure/AzureCommon>其提供helper宏方便使用。

  • C4

    C4模型是一个用于描述软件系统架构的可视化建模方法,由架构师Simon Brown提出在2018年发布。模型从以下四个维度,描述复杂系统全貌及系统组建之间的关系。

    1. Context系統上下文,说明系统和其使用者以及其他系統的关系
    2. Container容器,将系统分解为相关联的容器,描述一个软件系统内部的高层结构,容器是可部署/可运行的应用或服务单元
    3. Component组件,进一步细化容器内部结构,展示容器是由哪些组件组成,以及它们之间的关系。组件是构成容器的逻辑单元,通常表示容器内部的业务功能模块、服务类、控制器、DAO等
    4. Code代码,提供架构元素的涉及的细节,使用UML或者ER等既有的语法表达代码细节。
  • Classy|Classy-C4

    Classy是一个PlantUML扩展库,旨在提供更优雅、更现代化的类图绘制方式。核心目标是简化PlantUML的语法,同时增强类图的可读性和美观性。

  • Logos

    Logos是PlantUML中内置的技术品牌与开源项目Logo图标集合,格式为SVG。该图标库特别适用于开发者、DevOps 工程师等在架构图、技术栈展示中插入各类知名品牌标志(如GitHub、MySQL、Redis、Kubernetes等)。

  • Tupadr3

    Tupadr3图标库汇集了大量开发相关技术图标,包括Node.js、Docker、VS Code等。同时也集成了Devicons、Font Awesome等流行图标集中的品牌与UI元素,适用于README、技术简报与系统设计图中图标的插入。

  • Elastic|Material|Office|Kubernetes

    这些图标库包含了在开发、设计与文档中广泛使用、大家熟悉的图标与品牌标志。Elastic:Elastic Stack相关图标(如 Elasticsearch、Kibana);Material Icons:Google的Material Design图标,适用于UI设计;Office:Microsoft Office产品图标,适用于办公系统、文档管理相关系统;Kubernetes:容器编排相关图标,如Pod、Cluster、Deployment等,适用于云原生架构图;

  • Osa

    Open Security Architecture(OSA)是一个开源项目,旨在为企业架构师、系统设计师、安全专家等提供免费、可重复使用的安全架构模式Security Architecture Patterns和参考模型。 PlantUML官方标准库(stdlib)中为OSA图形符号提供的图元库,这意味着开发者可以使用OSA风格的图标(如防火墙、身份提供者、加密模块、终端等),快速构建符合OSA风格的安全架构图

  • Domainstory

    领域故事讲述(Domain Storytelling)是一种协作建模技术,它通过"讲故事"的方式来理解和记录业务领域的运作方式。这种方法特别适合在软件开发初期帮助开发人员理解业务需求。 PlantUML扩展工具包,包含用于可视化领域故事的宏(macros)、主题(themes)以及其他辅助工具,能够帮助你用PlantUML直观地记录和表达领域故事内容。

  • Cloudogu|Cloudinsight

    Cloudogu Ecosystem是一个开源、模块化、企业级DevOps平台,适合需要私有部署、工具整合和高安全性的开发团队。Cloudinsight是一个主要面向运维AIOps和IT监控分析的SaaS平台,专注于预测性运维和故障预防。PlantUML可以方便引用相关图标。

主题

PlantUML支持30多种主题,开发者可以简单使用!theme spacelab引用预置主题,使用函数%get_all_theme打印当前PlantUML版本支持的主题。

@startuml
!theme spacelab
start
:init;
-> test of color;
if (color?) is (<color:red>red) then
  :print red;
else 
  :print not red;
  note right: no color
endif
partition End {
  :end;
}
-> this is the end;
end
@enduml

预处理

一些预处理功能包含在PlantUML中,并可用于所有类型的绘图。这些功能与C语言的预处理器非常相似,只是特殊字符#改为感叹号!

  • 变量

    PlantUML支持三种类型的变量1.整数,2.字符串,3.json对象,在函数外创建的变量作用域是global,你可以在任何地方访问他们(包括函数)。当定义变量的时候你可以使用global强调这一点

    @startuml
    !$a  = 42
    !$ab = "foo1"
    !$cd = "foo2"
    !$ef = $ab + $cd
    !$foo = { "name": "John", "age" : 30 }
    
    Alice -> Bob : $a
    Alice -> Bob : $ab
    Alice -> Bob : $cd
    Alice -> Bob : $ef
    Alice -> Bob : Do you know **$foo.name** ?
    
    Alice -> Bob : 1. **$name** should be empty
    !$name ?= "Charlie"
    Alice -> Bob : 2. **$name** should be Charlie
    !$name = "David"
    Alice -> Bob : 3. **$name** should be David
    !$name ?= "Ethan"
    Alice -> Bob : 4. **$name** should be David
    @enduml
    
  • 布尔表达式

    PlantUML中约定,整数0表示false,任何非空数字如1或任何字符串如"1",甚至"0"表示true,支持布尔表达式常用的运算&&,||,以及布尔内置函数%false(),%true(),%not()

  • 条件

    PlantUML支持条件语句if以及else,帮助开发者绘制更复杂的流程图标,与shell语法相似,使用if + endif表示条件语句块。

    @startuml
    !$a = 10
    !$ijk = "foo"
    Alice -> Bob : A
    !if ($ijk == "foo") && ($a+10>=4)
    Alice -> Bob : yes
    !else
    Alice -> Bob : This should not appear
    !endif
    Alice -> Bob : B
    @enduml
    
  • 循环

    使用!while和!endwhile关键字实现重复循环

  • 函数

    PlantUML使用procedure或function定义函数,函数名以及参数名使用$开头,并且支持默认参数以及关键字参数,同时PlantUML中函数允许调用其他函数。使用invoke_procedure或call_user_func可以动态调用这些已定义的函数,完成更强大的功能。

    @startuml
    !procedure msg($source, $destination)
    $source --> $destination
    !endprocedure
    
    !procedure init_class($name)
    class $name {
    $addCommonMethod()
    }
    !endprocedure
    
    !procedure $addCommonMethod()
    toString()
    hashCode()
    !endprocedure
    
    init_class("foo1")
    init_class("foo2")
    msg("foo1", "foo2")
    @enduml
    
    @startuml
    !function $double($a)
    !return $a + $a
    !endfunction
    !function $double($a) return $a + $a
    
    !function $inc($value, $step=1)
    !return $value + $step
    !endfunction
    
    Alice -> Bob : The double of 3 is $double(3)
    @enduml
    
    @startuml
    !procedure $go()
    Bob -> Alice : hello
    !endprocedure
    
    !$wrapper = "$go"
    
    %invoke_procedure($wrapper)
    @enduml
    
  • 内置函数

    PlantUML支持一些常用的内置函数,函数以%开始,帮助开发者快速完成简单功能。详见https://plantuml.com/zh/preprocessing#393335a6fd28a804

  • 日志与诊断

    !log用于在不影响图表绘制流程的前提下,向命令行标准输出打印调试信息。这对于追踪变量值、函数调用流程或逻辑判断结果非常有帮助,有助于开发者更高效地定位问题。!assert可用于在代码中添加断言逻辑,用于验证某个条件是否成立。如果断言失败,PlantUML将在渲染阶段中止执行并输出相应的错误信息。这对于在复杂 PlantUML模板或宏函数中进行逻辑验证尤为重要,有助于提前发现配置或逻辑错误。!dump_memory指令可以在图表生成过程中输出当前内存中的全部变量和函数的内容。该指令也不会对图表的绘制结果产生任何影响,纯粹用于调试和分析目的。

2.Mermaid

Mermaid支持以下类型图标的绘制,Flowchart,Sequence diagram,甘特图,类图,Git graph,Entity Relationship实例关系图,User Journeys,Quadrant图,饼图,数据包图,Mindmap等 Mermaid嵌入html页面前首先需要导入mermaid.esm.mjs或者mermaid.esm.min.mjs调用mermaid.initialize()初始化运行环境,所有的图标,流程图都需要定义在pre标签中,Mermaid会处理页面中所有的<pre class="mermaid">标签元素,将其渲染成图片展示。

<body>
  <script type="module">
    import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs';
    mermaid.initialize({ startOnLoad: true });
  </script>  
  Here is a mermaid diagram:
  <pre class="mermaid">
        graph TD
        A[Client] --> B[Load Balancer]
        B --> C[Server01]
        B --> D[Server02]
  </pre>
</body>

与PlantUML一样,Mermaid提供命令行工具,可以方便的将Mermaid代码转换为可视化的图片

npm install -g @mermaid-js/mermaid-cli
mmdc -i input.mmd -o output.svg

语法

所有的Mermaid代码,使用类型申明开始,其后定义该类型图表的内容数据,下面的例子定义实体关系图。需要提醒的是在Mermaid中一些可以中断绘制流程的特殊符号需要谨慎使用,比如在flow类型图表中end单词,%%{``}%%等。

erDiagram
    CUSTOMER }|..|{ DELIVERY-ADDRESS : has
    CUSTOMER ||--o{ ORDER : places
    CUSTOMER ||--o{ INVOICE : "liable for"
    DELIVERY-ADDRESS ||--o{ ORDER : receives
    INVOICE ||--|{ ORDER : covers
    ORDER ||--|{ ORDER-ITEM : includes
    PRODUCT-CATEGORY ||--|{ PRODUCT : contains
    PRODUCT ||--o{ ORDER-ITEM : "ordered in"

Mermaid除了允许图表作者在Mermaid初始化时配置渲染模式,也允许在图表渲染之前通过指令或者frontmatter配置,来改变当前图表的外观,指令或配置的应用是在默认配置的基础上叠加生效的

import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs';
mermaid.initialize({ 
    startOnLoad: true,
    theme: "neutral",
    look: "handDrawn"
});

%%{init: { "theme": "forest" } }%%
graph TD
A(Forest) --> B[/Another/]
A --> C[End]
  subgraph section
  B
  C
  end
  
---
title: Hello Title
config:
  theme: base
  themeVariables:
    primaryColor: "#00ff00"
---
flowchart
	Hello --> World

扩展知识

图表类型 用途说明
Flowchart 展示业务流程、算法流程、决策路径等,用于分析逻辑流程与状态流转
Sequence Diagram 描述系统多个对象/角色之间的交互顺序,建模API通信、微服务交互等
Class Diagram 展示面向对象编程中的类、接口、继承关系,适用于软件设计说明文档
State Diagram 表示对象或系统的状态转换,适用于建模状态机、工作流系统等
Entity Relationship Diagram 表达数据库实体表及其关系,适合数据库设计和数据建模
Gantt Chart 项目管理工具,用于可视化任务时间安排、进度管理、里程碑设置等
Pie Chart 表示各组成部分在总体中的占比。适合用于展示统计比例、资源分布
Requirement Diagram 描述系统的需求元素及其依赖。适合大型项目中用作需求追踪模型
User Journey Diagram 展示用户完成特定任务的各个步骤与体验流程,适合UX分析与设计
Git Graph 可视化Git分支历史,适合讲解版本控制流程或代码分支策略
Mindmap 展示知识结构、头脑风暴结果、计划等层级关系内容
Timeline 用于表达事件的时间顺序,适合历史事件、产品迭代或计划进度展示
Quadrant Chart 显示项目、任务或观点在二维指标下的位置,适用战略分析、优先级评估
Zenuml 使用类似编程语言的语法编写时序图,支持更复杂的调用结构

3.参考文献

  1. http://t.zoukankan.com/dadadechengzi-p-architect.html
  2. https://github.com/Crashedmind/PlantUML-Elastic-icons
  3. https://mermaid.js.org/
comments powered by Disqus