简介:这是一份面向软件工程课程设计与系统分析学习者的航空机票预订系统结构化设计文档,适合高校学生在课设答辩、系统建模或数据库设计时参考。内容以实体—关系图清晰梳理旅行者、机票信息、航空公司、旅行社、取票通知等核心实体及其属性联系,用数据流图完整展现旅客提交预订、系统检索机票、信息传递至旅行社、最终生成取票通知的数据流动过程,并通过状态转换图刻画系统从接收预订到通知送达各阶段的状态变迁;配套的数据字典还逐项定义了旅客信息、机票信息、航空公司信息等数据项的字段与关系。文档逻辑严密、图示完整,可直接作为课程设计报告中的逻辑模型章节,或用于辅助完成数据库表设计、流程状态梳理等任务。资源包共含一个PDF文件,大小仅57KB,下载便捷。目前已有2971人学习下载,适合正在完成软件工程课设、需要绘制系统分析图或理解机票预订业务逻辑的高校学生与开发者。
1. 拿到航空机票预订系统四张图之后:先分清实体、流动、状态、定义各自管什么
带过几届软件工程课程设计,见得最多的不是不会画图,而是拿着一套现成的航空机票预订系统ER图、数据流图、状态转换图和数据字典,不知道怎么改成自己的题目。这套PDF本质上是一份标准的结构化分析产物:ER图回答“业务里有哪些对象、谁和谁发生关系”,数据流图回答“数据从哪进来、经过什么加工、写到哪些存储”,状态转换图盯着一笔订单从下单到取票的状态变化,数据字典把每个数据项、每条数据流、每张表定义到字段级。这篇拆解不是复述PDF,而是带你把四张图按“实体—流动—状态—字典”的顺序读透,再把它改造成自己课程设计里能交差、能抗住追问的结构化分析文档。适合正在做课程设计或期末大作业、答辩前想补图的人。
2. ER图怎么读透:五个实体、四类联系,以及怎么加出自己的订单
2.1 五个实体是“谁和谁交易”的底牌
ER图第一眼看的是实体。实体不是数据库表,而是业务里真实存在的对象。这套图里一共出现五个核心实体:旅客、机票信息、航空公司、旅行社和取票通知。它们的角色非常清晰:旅客是需求方,航空公司是资源提供方,旅行社是代理中转方,机票信息是买卖的标的,取票通知是最终交付给旅客的凭证。把这五个角色先安到业务场景里,再看属性和联系就不会乱。
| 实体 | 业务角色 | 关键属性 | 在系统里承担的事 |
|---|---|---|---|
| 旅客 | 需求方 | 姓名、性别、身份证号、工作单位、旅行地点、旅行时间 | 提交预订请求、接收取票通知 |
| 机票信息 | 交易标的 | 价格、帐单、等级、可售机票时间、航班机票信息 | 被查询、被预订、被出票 |
| 航空公司 | 供给方 | 名称、合适航班 | 提供航班和可售票资源 |
| 旅行社 | 代理方 | 名称、合适航班 | 代售机票、传递售出信息 |
| 取票通知 | 交付凭证 | 旅客清单、售出机票信息 | 告诉旅客去哪取票、取哪几张票 |
这里有两个容易理解偏差的地方。一是“机票信息”不等于“航班”。航班是一架飞机从A城飞到B城的排班记录,机票是某个航班上按日期、舱位拆出来的一批可售单元,价格、等级、可售时间都挂在机票信息而不是航班上,所以实体是“机票信息”而非“航班”。二是“取票通知”虽然名字里有“通知”,但它带旅客清单和售出机票信息,是业务里要被记录的交付结果,所以作为实体存在,而不是只当作一张纸。
画ER图之前还要先把属性和实体分开。属性是描述实体的特征,例如“工作单位”是旅客的特征,不需要拆成单独实体。初学者经常把“旅行时间”单独拉一个实体,觉得它重要就应该有身份,这是把字段物化的典型错误。判断一个词到底是实体还是属性,可以看它是否拥有自己的属性:实体还能挂别的属性,属性不能再挂属性。旅行时间没有下级特征,留在旅客实体里当属性就够了。
2.2 联系怎么定:从“旅客订机票”推出基数关系
实体之间要有联系,画联系最核心的工作是定基数。基数只有三种:一对一、一对多和多对多,但课程设计里大多数业务联系都是1:N。先把这套图里的联系和理由看一遍:
| 关系 | 基数 | 判断依据 |
|---|---|---|
| 旅客—机票信息 | 1:N | 一位旅客可以一次订多张机票;一张机票只属于一位乘机人 |
| 航空公司—机票信息 | 1:N | 一家公司拥有多个航班和对应的一批票;一张票只归属一家公司 |
| 旅行社—机票信息 | M:N | 一个旅行社代售多家公司的票;同一张票也能同时挂在几个代售渠道上 |
| 旅客—取票通知 | 1:N | 一位旅客可收到多次取票通知;一条通知对应一次取票结果 |
旅客和票的1:N是最好理解的:你不可能和另一个人共享同一张实体票,但你可以替全家订五张票。航空公司与票的1:N同理。真正需要留意的是旅行社与机票的M:N,M:N不能直接在关系数据库里落地,后面建物理表时要拆成一张“代售关系”表,这张表里存旅行社编号、票号、代售时间和分成比例。ER图阶段先画M:N没问题,但自己心里要清楚它不是最终表结构。
如果你打算照着这份PDF自己画一份,可以直接用下面这段PlantUML脚本,它和PDF里的ER图结构基本一致,只是补齐了主键标识:
@startuml left to right direction entity "旅客" as T { *旅客ID : char(12) -- 姓名 : string 性别 : char(2) 身份证号 : char(18) 工作单位 : string 旅行地点 : string 旅行时间 : datetime } entity "机票信息" as K { *票号 : char(14) -- 等级 : string 价格 : decimal(10,2) 帐单号 : char(12) 可售时间 : datetime 航班号 : char(8) } entity "航空公司" as A { *公司编号 : char(6) -- 名称 : string 合适航班 : string } entity "旅行社" as C { *旅行社编号 : char(6) -- 名称 : string 合适航班 : string } entity "取票通知" as N { *通知编号 : char(12) -- 旅客清单 : string 售出机票信息 : string } T ||--o{ K : "订购" A ||--o{ K : "提供" C }o--o{ K : "代售" T ||--o{ N : "接收" K }o--|| N : "对应" @enduml这段脚本用的是PlantUML语法,在支持PlantUML的编辑器或在线渲染器里可以直接转成实体关系图。符号说明:*标注主键,--把主键区和普通属性区分开,||--o{表示一端一条、另一端多条,也就是1:N,}o--o{表示两端都是多条,也就是M:N。如果手动画图,用Visio或亿图也不难,关键是基数符号和连线方向别画反。答辩时一定会问你“为什么旅客和票是1:N”,按上面的理由答就行。
2.3 照着PDF改图:三步把你题目里的实体加进来
拿到一份现成ER图,正确用法不是照抄,而是照着这个结构把你自己的课程设计题目重构一遍。我一般按三步走,比直接画省力很多。
第一步,名词提取。把你题目描述里所有名词抄出来,比如“订单”“支付”“退票”“航线”“会员积分”等等,然后逐个问自己:它有没有自己的属性?它会不会和另一个实体发生联系?如果两个答案都是“是”,它就是候选实体;如果只能回答一个“是”,多半是属性或联系。以“订单”为例,它有订单号、下单时间、总价,也跟旅客、机票都有联系,就是实体;“支付方式”只有类型和账号密码,一般不单独成实体。
第二步,做关系矩阵。把候选实体放进一个两两交叉的矩阵,逐个判断基数。这一步能避免常见的“画着画着多了一条线”。例如:
| 实体A | 实体B | 基数 | 理由 |
|---|---|---|---|
| 旅客 | 订单 | 1:N | 一个旅客可下多笔订单,一笔订单属于一个旅客 |
| 订单 | 机票信息 | 1:N | 一笔订单可包含多张机票,一张票一次只属于一笔订单 |
| 旅客 | 旅行社 | N:1 | 旅客只在某一家旅行社柜台订票 |
| 旅行社 | 订单 | 1:N | 一家旅行社经手多笔订单 |
第三步,决定要不要把“订单”实体加进去。PDF原图里旅客直接和机票信息相连,这只适合“每次订一张票”的简化场景。真实航空预订系统里一次下单可能买两张票、选两个舱位,还会把支付状态挂在订单上,所以大多数课程设计应该增加“订单”实体,把“旅客—机票”的连线改成“旅客—订单—机票”两段1:N。这样做的好处是,后面画数据流图时“订单表”和“订单状态”都有地方放,状态转换图也有明确的建模对象。
改图时记住一条底线:实体和属性但凡在需求描述里找不到,就不要自己发明。指导老师追问“这个会员等级从哪来的”,如果你答不出出处,整张图的信任度都会下降。反过来,需求里有但图里没有的字段,例如“乘客联系电话”,一定要补上,这叫诚实画图。
3. 数据流图从顶层拆到0层:三个外部实体与四个加工的边界
3.1 顶层图只画一个系统和三个外部参与者
数据流图的价值在于把“系统边界”画出来。顶层图也叫上下文图,全图只能有一个加工,就是你要开发的“航空机票预订系统”,剩下的方框只能是外部实体。外部实体的判定标准很严格:它必须独立于系统之外,能主动发出或接收数据,且自身不受系统内部控制。按这个标准检查PDF里出现的参与者,顶层图应该只保留三个外部实体:旅客、旅行社、航空公司。
旅客是预订行为的发起端,也接收系统返回的取票通知和帐单。旅行社在本系统里是中间业务节点:系统把售出机票信息给旅行社,旅行社向系统提供可售机票信息和出票确认。航空公司是资源端:向系统提供航班信息,接收系统的订票清单。要特别注意“取票通知”不是外部实体,它是系统内部加工产生的数据结果,最终发给旅客,不是第四个参与者。很多课程组在这里多画一个方框,后面我们会在避坑部分展开说。
顶层图的数据流要命名得清楚,方向也不能含糊。我一般维护一张数据流清单,防止画到最后连方向都记不住:
| 数据流 | 起点 | 终点 | 内容 |
|---|---|---|---|
| 预订请求 | 旅客 | 系统 | 出发地、目的地、旅行时间、乘机人信息 |
| 航班检索结果 | 系统 | 旅客 | 可选航班、舱位价格、余票数 |
| 售出机票信息 | 系统 | 旅行社 | 已订机票的票号、乘客姓名、航班信息 |
| 可售机票信息 | 旅行社 | 系统 | 各渠道可售航班与舱位数据 |
| 取票通知 | 系统 | 旅客 | 取票地点、取票时间、机票清单 |
| 订票清单 | 系统 | 航空公司 | 待出票订单汇总 |
这里有一个现实的建模选择:PDF的文字描述里提到“系统将机票信息传递给旅行社,旅行社将机票信息转换为取票通知”,如果完全照这个描述,旅行社会被画成系统内部的一个加工节点。我更建议把它作为外部实体处理,理由很简单:你的课程设计系统不可能实现旅行社的全套代售管理,你要做的是“连接旅行社”而不是“变成旅行社”。把旅行社放外部,系统边界清晰,子图也容易拆;如果你确实想做一个包含旅行社后台的系统,那就把这些功能拆到0层图里,同时说明系统范围变大,数据存储也会多好几张表。
3.2 0层图拆出四个加工:受理、查询、出票、通知
有了顶层图,下一步把“系统”这个黑匣子打开,画0层图。0层图里加工的数量没有固定标准,但机票预订这类业务,拆成四个加工最稳:P1受理预订,P2查询航班,P3确认订单并出票,P4发送取票通知。每个加工都要标注输入流、输出流和需要访问的数据存储。
| 加工编号 | 加工名 | 输入数据流 | 输出数据流 | 访问的数据存储 |
|---|---|---|---|---|
| P1 | 受理预订 | 预订请求 | 订单信息 | D1旅客表、D3订单表 |
| P2 | 查询航班 | 航班查询条件 | 合适航班 | D2航班信息表 |
| P3 | 确认订单并出票 | 订单信息、可售机票信息 | 售出机票信息 | D2航班信息表、D3订单表 |
| P4 | 发送取票通知 | 订单信息、旅客清单 | 取票通知 | D4取票通知表 |
这个拆分顺序对应真实订票流程:旅客先发起预订,系统校验乘机人信息;然后按出发地、目的地和时间查航班;查到可售票后提交订单,系统向旅客确认价格与帐单;最后生成取票通知发送出去。注意DFD中“查询航班”必须在“确认订单”之前,两者之间有先后依赖,但在DFD里不画箭头依赖,而是通过数据流组合体现。如果你想表现时间顺序,那是状态转换图或活动图的事,不要混进数据流图。
数据存储在0层图里用开口矩形表示,上面表里的D1到D4就是最小集合。经常有人把“订票清单”和“取票通知”合并成一张存储,我建议拆开:订票清单是给航空公司结算用的,取票通知是给旅客取票用的,一个是结算数据,一个是交付数据,生命周期不一样。合并存储也许能少画一个矩形,但后面写数据字典时字段会互相污染,得不偿失。
3.3 编号、命名与父子图平衡:三条规整化规则
DFD画到最后容易乱,乱的原因通常是三条规则没守好。第一条是加工编号要自顶向下分层。顶层图不编号,0层图用P1、P2、P3、P4;如果再往下拆,比如把P2“查询航班”继续拆成“按航线查询”“按日期查询”“按价格过滤”,新加工编号就是P2.1、P2.2、P2.3。编号除了好看,还有个实际作用:指导老师问“P2.2是干什么的”,你能立刻说出它的父加工是P2,子加工数据流要和P2的输入输出对得上。
第二条是数据流一定要用名词短语命名,不能用动词短语。这是DFD新手最常见的命令错误。“查询航班”不是数据流,“航班查询条件”才是;“通知旅客”不是数据流,“取票通知”才是。原因很简单:数据流是数据在管道里流动时携带的内容,内容永远是名词性的;动词属于加工的职责,放在加工框名称里。我给课程组检查图时,会直接扫一遍所有数据流标签,只要看到一个“XX并XX”的动词结构,就说明他还没把DFD和程序流程图画分家。
第三条是父子图平衡性检查。父图中进入某个加工的一条输入流,在拆开子图后必须仍然存在,并且最终要走到子图里的某个加工;父图里加工产生的每条输出流,在子图里要么作为某个子加工的输出,要么作为子图与外部实体或数据存储之间的流。简单说,父图的输入输出不能被丢掉,也不能凭空多出来。这个检查我放在最后做,因为往往要改两三轮才能平衡。你可以把父图和子图放在同一张纸的左右两侧,用彩色笔把同名数据流连成线,连不上就是不平衡。
三条规则之外还有一个重要的边界:数据流图绝不画控制流。你不需要在DFD里画“如果没票就提示失败”,那是加工内部逻辑或状态转换图该表达的东西。DFD只表达数据从哪来到哪去,画控制依赖会让图和程序流程框图趋同,丢了结构化分析的意义。
4. 状态转换图与数据字典:动态行为与静态定义怎么互相补位
4.1 订单状态机:把“检索航班”踢出状态列表
状态转换图在四张图里最容易被画错,一个很重要的原因是很多人把它和“流程图”混在一起。状态转换图描述的是某个对象的一生,在这个系统里,这个对象就是一笔订单。它不是描述“系统先做什么、后做什么”,而是描述“订单在某个时刻处于什么状态,遇到什么事件会跳到下一个状态”。
以航空机票预订系统的核心业务为例,订单状态机至少包含五个状态:待支付、已支付、已出票、已取票、已取消。把状态迁移画成一张表,比直接画圈更利于检查:
| 当前状态 | 触发事件 | 下一状态 | 备注 |
|---|---|---|---|
| 待提交 | 旅客提交预订 | 待支付 | 进入待支付前要校验乘机人信息 |
| 待支付 | 支付成功 | 已支付 | 库存占用生效 |
| 待支付 | 用户取消或超时 | 已取消 | 释放库存 |
| 已支付 | 出票成功 | 已出票 | 生成票号与帐单 |
| 已出票 | 旅客取票完成 | 已取票 | 终态 |
| 已取消 | — | — | 终态 |
这里要区分“状态”和“活动”两个概念。状态是业务对象在等待某个事件时停留的一种相对稳定的情形,比如“待支付”表示订单挂在那里等支付结果。活动则是瞬间完成或持续进行的动作,比如“系统检索机票信息”“发送取票通知”。如果你把“检索航班”写进状态框,那张图就变成了一张披着状态图外衣的流程框图。判断某一项是不是状态,可以问一个问题:这个对象能不能在这个词上面停留五分钟?能停留,才有资格当状态。“正在检索”不可能停留五分钟,因为检索要么开始要么结束,所以它不是状态。
状态转换图里每个状态间的连线还要标事件,不能只画箭头不写字。事件名用动词短语没问题,例如“支付通过”“退票申请”,因为事件是动作触发的,这和DFD里数据流必须用名词不冲突。画完整张状态图后,最好把“订单状态”字段的所有取值和状态图里的圆框一一对照,这已经算数据字典工作了,正好引出下一节。
4.2 数据字典分三层:数据项、数据流、数据存储
数据字典是四张图里最枯燥但也最堵漏洞的部分。很多人以为数据字典就是把图里的中文名字抄一遍,结果指导老师一问“旅客编号几位数”就答不上来。严格的数据字典分三层:数据项、数据流、数据存储,外加每个加工的结构化说明。
数据项是字段级定义,用“=”表示组成关系,用“|”表示或关系。例如:
- 旅客编号 = 姓名 + 性别 + 身份证号 + 工作单位 + 旅行地点 + 旅行时间
- 订单状态 = 待支付 | 已支付 | 已出票 | 已取票 | 已取消
光写组成还不够,重要字段要补类型、长度和取值范围。给大家一个可以抄作业的格式:
| 数据项 | 类型/长度 | 取值范围/备注 |
|---|---|---|
| 旅客编号 | char(12) | 前4位日期,后8位流水号 |
| 身份证号 | char(18) | 按国标校验 |
| 票号 | char(14) | 前8位航班号,后6位座位序号 |
| 价格 | decimal(10,2) | 单位元 |
| 订单状态 | varchar(10) | 待支付、已支付、已出票、已取票、已取消 |
数据流层是给DFD的每条数据流写定义。例如:
- 预订请求 = 旅客编号 + 出发地 + 目的地 + 旅行时间 + 舱位等级
- 取票通知 = 通知编号 + 旅客清单 + 售出机票信息
数据存储层则定义一张表的完整结构,例如:
- 订单表 = {订单号 + 旅客编号 + 航班号 + 订单状态 + 取票通知编号},按订单号组织索引
加工说明用结构化自然语言描述,一般不超过十行。例如P3“确认订单并出票”的加工说明可以写成:IF 存在可售机票 THEN 生成订单记录,置订单状态为“待支付”,并返回价格帐单;ELSE 返回“无票”信息。这样写的好处是,后面编码阶段可以直接把这个结构化说明翻译成程序逻辑,不用再回头猜图。
4.3 四张图的字段一致性交叉检查
数据字典不是画完就完了,它最大的作用是当“校准尺”。因为ER图、DFD、状态转换图是三个不同视角画出来的,如果没有统一的数据字典,三张图很容易自相矛盾。我每次都会做一轮交叉检查,照着下面五条逐一过:
- ER图中每个实体挂的属性,必须能在数据字典里找到对应的数据项或数据存储字段。找不到,说明实体是空壳。
- DFD中每条数据流,必须在数据字典的数据流层有定义,且定义里的每个组成项都能在上游数据存储或外部实体数据中找到来源。
- 状态转换图里出现的每一个状态值,必须出现在“订单状态”数据项的取值列表中。有人状态图里写了“已支付”,数据字典里却只有“已预订”,这就是明显的断链。
- DFD里每个数据存储,至少要对应ER图里的一个实体;反过来,ER图里的核心实体也至少要出现在一个数据存储里。
- 每个状态迁移的触发事件,在DFD的输入数据流中必须能找到对应的数据载体。例如“支付成功”事件,数据字典里要有“支付结果通知”或“订单状态变更请求”这条数据流。
这一轮检查做完,四张图才真正成套。很多指导老师第一遍看课设,不看实体也不看加工,直接拿状态图里的状态值去数据字典里找,找不到就直接扣分。所以请在交图前,把上述五条当作验收清单逐项打勾。
5. 避坑五连:课程设计图件中最常见的五个翻车点
这一章不说理论,只说我在帮课程小组拆图、改图过程中反复踩过的坑。每一条都是“现象—原因—解决”的结构,你在画图时照着比对就好。
5.1 ER图联系线画成蜘蛛网
现象:旅客、旅行社、航空公司、机票信息、取票通知五个实体之间画了十几条连线,连“航空公司—旅行社”都直接连上,整张图密密麻麻,根本没法读。
原因:画图时没有先判断两个实体之间是否存在直接业务关系,只要业务上“沾边”就拉一条线。实际上很多联系是间接的,通过中间实体就能表达。
解决:先列关系矩阵,只保留有直接数据交换的实体对。航空公司和旅行社之间的代售关系,通过“机票信息”这个中间实体就能表达,不需要多画一条线;如果题目明确要求记录“某个旅行社代售某航空公司机票”的代理关系,那就新增“代售关系”实体,而不是画一条无差别的线。判断标准一句话:这条线不经过中间实体,能不能解释出具体业务动作和数量基数?解释不出来就不要画。
5.2 顶层DFD里多画了“取票通知”这个盒子
现象:顶层图里出现四个外部实体:旅客、旅行社、航空公司、取票通知。看起来好像没毛病,毕竟系统确实产出了取票通知。
原因:把“系统画给别人的数据”误当成了“系统外部的人”。取票通知是系统内部加工后输出的一张凭证,它不主动和系统交互,也不能独立发起数据流。
解决:记住外部实体的三个条件:独立于系统、能主动发起或接收数据、不受系统内部控制。取票通知三个条件一个都不满足。顶层图就三个外部实体:旅客、旅行社、航空公司。如果取票通知也算外部实体,那“帐单”“机票清单”是不是每个都要画一个盒子?显然不成立。这层想通,就能避免一系列重复盒子的错误。
5.3 状态转换图画满了“正在检索”“正在出票”
现象:状态框里全是“正在查询航班”“正在生成通知”,整张状态转换图看起来和流程图、DFD没什么区别。指导老师一眼就看出来你没理解状态建模。
原因:把加工动作直接搬进了状态框,没有区分“对象的状态”和“系统的动作”。状态转换图的建模对象是订单,不是系统CPU的忙碌情况。
解决:用“能不能停留五分钟”这个方法删掉假状态。订单可以“待支付”五分钟,可以“已出票”好几天,所以它们是状态;订单不可能“正在检索”五分钟,要么瞬间完成要么报错,所以它不是状态。画完图后从头扫一遍,看到“正在”“开始”“进行中”这类词,直接改掉。如果你要表达系统内部处理顺序,那是流程框图的事,状态图管不了。
5.4 数据字典没有类型、长度和取值范围
现象:数据字典里只有“订单=订单号+旅客信息+航班信息”这样的中文组合表达式,问“订单号几位数”“订单状态有哪几个值”,回答不出来。
原因:把数据字典当成名词解释表,没有认识到它本质上是给后续数据库设计提供依据的字段规范。
解决:给每一个关键数据项补上类型、长度、取值范围。订单号就写char(16),前8位日期、后8位流水号;订单状态就写明只有“待支付、已支付、已出票、已取票、已取消”这几个合法值。你写不出来的字段,数据库大概率也建不出来。指导老师问“旅客编号在哪定义”,你直接把数据字典那一行指给他看,比现编一个答案强得多。
5.5 ER图、DFD、状态图字段各说各话
现象:ER图里旅客实体有“工作单位”,但DFD里预订请求数据流没带这个字段,状态图里也没有任何状态与它相关,数据字典里更查不到。整份材料各图之间对不上。
原因:画图时没有一份统一的字段主表,ER图归ER图画,DFD归DFD画,想到哪画到哪。
解决:建一张“字段主表”,把系统所有字段的中文名、英文名、类型、长度、属于哪个实体、出现在哪条数据流,全记在一张表里。之后画任何一张图,字段都从主表里取,不在主表里的字段不允许出现在图上。这比画完四张图再回头检查效率高很多。如果你已经画完了,就用4.3节那五条交叉检查逆推,把不一致的地方修掉。
提示:这五个坑有前后连带关系。我最常犯的是先画完ER图就急着画DFD,结果字段不一致。建议按“ER—DFD—状态图—数据字典”的顺序画,画完再做一轮反向检查。
6. 答辩前的一页纸讲法:用数据走查把四张图串成业务闭环
图全画好之后,最容易被忽略的一件事是“讲图”。答辩时你只有三五分钟把整套设计说明白,如果按PDF顺序从ER图讲起,大概率只讲到第二张图时间就到了。我习惯把四张图压成一条业务主线,讲法如下:先在黑板上从左到右写下三个外部实体——旅客、旅行社、航空公司,中间写系统方框。开讲第一句话固定为:“旅客提交预订请求,系统查询航班,确认订单后把售出机票信息同步给旅行社,同时生成取票通知返回给旅客。”这句话把顶层DFD的主干数据流全带出来了。
接下来按五个步骤展开,每一步只讲一句话,并指向对应图件:
| 步骤 | 内容 | 用哪张图 | 一句话示例 |
|---|---|---|---|
| 第一步 | 定边界 | 顶层DFD | 系统外部只有旅客、旅行社、航空公司 |
| 第二步 | 摆角色 | ER图 | 旅客订票、公司供票、旅行社代售、取票通知作为交付凭证 |
| 第三步 | 看流转 | 0层DFD | P1到P4四个加工把预订请求变成取票通知 |
| 第四步 | 盯状态 | 状态转换图 | 一份订单按“待支付→已支付→已出票→已取票”走完生命周期 |
| 第五步 | 查定义 | 数据字典 | 所有数据流和订单状态取值在字典里都有定义 |
这套讲法最实用的地方在于:它不是背图,而是顺着数据走。答辩前我还会做最后一轮“数据走查”——拿一笔具体的订单,比如“某旅客本周五从A城订一张到B城的机票”,从顶层图的预订请求进入,沿着DFD走一遍。每经过一条数据流,查一次数据字典有没有定义;每到一个状态变化,查一次状态转换图有没有这条迁移;每碰到一个数据存储,查一次ER图有没有对应实体。三分钟走完这笔订单,整套图的断链就全部现形。
有一次我帮某课程小组过图,发现他ER图里有“支付记录”实体,但DFD里没有对应的数据流,状态图也没有“支付成功”这个触发事件。我让他拿一笔订单沿数据走查走一遍,走到“待支付”那一站他自己就愣住了,因为订单停在待支付后没有任何路径能往前走。后来他补了支付回调数据流,状态图也加了“支付成功”迁移,整套图才真正闭环。从那以后,我每次交课设图之前,都强制自己走一遍这条数据主线,翻车率从肉眼可见降到基本为零。希望帮到你。
本文还有配套的精品资源,点击获取