3.3.2 数据流图
数据流图是结构化分析最基本的工具,数据流图从数据传递和加工的角度,以图形化的方式刻画数据流从输入到输出的移动和变换过程。在数据流图中具体的物理元素都已去掉,只剩下数据的存储、流动、加工和使用情况。这种抽象性能使人们总结出信息处理的内部规律性。由于数据流图是用图形来表示逻辑系统的,即使不是计算机专业人员也能比较容易地理解数据流图,因此它成为了一种极好的通信工具。
1.数据流图的基本符号
数据流图由如图3-2所示的4种基本符号表示。

图3-2 数据流图的基本符号
图3-3是一个简单的数据流图,它表示数据X从数据源S流出,经P1加工转换成Y,接着经P2加工转换为Z,在经过加工过程P2时,从F中读取数据。

图3-3 数据流图举例
1)数据流
数据流由一组确定的数据组成,例如“发票”为一个数据流,它由品名规格、单位、单价、数量等数据组成。数据流用带有名字的有箭头的线段表示,名字称为数据流名,表示流经的数据,箭头表示流向。数据流可以从加工流向加工,也可以从加工流进或流出文件,还可以从数据源流向加工或从加工流向终点。
对数据流的表示有以下约定。
(1)对流进或流出文件的数据流不需标注名字,这是因为文件本身就足以说明数据流;而别的数据流则必须标出名字,名字应能反映数据流的含义。
(2)数据流不允许同名。
(3)两个数据流在结构上相同是允许的,但必须体现人们对数据流的不同理解。例如,图3-4(a)中的合理领料单与领料单两个数据流,它们的结构相同,但前者增加了合理性这一信息。
(4)两个加工之间可以有几股不同的数据流,这是由于它们的用途不同,或它们之间没有联系,或它们的流动时间不同,如图3-4(b)所示。
(5)数据流图描述的是数据流而不是控制流。如图3-4(c)所示,“月末”只是为了激发加工“计算工资”,是一个控制流而不是数据流,所以应从图中删去。

图3-4 简单数据流图举例
2)加工处理
加工处理是对数据流转换进行的操作,它把流入的数据流转换为流出的数据流。每个加工处理都应取一个名字以表示它的含义,并规定用一个编号来标识该加工在层次分解中的位置。名字中必须包含一个动词,例如“计算”、“打印”等。
数据流加工转换的方式有两种:
(1)改变数据流的结构,如将数组中各数据重新排序;
(2)产生新的数据流,如对原来的数据进行汇总、统计和求平均值等。
3)文件
文件是存储数据的工具。文件名应与它的内容一致,写在开口长条内。从文件流入或流出数据流时,数据流方向是很重要的。如果是读文件,则数据流的方向应从文件流出,写文件时则相反;如果是既读又写文件,则数据流是双向的。在修改文件时,虽然必须首先读文件,但其本质是写文件,因此数据流应流向文件,而不是双向的。
例如,在图3-4(a)中,检查合理性加工时,只从库存账目文件中读出库存信息与领料单核对,所以数据流从文件流出,箭头指向加工。
4)数据源或终点
数据源和终点表示数据的外部来源和去处。它通常是系统之外的人员或组织,不受系统控制。
为了避免在数据流图上出现线条交叉,同一个源点、终点或文件均可在不同位置多次出现,这时要在源点或终点符号的右下方画小斜线,或在文件符号左边画竖线,以示重复,如图3-5所示。

图3-5 重复的源点、终点或文件
由图3-2可见,数据流图可通过基本符号直观地表示系统的数据流程、加工、存储等过程,但它不能表达每个数据和加工的具体、详细的含义,这些信息需要在“数据字典”和“加工说明”中表达。
2.数据流图的画法
1)画法原则
一般遵循“由外向里”的原则,即先确定系统的边界或范围,再考虑系统的内部;先画加工的输入和输出,再画加工的内部,具体如下。
(1)识别系统的输入/输出;
(2)从输入端至输出端画数据流和加工,并同时加上文件;
(3)加工的分解“由外向里”进行分解;
(4)数据流的命名要确切,名字能反映整体;
(5)各种符号布置要合理,分布均匀,尽量避免交叉线。
2)画法步骤
对于不同的问题,数据流图可以有不同的画法,具体操作时可按下述步骤进行。
(1)识别系统的输入/输出,画出顶层图,即确定系统的边界。
在需求分析阶段,系统的功能需求等还不很明确,为了防止遗漏,不妨先将范围定得大一些。在确定系统边界后,越过边界的数据流就是系统的输入/输出,将输入/输出用加工符号连接起来,并加上输入数据来源和输出数据去向就形成了顶层图。
库存管理系统的顶层数据流图如图3-6所示。

