程序流程图规范指南:从符号语义到PlantUML落地
2026/9/18 16:03:35 网站建设 项目流程

上个季度我接手一个遗留系统的文档重构,翻出十几张流程图,画图的人早就离职了。有意思的是,这十几张图里光"开始/结束"这一个符号就出现了四种画法:圆角矩形、椭圆、正圆,还有一张直接在矩形里写了个"开始"。更别提判断框了,有的用菱形,有的用矩形加一个问号,还有的用六边形。结果就是,我花了两天时间搞清楚这些图到底在说什么,比读代码还慢。

这件事之后我把"程序流程图规范"这件事重新捋了一遍。程序流程图看着是最没有门槛的文档形式,中小学信息技术课就教过,但它恰恰是最容易失控的——因为每个人心里都有一套"我觉得这样更清楚"的画法,谁也没有把它当回事。本文要讲的就是怎么把这套图从"各画各的"变成团队里能直接对齐的资产:符号语义怎么定,布局有没有硬约定,框里写什么字,一张图画到多细就该拆,以及怎么用工具把这些规则钉死,让它不靠人的自觉。

内容适合三类人:要交付流程图给评审或甲方的开发、写需求文档的产品、以及需要评审别人流程图的测试和技术负责人。哪怕你只画过学校作业那种练习图,看完也能直接照着改。

1. 流程图被打回的真正原因:语义不确定,而不是画得丑

1.1 判断框的"是/否"从来没人较真

我参加过不下二十次流程图评审,最容易吵起来的从来不是"这个框太大"或者"颜色不好看",而是同一个判断框出来的两条线,没人说得清哪条走的是正常路径。画图的人心里门儿清,看的人要顺着线一路追过去,追到某个处理框才发现"哦,原来这条是异常分支"。

这就是流程图最大的问题:它是给人读的,但它的作者往往只对自己可读。判断框有两个甚至三个出口,出口上的标注写了"是/否",可是"是"对应的是"校验通过"还是"校验失败"?这个语义在图的层面是不确定的,只能靠文字补。评审被打回,十次里有六次是因为这个。

真正规范的流程图,判断框的出口标注必须是自解释的。比如一个判断框写"token 是否过期",那么两个出口就不该标"是/否",而应该直接标"已过期"和"未过期"。看着啰嗦,但读图的人不用回头去看判断条件就能理解走向,一页图能省下三分钟。

1.2 三种最典型的"退回意见"

我把这两年收到的流程图评审意见归了归类,出现频率最高的就三条。

第一条是"缺少终止条件"。尤其是带循环的流程,图里画了一个判断框往上回指,但没有一个明确的出口说明循环什么时候结束。读图的人会怀疑这是不是一个死循环。

第二条是"分支不闭合"。一个判断框出去两条线,最后汇聚到两个不同的处理框,然后就断在那里了,没有汇回主干。图看起来"没画完",实际上画的人心里有数,只是懒得画那根汇合的线。

第三条是"符号混用"。同一个图里,输入和输出用了两种不同的框,处理框有时候是矩形有时候是圆角矩形。这种问题在评审时最容易被提,因为它是纯形式问题,谁都能指出,改起来又很麻烦。

1.3 规范到底要管哪四件事

很多人一听"流程图规范"就以为是背符号表,其实符号只是其中一层。一套能落地的规范至少要覆盖四层:

层次管什么出问题的典型表现
符号层每个形状代表什么语义判断框用矩形、起止用椭圆
布局层线条走向、分支方向、回环方式线条交叉成蜘蛛网、主干歪斜
文字层框内写什么、怎么写处理框里塞整段伪代码
粒度层画到多细、怎么拆页一张图画了八十个框

这四层里,符号层是标准能管的,有国家标准可依;布局层和文字层一半靠标准、一半靠团队约定;粒度层基本没有标准,全靠经验。后面的章节我就按这四层往下讲。

2. 符号层:那几个天天在用、却天天用错的形状

