考务处理系统顶层图解析:数据流图边界、外部实体与设计逻辑
1. 顶层图在数据流图体系中的位置为什么它被称作“最高抽象”考务处理系统这个词凡是学过软件工程、做过结构化分析的人应该都不陌生。教科书上关于它的例题十套卷子里至少要出现两三次而绝大多数教材给出的第一张图就是标题里说的这张顶层图一个加工、三个外部实体数据流只有那么五六条。很多初学者第一次看到这张图的时候心里都会犯嘀咕就这么点东西也叫系统报名、出题、阅卷、评分、登分、发通知这些流程全都看不见了画它到底有什么用这个问题问得非常好。顶层图在数据流图Data Flow DiagramDFD体系里的定位不是用来描述业务过程的而是用来界定问题边界的。它回答的是三个最原始、也最容易在项目启动阶段被忽略的问题系统在哪里谁在跟系统打交道系统从外界接收什么、向外界输出什么1.1 从一次需求评审会说起我参与过的项目中有好几次需求评审会开到一半就吵起来了。业务部门说“你们这个系统怎么把人工录成绩的流程给砍了”开发说“这个功能你们之前没提过”最后翻出会议纪要一看问题出在大家嘴里的“系统”根本不是同一个范围。业务方眼里的系统包括了Excel表格、微信群、电话通知这些手工操作而开发团队眼里的系统只包括代码运行的那部分。顶层图就是用来终结这种争吵的。它把整个待开发的信息系统画成一个圆也就是一个加工外面的考生、阅卷站、考试中心是三个外部实体数据流只有两类从外部实体流向系统的输入、从系统流向外部实体的输出。加工内部是什么样这张图完全不管那属于下一层——0层图要回答的问题。所以顶层图有个更通俗的名字叫上下文图Context Diagram或者叫环境图。它画的其实是系统与环境之间的关系而不是系统内部的结构。这个“上下文”的含义放在考务系统上尤其贴切考试中心在乎的是成绩数据和合格线判定规则阅卷站在乎的是答卷怎么进去、评分记录怎么出来考生在乎的是报名信息是否被正确接收、成绩单是否准确送达。至于内部是分五个模块还是八个模块、用没用数据库、有没有消息队列边界之外的这些实体完全不关心。1.2 顶层图的三个基本构成加工、外部实体、数据流理解了顶层图的定位再看它的三个要素就很顺了。加工Process在数据流图里用圆形或圆角矩形表示代表对数据的变换处理。顶层图里只有一个加工这个加工不需要编号有些教材里写“0”有些干脆不写这是约定俗成的习惯。它的名字就是整个系统的名字比如“考务处理系统”。一个加工意味着整个系统在边界外的人看来就是一个黑盒子数据进去、数据出来中间发生了什么外部不关心。外部实体External Entity用矩形表示是位于系统边界之外、与系统有数据交互的人或组织。考务系统案例里的三个实体选得非常典型考生是个人型外部实体阅卷站是组织型外部实体考试中心既是数据源的提供方又是数据的接收方。这三个实体几乎覆盖了外部实体的常见角色类型。数据流Data Flow用带箭头的线段表示描述数据的流向。顶层图里的每一条数据流都必须在下一层的加工分解中找到对应的去向或来源。我见过很多初学的人画完顶层图就扔到一边直接动手画0层图回头对不上账数据流不是丢了就是多了最后被老师或评审追问得哑口无言。提示顶层图的数据流命名一定要用名词短语比如“考生答卷”“考试成绩通知单”不要用“读取成绩”“发送通知”这类动词短语。数据流图里的动词属于加工不属于数据流这个习惯从第一张图就要养好。2. “考务处理系统”顶层图的逐个元素解构边界、实体与数据流的设计逻辑标题里的这张图看起来简单实际上每一个元素的摆布都有讲究。我不建议直接背图而是建议把这张图当成一道论证题来拆为什么是这三个实体为什么数据流只有这些有没有可能再多一个实体有没有可能少一条数据流2.1 加工为什么叫“考务处理系统”而不是“考试系统”先看加工名字。顶层图的加工名是“考务处理系统”注意这里的措辞——“考务处理”而不是“考试管理”“考试系统”这四个字圈定的业务范围其实很精准。“考务处理”在行业内一般对应的是报名组织、考场编排、试卷管理、阅卷组织、成绩统计与发布这一套流程性事务它不包含命题内容本身也不包含教学层面的决策。所谓“处理”二字强调的是对数据和流程的操作而不是对考试业务的决策。考试中心如果要在系统里做“合格线划定”那是加工内部的事情在顶层图上就体现为考试中心传来的“考试合格标准”数据流系统处理之后再回报“成绩分析报告”。加工的名字就是系统对外的名片。如果名字起得太宽比如“教育管理系统”评审的人会天然地质疑为什么不包含招生为什么不包含学籍边界就被架空了。如果起得太窄比如“成绩录入系统”那阅卷站送答卷这件事就不该出现在数据流里。名字与数据流不匹配看图的人第一反应就是系统范围描述有缺陷。2.2 外部实体一考生——既是数据起点又是数据终点考生这个实体位置在图的最左侧数据流有两条一条是考生到系统的“考生报名信息”一条是系统到考生的“考试成绩通知单”。有心的读者会发现考生在考务系统里是典型的“源与宿合一”的实体——他既提供数据也接收数据。这种合一双向的实体在设计顶层图时最容易漏掉一个方向。常见错误是只画了“考生报名信息”进来忘记画“考试成绩通知单”出去。为什么会漏因为在很多人的第一反应里成绩通知单好像是“考试中心”发给考生的系统只是中间传话的。这个认知错在把外部实体之间的直接交互理解成了系统的功能。考试中心确实会拿到成绩数据但面向考生发成绩单这件事在考务处理系统里是系统的工作不是考试中心的工作。顶层图的加工是“考务处理系统”那么所有在系统范围内完成的对外交互都要画成外部实体与加工之间的数据流外部实体之间不允许有数据流。这条规则我在后面还会强调它是我评审别人数据流图时最先检查的一点。还有一类设计是把“考生”拆成“考生库”这在顶层图里是错的。外部实体必须是有明确行为能力的组织或个人数据库是数据的存储属于加工内部的内容。如果把“考生库”画在外部相当于把系统的内部存储暴露到了边界之外后面0层图的存储就不知道该放在哪一层了整个层级体系都会乱。2.3 外部实体二阅卷站——组织型外部实体的典型形态阅卷站这个实体是很多人画图时最容易犹豫的一个。有人问阅卷站不是应该由考试中心管理的吗把它画成并列的外部实体是不是重复了不是的。外部实体的判定标准不是“隶属关系”而是“与系统是否有直接的数据交互、交互是否发生在系统边界上”。系统与阅卷站之间有“考生答卷”流入和“成绩花名册”流出这两条数据流说明阅卷站是一个与系统直接打交道的独立协作方。至于它内部受谁管理那是它自己组织架构的事与数据流图无关。阅卷站在顶层图里扮演的是典型的生产者-消费者角色它是原始数据答卷的提供者也是处理结果评分数据的接收者。这种角色的数据流命名要特别注意方向与内容的语义一致性从阅卷站流到系统的叫“考生答卷”从系统流回阅卷站的叫“成绩花名册”——很多人习惯写成“阅卷成绩”方向没问题但语义太模糊因为“阅卷成绩”既能理解成系统收到的评分也能理解成系统返回的统计结果评审时必定被追问。2.4 外部实体三考试中心——管理型实体的数据特征考试中心在三个实体里面最特殊因为它是“管理型实体”与系统的交互不是单条流而是两组双向流一组是“考生报名信息”从系统流向考试中心部分教材里也可能从考试中心流入“考生名单”这取决于具体业务流程的约定另一组是“考试合格标准”流入系统、“成绩分析报告”流出系统。这里反映了一个关键设计思想外部实体与加工之间的多条数据流代表多种业务交互类型不要在画图时为了画面整洁把它们合并。有些教材喜欢把“成绩分析报告”和“考试成绩通知单”合并成一条流写上“成绩信息”看起来简洁但到了0层图展开的时候这条流要么被拆成两条去对应不同的加工要么就得在整个分层体系里强行保持合并状态导致每一层都跟着别扭。数据流的粒度要以业务语义完整为界不以线的多少为界。考试中心的另一个特点是“规则提供者”属性。顶层图中的“考试合格标准”这条数据流是容易被初学者忽略的因为很多人默认合格线是系统自己定的。但在考务处理系统的业务模型里合格标准由考试中心制定并下达系统接收标准后执行判定。这个细节决定了0层图里必须有一个“成绩判定”或“合格判断”类的加工来接收这条流否则顶层图就与0层图对不上。2.5 边界之外为什么系统没有第四个外部实体评审数据流图时经常有人反问“试卷印刷厂呢考场监控呢报名缴费的银行呢”这些都是业务中真实存在的角色但它们在顶层图里不该出现。判断标准是实体是否与系统有直接的数据交换。试卷印刷厂若与考务处理系统交换的是“印刷任务单”和“试卷成品”那说明印刷业务被纳入了系统边界如果试卷印刷由考试中心线下组织印刷厂只跟考试中心打交道系统不接触印刷厂的数据那印刷厂就不该出现在顶层图中。考场监控如果由独立的监控系统负责与考务系统没有数据接口同样不应出现在这张图里。这个“不画无关实体”的原则是顶层图控制复杂度最重要的手段系统的边界一旦圈得过大后面每一层分解都会失控。项目里曾经有位同事把“考生家长”也画进了顶层图理由是“家长会查询成绩”但在当时的系统设计里家长是登录考生账号查成绩没有独立的身份和数据接口家长这个实体与系统之间没有直接交互画上去之后0层图无从分解最后还得删掉白白增加评审压力。3. 顶层图到0层图的展开平衡校验、命名一致与加工粒度的实战验证顶层图画完工作只完成了一半甚至是三分之一。因为它真正实用的价值在于作为0层图展开的唯一基准。很多学生在考试里栽的跟头不是栽在顶层图本身而是栽在顶层图和0层图之间的对应关系上。这是结构化分析方法里最核心的“分层平衡”概念我展开讲。3.1 考务处理系统0层图的一种典型展开方式把考务处理系统的顶层图向下展开一层一般可以得到三个主要加工1报名处理2成绩管理3成绩统计分析这三个加工分别对应顶层图中三条主要的业务链路报名链路考生-系统-考试中心、阅卷评分链路阅卷站-系统、成绩发布链路考试中心-考生。部分教材里还会拆出“考务安排”这个加工来承担考场编排这时候0层图会变成四个加工但无论怎么拆都必须保证输入输出数据流的总量守恒。0层图里有两条数据流值得特别注意一条是“考生答卷”从外部实体阅卷站直接流入加工2“成绩管理”这说明阅卷的组织与原始答卷采集工作归属于成绩管理模块另一条是“考试成绩通知单”从加工2流向外部实体考生说明成绩单的生成与发放是由成绩管理模块完成的而不是由统计分析模块输出。这两条流的归属判断就是面试官在数据流图面试中最爱追问的点。3.2 平衡校验怎么实操一条流对一条流所谓平衡是指父图上一层中某条数据流一旦涉及被分解的加工那么子图下一层的输入输出必须与父图完全一致。对于考务系统的顶层图来说平衡校验就是把0层图的整体输入输出集与顶层图做并集对比顶层图的输入数据流考生报名信息、考生答卷、考试合格标准顶层图的输出数据流考生报名信息向考试中心、成绩花名册向阅卷站、考试成绩通知单向考生、成绩分析报告向考试中心0层图上所有外部实体与所有加工之间的数据流并集必须与此完全一致。我见过不少人的0层图把“考生报名信息报考试中心”这条流丢了理由是报名信息本来就是从考生那来的考试中心拿到的应该是一份汇总表而不是原始报名信息。这个念头很危险——如果考试中心收到的确实是汇总表那顶层图上这条流的名字就该改成“考生报名汇总”而不是“考生报名信息”。名字没有改、图却改了这就是不平衡。实操时我建议做一张数据流清单每画完一层就拿着清单逐条核对一次。表格长这样数据流顶层图来源顶层图去向0层图来源0层图去向是否平衡考生报名信息考生系统考生加工1 报名处理平衡考生答卷阅卷站系统阅卷站加工2 成绩管理平衡成绩花名册系统阅卷站加工2 成绩管理阅卷站平衡考试成绩通知单系统考生加工2 成绩管理考生平衡考试合格标准考试中心系统考试中心加工2 成绩管理平衡成绩分析报告系统考试中心加工3 成绩统计分析考试中心平衡这张表做出来图有没有问题一眼就能看出来。不要嫌麻烦在项目评审里抓分层平衡问题是最快的挑刺方式你自己先查一遍就相当于提前自查了。3.3 加工粒度的把握展开到什么程度算合适0层图分解成几个加工比较合适没有绝对答案但有经验法则3到7个为宜。太少则说明分解不够太多则说明0层图直接承担了过多细节。以考务系统为例如果把“成绩管理”直接拆成“成绩录入”“成绩校验”“成绩判定”“成绩发布”四个加工0层图就有六个加工了这时要问一句这些加工内部还有没有独立的数据存储和复杂的处理逻辑如果只是同一个模块里的子步骤把它们平铺在0层图会把该由1层图承担的复杂度提前暴露出来读图的人会非常累。反过来如果0层图只画一个“报名处理”和一个“成绩处理”把统计分析合并进成绩处理那0层图就退化成了一张没有多少信息的草稿。好的分解粒度是每个加工都对应一项独立、内聚的业务任务并且每个加工都需要进一步分解才能说清楚——但进一步分解的工作留给下一层而不是在这一层一次画完。我常用的判断标准是0层图中的每个加工展开后若只需要3到5个子加工就能说清楚那粒度就是合适的如果需要8个以上子加工说明这个加工在0层图里拆得不够应该提前分离。4. 从考务系统案例到通用方法一份可以直接上手的顶层图绘制清单前面拆了考务系统的具体案例这些原理能不能迁移到别的项目完全可以。顶层图的画法非常固定适应于任何系统的需求分析阶段。我按自己这些年画图的习惯整理了一套可以“抄作业”的流程每一步都对应着考务系统案例里的具体操作作为示范。4.1 第一步圈定系统边界写下加工名先不要急着画实体和箭头先在白板中间画一个大圆写上系统名。名字本身就是在定义边界它包含哪些业务、不包含哪些业务这四个字要反复斟酌。考务处理系统之所以取这个名是因为它明确覆盖“报名到成绩发布”这一段考务全流程但不包含“命题内容审核”“考场物理监控”这些相邻业务。写加工名的时候顺便列一份“明确不包含的业务清单”比如不含教材征订、不含证书打印、不含考生转考申请。这份负清单不画进图里但它能帮你在评审时挡住很多“为什么不画XX”之类的问题。4.2 第二步列出所有与系统有直接数据交互的候选实体这一步的产出不是最终的外部实体而是候选名单。把业务流程从头到尾走一遍谁给系统提供原始数据谁接收系统的输出结果谁为系统提供规则和参数谁从系统获取报表和统计信息考务系统里的三个实体就是这么来的考生提供报名信息、接收成绩单阅卷站提供答卷、接收评分花名册考试中心提供合格标准、接收分析报告。筛选候选用三问法它是人、组织还是另一个系统三类都可以是外部实体它与系统的数据交换是否发生在系统边界上发生在边界以内的是加工内部逻辑不是外部实体如果剔掉它系统的输入输出描述是否完整不完整就保留完整就划掉4.3 第三步逐个实体画数据流先画输入再画输出这一步最容易乱最容易错也最能体现画图者的业务理解深度。我按实体逐个过不跨实体顺序是先画该实体发给系统的数据流再画系统发给该实体的数据流每画完一个实体就在候选名单上打个勾。拿考生举例先画“考生报名信息”考生到系统再画“考试成绩通知单”系统到考生。很多人到这里就停了漏掉了“报名信息回执”或“报名审核结果”之类的反馈流。这时候需要用穷举法追问一次该实体与系统之间的每一次业务往来是否都有一条数据流对应上了考生报名时系统要不要回报成绩公布后考生是否能查询如果查询动作是考生主动发起、由系统响应那么在顶层图里就应有“成绩查询请求-成绩查询结果”这组流。如果查询被设计成系统主动推送成绩单那只有一条输出流就够了。考务系统经典教材案例选择的是“系统主动推送成绩通知单”模式这也是大多数省份实际考务系统的做法因此顶层图只有一条输出流没有查询请求流。提示每画完一条数据流顺手在流线上标注名字。不要等全部画完再统一标注数据流一多就分不清谁是谁了。命名用名词、不出现动词、不带“和”“及”这类并列连词保证每条流只表达一类数据。4.4 第四步检查外部实体之间是否有直接连线这条规则值得单独列一步因为它是新手最容易踩的坑数据流图中外部实体之间不允许存在直接的数据流。所有数据交换都必须经过加工系统。如果出现外部实体之间的连接只有一种解释这个交互发生在系统边界之外不属于系统的功能范畴因此不该出现在图里。但业务上明明存在的交互怎么办两种选择要么把交互纳入系统范围改为两个实体分别与系统交换数据要么明确标注该交互线下完成与系统无关在顶层图中省略。考务系统的经典设计里阅卷站与考试中心之间的“交接成绩汇总表”在业务上是存在的但系统边界外的线下流程因此顶层图不体现。如果非要在图里画就等于把加工给绕开了0层图根本无法分解这条流整个分层体系瞬间崩塌。4.5 第五步用数据流清单做一次完整自查最后一步把成品图变成数据流清单逐条核验。强烈建议把这个习惯保留到所有分层图里。清单格式我在上文已经给过表格模板把“来源”“去向”两列单独拎出来检查就能发现绝大多数错误。完整自查清单如下任何一条不满足都要回头改图加工只有一个名字与系统名一致顶层图每条数据流都有方向、有名称方向与名称语义相符没有外部实体到外部实体的数据流没有控制流如“启动系统指令”混入数据流图每个外部实体至少有一条数据流与加工相连数据流命名不出现动词短句外部实体与加工之间的数据流在0层图中有对应去向。5. 画过几十张顶层图后我最想提醒的四个高频错误这张标题里的考务系统顶层图其实恰恰浓缩了数据流图绘制中最容易出问题、也是课程设计和项目评审里反复被揪出来的几类错误。我挑四个自己反复踩过的坑展开说。5.1 把数据存储画在顶层图里顶层图唯一的圆是加工存储数据存储是加工内部的实现细节在顶层图里完全不可以出现。有人把“考生数据库”“成绩库”画在加工旁边理由是系统要存取数据所以要有存储。这个说法混淆了系统的外部特性和内部结构外部实体与系统的交互体现在数据流上而数据存储是内部设计的内容应该在0层或1层图里根据加工间数据的流转需求引入。说白了顶层图是给业务方看系统边界的存储放在那里业务方会误以为系统自带数据库是某种对外承诺容易引发需求蔓延。5.2 把输入输出合并成一条粗箭头这个错误比存储错误隐蔽得多。有人觉得“报名信息”和“成绩单”都是考生和系统之间的交流画成一根双向箭头就行了标注名字为“考生信息”。问题在于合并之后这条流的语义变得含混0层图里对应哪个加工根本无法判断。如果这条流被分解进了“报名处理”加工那“成绩单”的归宿就丢了如果分解进了“成绩管理”加工报名信息又成了无源之水。数据流图的基本约定是每条数据流代表一类特定数据的定向传递。双向交互射成两条独立的有向流永远不要让一条流既表示输入又表示输出。你们可以记一个口诀数据流图里的箭头永远只有一个头。5.3 加工名写成动宾短语或系统名重复顶层图只有一个加工名字就是系统名这个大家不太会错。到了0层图加工命名的规范就要立起来加工用动词宾语或动宾结构的短语表达动作比如“审核报名信息”“统计成绩”“生成通知单”。有人习惯用“报名信息审核模块”“成绩统计子系统”这种名词性地方名图倒是能看懂可规范说来不是数据流图的风格。加工在图上表达的是“行为”不是“组织架构”或“程序组件”。这里有个训练方法拿到一张数据流图不用看来龙去脉把每个加工的名字列出来读一遍如果读起来像一份系统菜单那说明命名偏向了模块如果读起来全是名词堆叠比如“报名信息”“成绩单”“合格标准”那就该改成动词短语。5.4 把错误处理流程画进数据流图最后一个坑更偏向逻辑层面。考务处理系统的顶层图几乎每个项目组在需求阶段都要讨论一件事考生填写了错误的报名信息系统应该怎么处理比如身份证号填成了18位但校验不通过要不要画一条“报名错误信息”从系统返回给考生从业务上说这条数据流真实存在。但如果把它画在顶层图里就会带来一个麻烦到底哪些输入需要回执是不是每条数据流都要配套一条校验失败的回执这会导致数据流数量翻倍而且每条回执流在0层图里都要有对应加工去承接图的复杂度瞬间失控。我的处理惯例是顶层图只表达正常业务路径上的数据交互异常流程放到加工内部的数据流图1层及以下里单独画或者用状态转换图、决策表来补充说明。项目的核心边界上顶层图承担的是“范围”职责不是“逻辑”职责不要在范围图上堆细节。6. 画图工具与交付形态从白板草图到可评审的数据流图文档说到这里很多读者可能已经想动手自己画一张。关于画图工具和最终交付形态我也有几点经验性的建议特别是考虑到数据流图是要给不同角色看的业务专家看逻辑、开发看边界、测试看数据流转路径。6.1 工具选型Visio、draw.io、PlantUML 怎么选如果你只求快速产出、方便分享和协同编辑draw.io也就是 diagrams.net是我的首选免费、免安装能导SVG和PNG多人协作也流畅。若是在企业内部做正式交付文档Microsoft Visio 依然是通用性最高的选择模板里的Gane-Sarson符号或Yourdon符号直接拿过来用即可只是Visio对中文用户的默认模板支持不太好第一次使用需要手动建一个符号库后面就顺手了。偏好命令行和版本管理的团队可以试试 PlantUML文本即图表能直接放进Git仓库参与Code Review。但PlantUML画数据流图的语法支持不如画UML类图成熟复杂图要花不少时间去调整布局。我个人的习惯是初步沟通用白板或draw.io正式评审前把图重新整理进Visio或draw.io模板里保持符号、线型、字体的统一。6.2 符号规范一套固定符号用到底数据流图有两大主流符号体系Yourdon/DeMarco加工画圆、数据流画直线箭头和Gane-Sarson加工画圆角矩形、数据流画曲线箭头。国内教材多用Yourdon/DeMarco体系企业里Gane-Sarson也很常见。最怕的是同一个团队里有人用圆有人用圆角矩形评审的时候光是对符号就要花十分钟。选定一套后整个分层图从头到尾都使用同一套符号这个没得商量。元素Yourdon/DeMarcoGane-Sarson加工圆形圆角矩形外部实体矩形矩形右上角开口或封闭数据存储双横线平行线段封口或开口数据流直线箭头曲线箭头我画的图偏爱Gane-Sarson圆角矩形在实际排版时比圆形更好自动布局加工名太长不会被截得难看而且在0层图里加工多了之后圆角矩形的视觉重量更均匀。如果你画顶层图选哪套都无所谓但请记住顶层图的加工一般用大一点的圆或圆角矩形强调它是系统的最高抽象。6.3 交付评审一张图配一张表最后给那些准备拿数据流图去参加评审的读者一个建议不要只交付一张孤零零的图。配上一张“数据流说明表”每条数据流一行写清楚来源、去向、数据内容、触发时机、频率。表格不需要很复杂但能把图的抽象性落到业务的具体性上。考务系统顶层图配的说明表第一行大致长这样数据流来源去向数据内容触发时机频率考生报名信息考生考务处理系统姓名、证件号、报考科目、考点意向等报名窗口期内每人一次考生答卷阅卷站考务处理系统客观题答案、主观题作答内容考试结束阅卷前每科一份考试成绩通知单考务处理系统考生各科成绩、总分、合格结论成绩审核发布后每人一次成绩分析报告考务处理系统考试中心合格率、分数段分布、科目均分等成绩发布后周期性每个考次一次这么一张表放出来评审的人根本不用靠猜来理解图。我自己的经验是凡是评审中数据流图被挑出问题的项目十有八九没有配这张表——流程没理清楚图表出了问题文字又没能兜住。这里还有个小技巧说明表里的“数据内容”一栏其实可以被你用来做数据字典的第一版草稿。到了详细设计阶段把这些字段逐个确认类型、长度、校验规则数据字典就顺理成章地建立起来了。顶层图、数据流说明表、数据字典三者是一脉相承的三件套在线下项目中这三件套都用起来需求分析的质量会明显不一样。按这个思路把考务系统顶层图从头到尾推演完你会发现自己对数据流图的理解已经不只是在背一张图了。把这套边界的思维、实体筛选的方法、平衡校验的表格带到下一个真正的业务系统里去画图的乐趣和实效都会超出预期。