图3-6 库存管理系统的顶层数据流图
(2)画系统内部的数据流、加工与文件,画出一级细化图。
从系统输入端到输出端(也可反之),逐步用数据流和加工连接起来,当数据流的组成或值发生变化时,就在该处画一个“加工”符号。
画数据流图时还应同时画上文件,以反映各种数据的存储处,并表明数据流是流入文件还是流出文件。
最后,再回过头来检查系统的边界,补上遗漏但有用的输入/输出数据流,删去那些没被系统使用过的数据流。
库存管理系统的一级细化图如图3-7所示。

图3-7 库存管理系统的一级细化图
(3)加工的进一步分解,画出二级细化图。
同样运用“由外向里”的方式对每个加工进行分析,如果在该加工内部还有数据流,则可将该加工分成若干个子加工,并用一些数据流把子加工连接起来,即可画出二级细化图。二级细化图可在一级细化图的基础上画出,也可单独画出该加工的二级细化图,二级细化图也称为该加工的子图。需要注意编号问题,即对上一级加工的分解,应以上一级编号为开始,加一个“.”,并依次编号。例如对1号加工的分解,编号为1.1,1.2,…。
(4)其他注意事项。
一般应先给数据流命名,再根据输入/输出数据流名的含义为加工命名。名字含义要确切,要能反映相应的整体。若碰到难以命名的情况,则很可能是分解不恰当造成的,应考虑重新分解。
从左至右画数据流图。通常左侧、右侧分别是数据源和终点,中间是一系列加工和文件。正式的数据流图应尽量避免线条交叉,必要时可用重复的数据源、终点和文件符号。此外,数据流图中各种符号布置要合理,分布应均匀。
画数据流图是一项艰巨的工作,要做好重画的思想准备,重画是为了消除隐患,有必要不断改进。
因为作为顶层加工处理的改变域是确定的,所以改变域的分解是严格地自顶向下分解的。由于目前还不存在目标系统,因此分解时开发人员还需凭经验进行,这是一项创造性的劳动。同时,在建立目标系统数据流图时,还应充分利用本章讲过的各种方法和技术,例如,分解时尽量减少各加工之间的数据流,数据流图中各个成分的命名要恰当,父图与子图间要注意平衡,等等。
在画出分层数据流图,并为数据流图中各个成分编写词典条目或加工说明后,就获得了目标系统的初步逻辑模型。
3.绘制数据流图时应注意的问题
下面从4个方面讨论画分层数据流图时应注意的问题。
1)合理编号
分层数据流图的顶层称为0层,它是第1层的父图,而第1层既是0层图的子图,又是第2层图的父图,依此类推。由于父图中有的加工可能就是功能单元,不能再分解,因此父图拥有的子图数不大于父图中的加工个数。
为了便于管理,应按下列规则为数据流图的加工编号:
(1)子图中的编号由父图号和子加工的编号组成;
(2)子图的父图号就是父图中相应加工的编号。
为简单起见,约定第1层图的父图号为0,编号只写加工编号1,2,3,…。下面各层由父图号1,1.1等加上子加工的编号1,2,3组成。按上述规则,图的编号既能反映出它所属的层次及它的父图编号的信息,还能反映子加工的处理信息。例如,1表示第1层图的1号加工处理,1.1,1.2,1.3,…表示父图为1号加工的子加工,1.3.1,1.3.2,1.3.3,…表示父图号为1.3加工的子加工。
为了方便起见,对数据流图中的每个加工,可以只标出局部号,但在加工说明中,必须使用完整的编号。例如,图3-8可表示第1层图的1号加工的子图,其编号可以简化成图中的形式。

图3-8 简化子图编号示例
2)注意子图与父图的平衡
子图与父图的数据流必须平衡,这是分层数据流的重要性质。这里的平衡指的是子图的输入/输出数据流必须与父图中对应加工的输入/输出数据流相同。
3)局部文件
图3-9中的父图和子图是平衡的,但子图中的文件W并没在父图中出现。这是由于对文件W的读/写完全局限于加工3.3之内,在父图中各个加工之间的界面上不出现,该文件是子图的局部文件或临时文件。
应当指出的是,如果一个临时文件在某层数据流图中的某些加工之间出现,则在该层数据流图中就必须画出这个文件。一旦文件被单独画出,还需画出这个文件同其他成分之间的联系。

