面向数据流的需求分析:数据流图、数据字典与加工说明
简介这份PPT面向软件工程课程学习者与需求分析入门者围绕面向数据流的分析方法展开重点解决从现实业务到逻辑模型、物理模型的建模与需求定义问题。压缩包仅含1个PPT文件大小约1.41MB内容以课堂讲义形式组织便于按讲次查阅和复习。已有226人学习说明其适合作为课堂配套资料使用。讲义以小型图书馆管理系统为例串联借书、还书、增删图书、检索与借阅记录查询等需求讲解抽象、模型、逻辑模型与物理模型、需求获取、功能性/非功能性需求、需求定义及分析验证等知识点并对比结构化开发方法与面向对象开发方法。读者可据此理解数据流分析的基本流程、需求建模的表达方式及从当前系统到目标系统的转换思路适合课程复习、作业参考和需求分析入门梳理。1. 从一张借书单说起面向数据流的分析方法到底在分析什么去图书馆借一本书你递出借书证管理员在系统里敲几下键盘这本书就从「在馆」变成了「借出」。整个过程里真正被搬来搬去的不是书是数据一条借阅记录、一次库存状态变更、一次借阅额度检查的结果。面向数据流的分析方法就是把注意力集中到这些「搬来搬去的数据」上的一套需求建模办法——它先不问系统由哪些对象组成而是问数据从哪来、经过哪些加工、存到什么地方、最后流向谁。软件工程里讲需求分析这条路子流传了几十年因为它要求你在动手写代码之前先把「系统到底要处理哪些数据」说明白。搞懂它再看需求评审会上那几张画着圆圈和箭头的图就不会觉得那只是玄学。2. 需求为什么不能直接开写从物理模型到逻辑模型的关键一步2.1 现实世界和计算机世界之间隔着一层模型一个校园教材采购场景学生要买教材先填一张购书申请交到某个科室审查审查通过后开发票、开领书单学生拿着领书单去领书。这条线上有纸张、有办公室、有来回跑的人。这套东西在软件工程里叫当前系统的物理模型它如实记录了现实里发生的一切包括大量与「系统该做什么」毫无关系的信息谁在哪间办公室、单据什么颜色、盖哪个章、走几层楼。直接把这一套搬进计算机得到的是一个照着现有流程复刻的电子壳子原来的三个签字变成三次点击原来的两张纸变成两个页面效率没提高毛病倒是一个不落全固化了。所以需求分析的第一步不是问「怎么把它做成软件」而是先把物理模型里的非本质因素剥掉。剥完之后剩下的那层东西才叫逻辑模型。物理模型回答「现在是怎么做的」逻辑模型回答「本质上在做什么」目标系统的逻辑模型回答「换成计算机做应该做什么」。这中间隔着一次映射现实世界 → 概念符号模型 → 计算机世界。映射做得好不好直接决定后面所有设计的返工量。2.2 抽象地铁图为什么不按真实比例画抽象这个词被讲得太重其实日常里到处都是。地铁线路图就是个好例子它不按真实地理比例画站点间距被拉平线路被拉直河流和街区统统消失。但在换乘这件事上它比卫星地图好用一百倍。它舍弃的是地理精度保留的是「哪条线在哪一站能换乘」这个连接关系。需求分析里的抽象干的是同一件事按你关心的维度保留其余全丢掉。保留什么输入是什么、做了什么处理、输出是什么、存了哪些数据。丢掉什么用什么设备、谁坐在哪个屋、界面是蓝色还是绿色。抽象的结果是一套概念符号模型——数据流图、数据字典、加工说明都属于这一类。它们的共同点是纸上没有一个像素但你能照着它把系统造出来。提示抽象不是「简化」而是「有选择地省略」。省错了东西图就变成废纸省对了东西图就是设计图纸。2.3 当前系统的逻辑模型和目标系统的逻辑模型需求分析的过程可以拆成几步走先调查现实环境拿到当前系统的物理模型再去掉非本质因素抽出当前系统的逻辑模型然后分析当前系统和目标系统的差别建立目标系统的逻辑模型接着细化、改进、优化最后做需求验证。用小型图书馆管理系统比一比就清楚了。现在借书靠手写登记本逻辑上只有三件事登记一条借阅关系、判断这本书是否在馆、判断这位读者还有没有额度。目标系统做的也还是这三件事只是执行者从人变成了程序。差别不在「业务变了」而在「谁来执行、执行得多快、能不能并发」。把这三件事写成处理逻辑就是逻辑模型把它落到具体界面、数据库表、服务器数量上才回到物理模型。很多人一上来就聊数据库建几张表、接口怎么设计本质是把物理模型当成了起点跳过了中间那一层——后面需求一改全盘翻车血泪经验大多来自这里。项目里的图书馆系统有两条明确的业务约束馆内所有未借出的书必须能随时供读者借阅同一时刻一本书不能既被借出又被借阅一个读者一次借出的数量不能超过预定值。这三条在物理模型里体现为「管理员看一眼登记本」在逻辑模型里就必须写成可判断的规则否则程序根本没法执行。2.4 功能需求管做什么非功能需求管做到什么程度需求分两条腿。功能性需求定义系统做什么描述系统必须支持的功能和过程。图书馆系统里那几条就是典型的功能需求借书、还书增加或删除一本书按作者名或专业领域检索一批书找出某位读者借出的一批书找出最近借走某本书的读者。系统有两类用户——图书管理员和普通读者其中「找出某位读者借出的书」供普通读者用借书、还书、增删图书、查最近借阅人这几项供管理员用。功能需求最怕写成一个动词短语就交差「借书」两个字背后其实藏着校验、写入、更新状态三步。非功能性需求定义系统工作时的特性描述操作环境和性能目标。它通常包括存储容量限制、执行速度、响应时间、吞吐量这类性能指标硬件设备、操作系统、网络、数据库这类环境约束与外部系统的输入输出、数据格式、存储介质这类界面约定以及用户类型、熟练程度、培训需求、误操作可能性这类人的因素。这类需求最容易被写成一句「系统要快」然后被所有人忽略直到上线那天才发现检索一万本书要等八秒。需求类型回答的问题图书馆系统里的例子功能需求系统做什么借书、还书、增删图书、按作者检索、查借阅人性能需求做得多快、能扛多少检索响应时间、并发借阅处理能力环境需求跑在什么上面数据库类型、网络条件、部署位置界面需求和外界怎么交换数据书目数据导入格式、借阅记录导出格式用户因素谁在用、好不好用读者自助检索的易用性、管理员的误操作容忍度需求分析要达成的目标也就清楚了给出数据领域、功能领域、行为领域三个方面的模型提出详细的功能说明确定设计约束条件规定性能要求同时保持和用户的密切沟通让用户明确自己那一侧要配合什么。这三件事缺一件需求文档就只是写给自己看的。3. 数据流方法的三件套数据流图、数据字典、加工说明3.1 数据流图里只有四种角色数据流图看起来符号很多其实只有四种角色在台上。外部实体是系统边界之外、跟系统打交道的人或系统图书馆系统里就是读者和图书管理员。加工是对数据做变换的动作借书处理、还书处理、图书维护、检索服务都是加工。数据存储是数据待着不动的地方图书目录、借阅记录、读者档案。数据流是数据在它们之间移动的路径一张借书请求从读者流向借书处理一条借阅记录从借书处理流向借阅记录存储。这四种角色构成一套极简语法好处是逼你把「谁给的数据、经过什么处理、存到哪、给谁看」四件事一次说全。需要注意数据流图画的是数据怎么流动不是程序执行顺序也不表达判断和循环。图上不会出现「如果书已借出则提示失败」这种分支那属于加工说明的内容。初学者最容易在这上面出错把数据流图画成带菱形判断框的流程图画完自己还挺满意评审时被问一句「你这个箭头是数据还是控制信号」就卡住了。3.2 分层从一张顶层图逐层往下拆真实系统的数据流图不可能只有一张那样画出来会像一团毛线。常规做法是分层顶层图只画系统作为一个整体黑匣子和外部实体之间的输入输出0 层图把黑匣子打开露出里面的主要加工再往下每一层继续拆直到每个加工都小到能写清楚一段说明。图书馆系统的顶层图很干净读者给出借阅请求系统返回借阅结果管理员给出图书维护指令系统返回处理结果。到了 0 层就能看到借书处理、还书处理、图书维护、检索服务四块它们共同读写图书目录和借阅记录两个存储。再往下拆借书处理会露出「校验读者状态」「校验图书状态」「写入借阅记录」「更新图书状态」几个子加工。分层画的时候要守住一条规则父子平衡。上层某个加工的输入输出数据流必须和它拆开之后那一层图边界上的输入输出对得上不能凭空多出来一条也不能悄悄少一条。这条规则很枯燥但它是唯一能防止「画到第三层发现对不上、只好回去改第一层」的机制。3.3 数据字典把每条数据流说清楚图能让结构一眼看清楚但图上的每条箭头都得有个准确含义。数据字典干的就是这件事把数据流、数据项、数据存储、加工的定义统一登记下来让所有人对同一个名字有同一个理解。没有它同一张图上「借阅记录」可能在一个人脑子里是书名加日期在另一个人脑子里还包括罚款金额等做出来才发现差了一截。数据字典常用几个简单符号等号表示定义加号表示顺序连接竖线表示从中选一个花括号表示重复若干次圆括号表示可选。举个简化例子「借阅记录 读者编号 图书编号 借出日期 (归还日期)」读起来就是一条借阅记录由读者编号、图书编号、借出日期顺序组成归还日期可能为空。「图书目录 {图书条目}」表示图书目录是若干图书条目的集合。这些符号不复杂价值在于强制你把含糊的词拆到不能再拆。条目名类型简述组成借阅请求数据流读者发起借书时的输入读者编号 图书编号借阅记录数据存储记录谁借了什么、何时借何时还读者编号 图书编号 借出日期 (归还日期)图书条目数据项组一本书的登记信息图书编号 书名 作者 专业领域 在馆状态借阅额度数据项单个读者可同时借阅的上限整数3.4 加工说明小说明怎么写才不靠猜数据流图的最底层加工没法再拆了这时候要靠加工说明把它讲清楚。常用的三种写法是结构化语言、判定表、判定树。结构化语言接近自然语言但更克制判定表适合规则多、条件交叉的情况判定树把条件一层层展开更直观。拿借书这个加工来说文字写「校验读者和图书状态通过后写入借阅记录」太糊写成可判定的逻辑才没有歧义# 借书加工的判定逻辑对应数据字典里的借阅请求、借阅记录、借阅额度 def check_borrow(book, reader, limit): # 规则一同一时刻一本书不能既被借出又被借阅 if book.status ! 在馆: return False, 该书已借出 # 规则二读者一次借出的数量不能超过预定值 if reader.borrowed_count limit: return False, 已达借阅上限 # 规则三读者状态必须可用未挂失、未过期 if not reader.active: return False, 读者状态异常 return True, 可以借阅这段代码不是让你真去实现系统而是演示加工说明该精确到什么程度。三个参数正好对应数据字典里的三个条目book是图书条目reader是读者档案limit是借阅额度。每一条 if 分支都来自现实世界里的一条业务约束反过来也能验证数据字典是不是漏了字段——比如你想写「读者状态异常」却发现自己没定义读者状态那就是字典缺项。三种写法里规则少就用结构化语言规则交叉多就上判定表条件有层次就用判定树选哪个不重要写到别人能照着测才算过关。4. 面向数据流还是面向对象两种建模视角的分界线4.1 一个顺着信息流向切一个顺着信息内容切现有的需求分析建模方法可以按关注点分成两大阵营。面向信息流向的一派代表是结构化分析方法它顺着数据在系统里怎么流动来切分系统面向信息内容的一派代表是面向对象分析方法它顺着数据本身由什么构成、有哪些行为来切分系统。描述系统需求时本来就可以从功能、行为、信息三个侧面入手侧重点不同画出来的图自然不一样。结构化方法的核心产物是一组图加一套字典讲的是「数据从 A 到 B 经过哪些变换」。面向对象方法的核心产物是类、属性、方法、关系讲的是「这个东西是什么、能干什么、和谁有关系」。同一个图书馆系统结构化视角看到的是借书处理、还书处理、检索服务几条流水线面向对象视角看到的是图书、读者、借阅记录几个对象借书是读者对象和图书对象之间发生的一次交互。这两种视角不存在谁更先进的问题它们回答的是不同的问题。就像描述一栋楼你可以画人流的动线图也可以画房间的功能分区图两张图都正确但你要拿去审批消防通道动线图更管用。4.2 为什么结构化方法天然偏爱数据流结构化开发方法有一条贯穿始终的思路自顶向下、逐层分解。这条思路和数据流是天生一对。因为数据流天然有层级——顶层看整个系统的进出往下一层看几大处理块之间的流转再往下一层看单个处理块内部的细节。每一层都是一次「把黑匣子打开」打开的依据就是数据在这个加工内部怎么变。这套分解还有个副产品它能顺手暴露数据的不一致。某个数据项在 0 层图里出现在 1 层图里消失了或者某个存储只写不读一眼就能看出来。结构化方法在信息管理系统、批处理系统这类「数据进出清晰、加工链条长」的场景里特别顺手原因就在这。面向对象方法的长处则在另一头当系统里对象关系复杂、状态多、行为需要封装时按数据内容切分更能控制复杂度。两种方法后来在实践里也经常混着用——先用数据流把业务流程理清楚再用对象模型把领域概念固定下来这不算犯规。4.3 两种方法不是新替旧的关系对比维度面向数据流结构化分析面向对象分析切分依据数据流向与加工过程信息内容与对象职责主要产物数据流图、数据字典、加工说明类图、用例、交互序列擅长场景信息管理系统、批处理、流程清晰的数据加工对象关系复杂、状态多、需要长期演进的系统对需求变更的耐受流程一变就要改图改动面较大对象边界稳定时变更局部化更好沟通对象业务人员容易看懂箭头和加工技术人员更容易对齐设计看完这张表会发现选择的关键不在「哪个新」而在「这次的问题长什么样」。业务流程占主导、数据加工链条长、需要和不懂技术的业务方对齐那就先上数据流。领域概念复杂、对象之间交互频繁、后续要反复迭代那就先上对象模型。硬要把一个实时控制系统画成数据流图画到第三层你就会发现自己不得不往里塞控制信号而控制流本来就不是它该画的东西。5. 五个一学就混的地方把数据流方法用错的常见误区5.1 把数据流图当流程图最容易混的一对。数据流图上的箭头表示数据在移动流程图上的箭头表示执行顺序还带菱形判断和回退。混的原因很实在两者都长着箭头和方框画在纸上远看差不多。区分办法很简单问一句「这条箭头上流的是什么」。能说出一个具体的数据名词比如借阅请求、借阅记录、检索条件那就是数据流如果这条箭头表达的是「先做这个再做那个」或者「如果失败就回到上一步」那它就是控制流不该出现在数据流图上。判断和循环要写进加工说明而不是画进图里。5.2 物理模型和逻辑模型分不清混的原因在于两者经常同时出现在一张草图上左边写着「管理员在借阅台登记」右边画着数据库表中间还夹着服务器部署。看着挺完整其实三个层次糊在一起了。区分办法是看它是否依赖具体实现。如果描述里出现「在哪个屋」「用什么设备」「几张表」「什么界面」那是物理模型如果只剩「输入什么、做什么判断、输出什么、存哪些数据」那是逻辑模型。做需求分析时先老老实实把逻辑模型画干净再往物理模型落顺序反了就会把实现细节当成需求本身后面改一处牵动全身。5.3 需求分析和需求定义当成同一件事很多人把这两个词当同义词用。混的原因是两个阶段都在跟用户聊、都在产出文档边界不明显。区分办法看产出物的性质。需求分析偏「摸清楚」调查现实环境、抽取逻辑模型、分析当前与目标的差别产出的是模型和说明。需求定义偏「定下来」确定数据领域、功能领域、行为领域三方面的模型提出详细功能说明确定设计约束规定性能要求产出的是可以拿去评审、签字、作为验收依据的东西。分析做完了不等于定义做完了中间还差一次和用户的确认。5.4 只写功能需求把约束当注释这是最容易在项目后期出问题的一条。功能需求写得很欢借书还书增删检索一条不落非功能需求就一句「系统要稳定、响应要快」。混的原因在于约束类需求不好写写「同一时刻一本书不能既被借出又被借阅」比写「支持借书功能」费劲得多。区分办法是拿一个笨办法逐条过这个功能在什么情况下会失败失败时系统该给什么反馈同时有两个人操作会怎样数据量涨十倍还撑得住吗图书馆系统里那三条约束本质上就是三个必须写进需求文档的失败条件。把这些当成注释随手记在页边最后十有八九没人实现。5.5 数据字典当成可选的装饰图画得漂亮字典随便写两行觉得反正大家看得懂。混的原因在于图的直观性太强让人误以为理解已经对齐了。区分办法是做个测试随便挑图上一个数据流名字让三个人分别说出它由哪些数据项组成。说得一致字典可以少写说得不一致说明这个名字背后藏着三种理解。数据字典的价值就在这种笨拙的地方它把「大家应该都懂」变成「白纸黑字写着」。6. 什么时候该画数据流图什么时候别硬套先说适合的情况。业务流程占主导、数据加工链条长、参与方多且不懂技术这类需求用数据流方法梳理最顺。典型如信息管理系统、报表统计、审批流程、数据迁移——它们的共同点是「输入、处理、输出、存储」四件事能说清楚而系统里真正复杂的不是对象关系是流程分支和数据口径。这类场景里一张 0 层图往往比十页文字更能让业务方点头因为它把「你的数据从哪来、我加工完给谁」摆在了明面上。再说别硬套的情况。实时控制系统、强交互产品、算法密集型模块这三类都不太适合。实时控制里真正关键的是状态机和控制信号数据流图根本没法表达「两秒内必须响应中断」这种时序约束强交互产品关心的是界面状态和用户路径用加工和数据存储去描述会非常别扭算法密集型模块的重点在计算过程本身画一堆数据流出来信息量还不如一段伪代码。拿图书馆系统做个具体判断。需求有六条借书、还书、增删图书、按作者或专业领域检索、查某读者借出的书、查最近借走某本书的读者。三类用户权限清楚两条硬约束明确。这些需求几乎全是「数据进—加工—数据出」的形状画数据流图收益很高。但如果你要给这个系统加一个「扫码即借」的移动端那部分涉及设备交互、权限弹窗、网络异常重试就不该继续用数据流图硬画交给用例和交互设计更合适。还有一个更实际的判断法看你的改动成本落在哪。如果需求变更主要是「流程加一个分支」「多一类数据来源」数据流图改起来很轻加一个加工、补两条数据流、同步数据字典就行。如果变更主要是「对象多了一种状态」「对象之间的关系变复杂」那数据流图会越改越乱这时候该换视角了。注意数据流图不是画得越细越好。每层控制在七上八下七个左右加工是人能读进去的上限超过就该再分一层否则评审时没人看得下去。我自己的习惯是任何需求文档交出去之前先拿一张白纸把顶层图画一遍只画系统边界和外部实体逼自己回答两个问题谁给我数据我把数据给谁。画不出来说明这需求压根没想清楚先别急着开会。画得出来再往下拆一层看看有没有哪个加工我写不出一句准确的说明——写不出来的那个通常就是后面会出问题的地方。这个笨办法救过我几次从那以后我每次评审需求都强制走一遍图可以不给人看但那两个问题必须自己答上来。希望帮到你。本文还有配套的精品资源点击获取