2.1 基础符号到底有几个

规范的依据是 GB/T 1526(对应国际标准 ISO 5807),里面定义的符号其实比大家日常用的多得多,包括处理、判断、起止、输入输出、文档、预定义处理、人工输入、人工操作、存储、连接符、页间连接符等十几种。日常程序流程图用得到的核心就六七个,我用一张表说清楚。

符号形状名称准确语义
圆角矩形(或圆)起止符流程的开始、结束,或引出一个外部流程
矩形处理一段计算、赋值、状态变更,只有一个入口一个出口
菱形判断根据条件在多条路径中择一,一个入口多个出口
平行四边形数据/输入输出读取或写出数据,不改变数据本身
双竖线矩形预定义处理调用一个已定义的子流程或函数,图内不再展开
底部带波浪的矩形文档输出或输入一份文档形式的载体
小圆圈连接符同一张图内连线的断开与续接
小圆圈加页标页间连接符跨页或跨图的连接

这里有两个特别容易被忽略的点:一是"预定义处理"和"处理"的区别,前者的存在是为了把复杂度藏起来,代表"这里有个已经定义好的东西,我不展开";二是"连接符"和"页间连接符"不是一回事,前者在同一页内跳,后者跨页跳,混用会让读者不知道该翻哪一页。

2.2 起止符不是必须的,但主流程必须有

新手最容易犯的一个错是,给每个子流程都画一对起止符。一个大的流程图里,如果每个分支都从头开始、到尾结束,读者会以为这是几条独立的流程。

正确的做法是:一张图(或者一套图的最外层)只有一个入口和一个出口,用起止符标。内部的子流程、被调用的函数,用预定义处理框表示,不单独配起止符。这背后的逻辑很简单:起止符代表的是"这个流程与外界的分界",子流程并没有与外界直接交互,它只是被父流程调起来的一段逻辑。

如果一张图里真的存在多个合法的入口(比如一个事件驱动的处理流程,可能被定时器触发,也可能被消息触发),那就用不同的起止符分别引出,但要在起止符里写清楚触发源。这一点在可靠性、IoT 这类多触发源的场景里特别常见,别偷懒只写一个"开始"。

2.3 判断框的出口数量是有讲究的

标准里判断框是"一个入口多个出口",没说上限。但工程实践里,一个判断框超过三个出口,图就开始难读了。我的经验是,超过三个出口就拆成两层判断,或者换成一个"分支表"表述。两个出口最舒服,三个出口勉强能看,五个出口基本等于灾难。

还有一个反过来的坑:把该用判断的地方用处理框。比如"累加计数并判断是否达到阈值",很多人会画成一个处理框,然后在旁边的注释里写"达到阈值则退出"。这是典型的偷懒,判断被藏进了处理框里。判断必须显式地用菱形表达,因为它是流程走向的分叉点,藏起来就等于把图的骨架藏起来了。

有一条经验我一直在用:只要这个框会导致后续流程走向不同,就必须是菱形,哪怕它同时也做了别的计算。宁可多画一个框,也别把分叉藏起来。

2.4 那些"看着对其实是野路子"的画法

最后列几个我见过但不符合规范的画法,供对照。

用矩形表示输入输出,靠文字区分——不行,输入输出有专用符号,就是为了让读者一眼看出数据边界在哪。

用实心圆点表示连接符——不规范,连接符就是小圆圈,实心点是有些绘图工具的默认连接点标记,不是符号。

用不同颜色区分主干和分支——颜色可以作为辅助,但不能作为唯一区分手段,因为黑白打印、色弱读者都会丢失信息。主干靠位置和线宽区分更可靠。

判断框用六边形或带斜角的矩形——这是有些 BPMN 工具的做法,但在程序流程图语境下不是标准符号,换成菱形。

3. 布局层:主干单线、分支右行、回环收口的约定

3.1 走向和主干线