图3-9 数据流图中的局部文件
4)分解的程度
对于规模较大的系统的分层数据流图,如果一次性把加工直接分解成基本加工单元,一张图上画出过多的加工将使人难以理解,也增加了分解的复杂度。然而,每次分解产生的子加工太少,会使分解层次过多而增加作图的工作量,阅读也不方便。经验表明,一个加工每次的分解量最多不要超过7个为宜。同时,分解时应遵循以下原则。
(1)分解应自然,概念上要合理、清晰。
(2)上层可分解得快些(分解成的子加工个数多些),这是因为上层是综合性描述,对可读性的影响小,而下层应分解得慢些。
(3)在不影响可读性的前提下,应适当地多分解成几部分,以减少分解层数。
一般说来,当加工可用一页纸明确地表述,或加工只有单一输入/输出数据流(出错处理不包括在内)时,就应停止对该加工的分解。另外,对数据流图中不再作分解的加工(功能单元),必须作出详细的加工说明,并且每个加工说明的编号必须与功能单元的编号一致。
4.数据流图的修改
前面介绍了画数据流图的基本方法,对于一个大型系统来说,由于在软件设计初期人们对问题理解的深度不够,在数据流图上也不可避免地会存在某些缺陷或错误,因此还需要进行修改,才能得到完善的数据流图。这里介绍如何从正确性和可读性两方面对数据流图进行改进。
1)正确性
数据流图的正确性,可以从以下几个方面来检查。
(1)文件使用。在数据流图中文件与加工之间数据流的方向应按规定认真标注,这样也有利于对文件使用正确性的检查。例如,在图3-10中,因为文件1和文件2是子图的局部文件,所以在子图中应画出对文件的全部引用。但子图中的文件,好像一个“渗井”,数据只流进不流出,显然是一个错误。
(2)父图平衡。造成子图与父图不平衡的一个常见原因是在增加或删除一个加工时,忽视了对相应父图或子图的修改,在检查数据流图时应注意这一点。
(3)加工与数据流的命名。加工和数据流的名字必须体现被命名对象的全部内容,而不是一部分内容。对于加工的名字,应检查它的含义与被加工的输入/输出数据流是否匹配。一个加工的输出数据流仅由它的输入数据流确定,这个规则绝对不能违背。数据不守恒的错误有两种:一是漏掉某些输入数据流;二是某些输入数据流在加工内部没有被使用。虽然有时后者并不一定是一个错误,但也要认真考虑,对于确实无用的数据就应该删去,以简化加工之间的联系。

图3-10 局部文件使用错误
在检查数据流图时,应注意消除控制流。
2)可读性
数据流图的可读性,可以从以下几个方面来提高。
(1)简化加工之间的联系。各加工之间的数据流越少,各加工的独立性就越高。因此应当尽量减少加工之间数据流的数目,必要时可采用后面介绍的步骤对数据流图重新分解。
(2)分解应当均匀。在同一张数据流图上,应避免出现某些加工已是功能单元,而另一些加工却还应继续分解为好几层的情况。否则,应考虑重新分解。
(3)命名应当恰当。理想的加工名由一个具体的动词和一个具体的宾语(名词)组成。数据流和文件的名字也应具体、明确。
3)数据流图重新分解的步骤
有时需要对部分或全部数据流图进行重新分解,可按以下步骤进行:
(1)把需要重新分解的所有子图连成一张图;
(2)根据各部分之间联系最少的原则,把图划分成几部分;
(3)重建父图,即把第(2)步所得的每一部分画成一个圆圈,各部分之间的联系就是加工之间的界面;
(4)重建各张子图,只需把第(2)步所得的图,按各自的边界剪开即可;
(5)为所有加工重新命名、编号。
例如,图3-11(a)中加工2与其他加工的联系太复杂以致很难独立理解,所以其结构不太合理。将它们的父图加工分成两个更为合适,如图3-11(b)所示。
根据上述规则检查库存管理系统,可以发现如下问题。
(1)一层细化图缺少了一个输入数据流。应在供应商和处理P1之间加一个数据流“发货单”,数据从供应商流入处理P1。
(2)文件使用错误。供应商信息、车间信息和商品信息3个文件在一层细化图中只流进不流出。应在顶层数据流图中添加“供应商信息”、“车间信息”和“商品信息”3个数据存储,系统读取3个文件,因此数据从文件流入“库存管理系统”并进行处理。

图3-11 结构不合理的数据流图及其修改