布局这条线,标准给的建议很简短:自上而下、从左到右。就这么八个字,但落地的时候要拆成一堆细则。

核心约定是"主干单线"——整个流程的主路径应当是一条从上往下的竖直主线,尽量不左右横跳。这听起来像洁癖,但它直接决定了读图的效率。人眼读图是先扫竖线再扫横线,如果主干本身是弯的,读者就得一段段拼接,认知负担立刻上去。

主干线上的框要等宽对齐,也就是说处理框的左边界尽量对齐成一条竖线。判断框可以稍微宽一点,因为菱形里要写字。但不要让框忽宽忽窄,那会让读者以为框的大小有含义(实际上没有)。

3.2 线条交叉要尽量避免,不只是丑

很多人觉得线条交叉只是"不够美观",其实它直接影响正确性。两条线交叉的时候,交叉点如果没有明确的"跨线"标记,读者会怀疑这里是不是一个连接点。而流程图里的连接是靠线段端点,不是靠交叉,所以交叉本身没有任何语义——但读者不一定知道。

减少交叉的常用手段有两个:一是把分支画成向右展开的"梳子"形状,主干竖着,分支从右侧水平伸出,分支内部再纵向排列;二是对回环用连接符打断,不画实体长线。特别是跨越大半个画面的回环线,一律用连接符,这是最有性价比的一条布局规则。

3.3 分支展开与汇聚的对称性

一个判断框出去两条分支,规范的画法是:两条线对称展开,一条向左一条向右(或者干脆都先向下,再水平分开),处理完之后再对称汇回主干。这种对称的"叉子"形状读者一眼就懂。

反过来,如果一条分支直接往下走,另一条分支拐了好几道弯才回到主干,读者就会误以为那条弯的分支是"异常路径"或者"额外处理"。走向的不对称会被读成语义的不对称——这是流程图里一个很有意思的心理现象,也是很多人画图时不自觉传达出去的暗示信息。

如果你确实想传达"这条是常规路径,那条是例外路径"这个含义,那就应当刻意让常规路径走主干,例外路径走侧支并明确标注,而不是靠弯弯绕绕来暗示。

3.4 回环和跳转:能不画实体线就不画

循环是目前最考验布局的结构。一个循环在流程图上就是"向上回指的箭头",这条箭头骑着主干线往上走,会穿过中间好几层框,把图搅乱。

我的做法是:短距离回环(回跳到相邻的上一两个框)直接画实体线,从右侧绕上去;长距离回环一律拆成两个连接符,一个标在跳出的位置,一个标在跳回的位置,图面上就只剩两个小圆圈加一行标注。代价是读者要跳一下,但换来的是整页的清爽。

还有一个更彻底的方案:如果循环体内部逻辑复杂,直接把它抽成一个子流程,主图上只留一个预定义处理框加一条回指线。这也是后面讲粒度分层时会用到的技巧。

4. 文字层:框里写什么,才不叫"伪代码"

4.1 处理框必须是动词开头的可执行描述

处理框的文字,我给自己定的规矩是:主语默认省略,开头是动词,描述一个完整动作。比如"计算订单总价"、"写入用户记录"、"初始化连接池"。长度控制在十几个字以内,超出就说明这个框该拆了。

最常见的错误是把处理框写成一段代码或者一段伪代码。比如框里写for i in list: sum += i,这已经越过了流程图的表达边界。流程图是表达"做什么"的,不是表达"怎么写"的。真要表达实现细节,那应该直接看代码,而不是在图上画。

还有一种错误是写空话,比如"处理数据"、"业务逻辑"。这种框放在图里没有信息量,评审时一定会被问"具体是什么"。尽量写成"校验手机号格式"、"合并两条物流记录"这种一看就懂的动作。

4.2 判断框的条件要是能回答是非的短句

判断框的文字规范和处理框不同,它要写成一个可以被回答"是/否"或"哪一类"的问题。比如"库存是否充足"、"用户等级是哪一档"。这里有两种风格:一种是以"是否"结尾,一种是以"是哪一档"这种枚举式。

我个人的偏好是,判断框里写陈述式条件,出口上写结果。比如框里写"重试次数 < 3",出口分别标"是"(继续重试)和"否"(进入失败处理)。如果条件本身比较长,比如涉及两个变量的比较,就拆成两个连续的判断框,别在一个框里塞复合条件。

复合条件里最坑的是"与/或"混用。判断框里写"余额充足 或 已开通免密",出口的两条分支会让读者反复确认这到底是或还是且。解决办法就是拆框,一个框判断一个变量,复合逻辑用连续的菱形表达。

4.3 输入输出框要标明数据来源

输入输出框里写什么?写"数据的名字"加上"来源或去向",比如"读取用户信息(来自用户表)"、"输出对账文件(至对象存储)"。很多图里只写"获取数据"、"返回结果",读者根本不知道数据从哪来、到哪去。

这一点在跨系统流程里尤其重要。如果一个流程图横跨三个系统,那么每一个输入输出框都应该是系统边界的一部分,写清楚是哪个系统在读写。这些框连起来,其实就是一张数据流图,能帮读者快速看清系统的交互面。

4.4 术语一致性靠一张表来兜底

流程图被吐槽"看不懂",有相当一部分是术语不统一造成的。同一个东西,有的框里叫"订单",有的框里叫"交易单",有的框里叫"单子"。读者会以为是三个不同的实体。

解决办法很朴素但有效:画图之前先列一张术语表,规定每个核心概念在图里的固定叫法。这张表不用长,通常十个词以内就够。它带来的收益是复利式的——越大的系统、越多的图,收益越高。

一个小技巧:把术语表直接贴在流程图所在文档的开头,评审的人看到就能对上号,省去很多来回确认。

5. 粒度与分层:一张图装不下的时候怎么拆

5.1 先定一个单页容量的心理阈值

粒度这件事没有标准答案,但有一个可操作的经验值:一张 A4 横版、正常字号下,主流程的框控制在 15 到 20 个以内。超过这个数,读者就要开始"跳读",得在脑子里存状态才能跟上。

超过这个量的图,八成不是逻辑变复杂了,而是把不该在这一层展开的东西画进来了。比如一个订单流程,如果把所有异常分支、所有日志记录、所有参数校验都平铺在一张图上,很快就爆了。正确做法是分层。

5.2 概览图、子流程、叶级图的三层结构

我一般把流程图分成三层。

第一层是概览图,五到九个框,只画主路径和主要异常出口。它回答的问题是"这个流程大致做了什么"。给谁看?给不熟悉这个系统的人看,给评审会上第一眼的人看。

第二层是子流程图,每个概览图里的预定义处理框对应一张子图,展开详细步骤。它回答的是"这个环节具体怎么走"。

第三层是叶级图,只在真的需要精确对齐逻辑时才画,比如复杂的并发处理或者状态机。到了这一层,很多团队会干脆改用状态机图或者时序图,因为流程图表达并发是它的短板。

这三层之间的连接靠"页间连接符",每张子图顶部标清楚"这是哪张图的哪个框展开的",底部标清楚"退回哪一层"。这看起来是很繁琐的仪式感,但它是让一套图能被人接手的唯一办法。

5.3 流程图和代码的边界在哪里

还有一个常被问的问题:流程图画到什么程度就该停,直接去看代码?

我的答案取决于图的用途。如果是给非技术人员看,停在业务动作这一层,把技术细节交给文档或者注释;如果是给开发对齐接口和并发逻辑,那要画到函数调用级别,再细就没必要了,因为再细的图维护成本会超过它带来的价值。

这里有一条底线:流程图一旦画到和代码一一对应,它就开始过时。代码改一行,图就对不上了,而没有人会记得同步改图。所以流程图的粒度应当停在"变化频率低"的那一层,把易变的部分留给代码和注释。

6. 把规范钉进工具链:模板、文本化画图与评审清单

6.1 用模板固化符号和样式

规范写在文档里,永远有人不看。最有效的落地方式是把规范变成绘图工具里的模板。以 draw.io(现在叫 diagrams.net)为例,可以把符号表做成一个自定义图形库,团队每个人都导入同一个库,画出来的符号自然一致。

样式也要固化:统一的框体字号、统一的线宽、统一的箭头样式、统一的主干对齐网格。特别是"对齐到网格"这个设置,打开它以后主干线自然就是直的了,省掉大量手动对齐。Visio 里同样可以做模板(stencil),原理一样。

6.2 文本化流程图:PlantUML 和 Mermaid 的取舍

图形工具的优点是灵活,缺点是没法版本管理。两个版本的图存在 Git 里,diff 出来是二进制乱码,根本没法评审。这就是文本化流程图的价值所在:用代码描述图,图的变更就变成了文本 diff,可以走正常的代码评审流程。

常用的两种文本化方案,我列个对比。

维度PlantUML 活动图Mermaid 流程图
语义模型偏向活动图,分支合并语义清晰偏向通用流程图,灵活
符号规范性默认样式接近标准默认样式偏现代,需要配置
布局控制自动布局,人工干预有限自动布局,导向前端文档
适用场景后端流程、接口时序配合文档内嵌、README 展示

我个人的用法是:需要放在代码仓库里长期维护、需要走评审的图,用 PlantUML 活动图;需要嵌在说明文档里快速展示的,用 Mermaid。两者都能生成图片,但源文件是文本,这点最关键。

一个 PlantUML 活动图的基本骨架长这样:

@startuml start :接收请求; if (参数是否合法?) then (合法) :查询用户; if (用户是否存在?) then (存在) :生成订单; else (不存在) :返回未注册; stop endif else (不合法) :返回参数错误; stop endif :返回订单号; stop @enduml

注意这里判断框的出口标注写的是"合法/不合法"、"存在/不存在",而不是"是/否",这就是前面说的自解释原则,在文本化工具里同样适用。

6.3 用版本管理和评审流程管住图的变更

把流程图源文件(.puml 或 .drawio 的 XML)放进 Git,和代码放一个仓库或者一个文档仓库,然后在合并请求里一起评审。这样做的最大好处是:流程图不再是一个"画完就扔"的附件,而是有历史、有归属的资产。

我们的做法是,凡是与核心业务逻辑相关的流程图,源文件必须进仓;评审时和代码一起看。图改了但代码没改,或者代码改了但图没改,评审人一眼就能看出来。这条规则执行了半年,我们仓库里"过期的流程图"比例从一半以上降到了个位数。

6.4 我审图时用的那份清单

最后把我自己审流程图时对照的清单放出来,一共八条,按顺序看:

序号检查项判断标准
1入口出口是否唯一整图只有一个起止对(按触发源区分)
2判断框出口是否自解释出口标注写结果,不写"是/否"
3分支是否都汇回主干每条分叉最终有汇聚点或明确终点
4循环是否有出口每个回环都要有跳出条件
5符号是否统一同类语义用同一种框
6文字是否是动作描述处理框动词开头,无伪代码
7线条交叉是否可接受交叉处无歧义,长回环用连接符
8粒度是否单页可读主流程 15 到 20 框以内

清单不长,但每次评审按这个顺序过一遍,绝大多数形式问题在开口之前就被筛掉了。


我个人在实际操作中的体会是,流程图规范最难的从来不是记住那些符号,而是忍住"多画一点更保险"的冲动。图越满,重点越糊。真正被团队反复引用的流程图,往往就是那些框少、线直、判断框出口写得明明白白的图,看起来朴素,但谁都能在三分钟内读懂。规范不是为了让图更漂亮,而是为了让读图的人少花一点时间——这一点想通了,剩下的细节自然就愿意抠了。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询