第3章结构化设计

在软件需求分析阶段,开发人员已经搞清楚了软件“做什么”的问题,并把用户需求通过规格说明书描述了出来,这也是目标系统的逻辑模型。在软件系统设计阶段,开发人员要把软件“做什么”的逻辑模型变换为“怎么做”的物理模型,即着手实现软件的需求,并将设计的结果反映在“设计规格说明书”文档中。
结构化设计属于软件工程的系统设计阶段,通常划分成两个步骤: 结构化总体设计和结构化详细设计。
软件设计的一条基本原理是程序模块化,即一个大程序应该由许多规模适中的模块按合理的层次结构组织而成。总体设计阶段的主要任务是设计软件的结构,即确定程序的组成模块及模块间的关系。通常用层次图、结构图、HIPO图等描绘软件的结构。
详细设计阶段的主要任务是设计出程序的详细规格说明,其作用类似于其他工程领域中工程师经常使用的工程蓝图,详细规格说明应该包含必要的细节,程序员可以根据详细规格说明写出实际的程序代码。通常用流程图、表格、PDL语言等描述详细设计的结果。
本章首先介绍结构化总体设计阶段的体系结构设计、接口设计和数据设计,然后介绍结构化详细设计,同时给出与每一步骤相对应的“高校图书借阅系统”的设计实例,最后用“航空公司机票预订系统”项目案例完整地实现结构化设计的全过程。


课程思政


 3.1结构化设计概述
结构化设计方法是一种面向数据流的传统软件设计方法,以数据流为中心构建软件分析模型和软件设计模型。它以结构化需求分析的结果作为设计依据,设计出满足用户需求的软件模型。总体设计阶段的软件设计模型包括软件体系结构模型、软件接口模型和软件数据模型。


视频讲解


3.1.1结构化设计的任务
软件设计的主要任务是解决如何做的问题,要在需求分析的基础上,建立各种设计模型,并通过对设计模型的分析和评估,来确定这些模型是否能够满足需求。软件设计是将用户需求准确地转化成为最终的软件产品的唯一途径,在需求到构造之间起到了桥梁作用。
在软件设计阶段往往存在多种设计方案,通常需要在多种设计方案之中进行决策和折中,并使用选定的方案进行后续的开发活动。软件设计阶段在整个软件生存期起着非常重要的作用,其方案的选择影响着软件的开发质量、维护的难易程度、甚至最终软件实现的成败。
结构化总体设计也称为软件的概要设计,该阶段的任务包括软件的体系结构设计、接口设计和数据模型设计。
(1) 体系结构设计: 体系结构设计也称为模块设计,定义软件模块及模块之间的关系。其设计依据为结构化需求分析阶段的数据流图。
(2) 接口设计: 接口设计包括外部接口设计和内部接口设计。外部接口描述用户界面、软件和硬件设备及其他软件系统的接口,其设计依据为结构化需求分析阶段的顶层数据流图; 内部接口为软件各模块之间的接口,其设计依据为结构化需求分析阶段的数据流图。

(3) 数据模型设计: 主要是根据结构化需求分析阶段所建立的ER图和数据字典来确定软件涉及的文件系统的结构及数据库的表结构。
结构化详细设计阶段的任务为软件的过程设计。过程设计的主要工作是确定软件各个模块内的算法及内部数据结构,并选定某种过程的表达形式来描述各种算法,其设计依据为结构化需求分析阶段的数据流图、状态转换图及数据字典。






视频讲解


3.1.2结构化设计的原则
经过几十年的发展和经验总结,人们已经归纳出以下5条软件结构化设计的原则。
1) 模块化
人们解决大型复杂问题时通常采用分解的方式,即将大型复杂的问题分解为许多容易解决的小问题,原来的问题也就容易解决了,软件设计的模块化方法就是采用分解的方式进行软件设计。
2) 高内聚、低耦合
耦合是程序结构中各个模块之间相互关联的度量,它取决于各个模块之间接口的复杂程度、调用模块的方式和通过接口的信息类型。低耦合就是各模块间联系要尽量简单,这样在详细设计、编码、测试和维护某模块时,就不需要对其他模块有很多的了解,从而简化了开发人员的工作。
内聚是一个模块内部各个元素彼此结合的紧密程度的度量。理想情况下,一个内聚性高的模块应当只做一件事,即一个模块各部分都是完成某一具体功能必不可少的部分,这样的模块是内聚性最高的,叫作功能内聚。如果一个模块完成多个功能,但各个功能都在同一数据结构上操作,基于同一数据结构达到了信息隐蔽,这种模块内聚性较高,叫作信息内聚。如果达不到这两种高内聚,内聚性也应该尽可能地高,否则软件设计以后的各个阶段的工作效率会大大降低,甚至可能出现错误。
3) 抽象
抽象是指抽取事物最基本的特性和行为,忽略非基本的细节。采用分层抽象的办法可以控制软件开发过程的复杂性,设计开始时应尽量提高软件的抽象层次,按抽象级别从高到低进行软件设计,有利于软件的理解和开发过程的管理。
4) 信息隐藏
信息隐藏是采用封装技术将程序模块的实现过程、数据等细节隐藏起来,不需要这些信息的其他模块不能访问; 而模块之间可以通过接口说明给出的信息,包括操作、数据类型等来联系。
5) 一致性
软件设计中各个模块应使用一致的术语和符号,模块之间的接口应保持一致,与硬件的接口应保持一致,系统规格说明和系统应用行为应保持一致。这就要求软件设计人员使用良好的设计工具、采用良好的设计方法及具有良好的编码风格。


视频讲解


3.1.3模块独立性
模块独立是指每个模块只完成一个相对独立的特定子功能,并且和其他模块之间的关系很简单,和其他模块之间没有过多的相互作用。
模块独立的软件易于开发,因为能够分割功能而且接口可以简化。模块独立的软件易于测试和维护,因为相对来说,修改设计和程序需要的工作量比较小,错误传播范围小,需要扩充功能时也很容易“插入”模块。
模块独立性有两个定性标准度量为内聚和耦合,提倡模块遵循高内聚、低耦合的原则,保证模块具有较好的独立性。
1. 耦合
耦合性是程序结构中各个模块之间相互关联的度量,它取决于各个模块接口的复杂程度、模块的调用方式及通过接口的信息。
一般将耦合方式分为7种类型,以下越靠前的耦合方式模块间耦合性越低、独立性越高。
1) 非直接耦合
两个模块之间没有直接关系,它们之间的联系完全是通过主模块的控制和调用来实现的。
2) 数据耦合
一个模块访问另一个模块时,彼此之间是通过简单数据参数(不是控制参数、公共数据结构或外部变量)来交换输入、输出信息的。
3) 标记耦合
一组模块通过参数表传递记录信息,称为标记耦合。这个记录是某一数据结构的子结构,而不是简单变量,其实传递的是这个数据结构的地址。
4) 控制耦合
如果一个模块通过传送开关、标志、名字等控制参数明显地控制选择另一模块的功能,称为控制耦合。
5) 外部耦合
一组模块都访问同一全局简单变量而不是同一全局数据结构,而且不是通过参数表传递该全局变量的信息,则称它为外部耦合。
6) 公共耦合
若一组模块都访问同一个公共数据环境,则它们之间的耦合就称为公共耦合。
7) 内容耦合
如果发生下列情形,模块之间就是内容耦合: 一个模块直接访问另一个模块的内部数据; 一个模块不通过正常入口转到另一模块内部; 两个模块有一部分程序代码重叠(只可能出现在汇编语言中); 一个模块有多个入口。
2. 内聚
模块的内聚是指模块内部各元素彼此结合的紧密程度。一个内聚程度高的模块在理想状况下应只做一件事。
一般将内聚的方式也分为7种类型,以下越靠前的内聚方式模块的内聚性越高、独立性越高。
1) 功能内聚
一个模块中各部分都是完成某一具体功能必不可少的组成部分,或者说该模块中所有部分都是为了完成一项具体功能而协同工作,模块各部分之间是紧密联系、不可分割的,则称该模块为功能内聚模块。
2) 信息内聚
一个模块完成多个功能,各个功能都在同一数据结构上操作,每一项功能有一个唯一的入口点,则称该模块为信息内聚模块。
3) 通信内聚
如果一个模块内各功能部分都使用了相同的输入数据或产生了相同的输出数据,则称它为通信内聚模块。
4) 过程内聚
使用流程图作为工具设计程序时,如果流程图太大,可以把流程图中的某一部分划出组成模块,就得到过程内聚模块。例如,把流程图中的循环部分、判定部分、计算部分分成三个模块,这三个模块都是过程内聚模块。
5) 时间内聚
时间内聚又称为经典内聚,大多为多功能模块,模块的各个功能的执行与时间有关,通常要求所有功能必须在同一时间段内执行。例如,初始化模块和终止模块就是时间内聚模块。
6) 逻辑内聚
这种模块把几种相关的功能组合在一起,每次被调用时,由传送给模块的判定参数来确定该模块应执行哪一种功能。
7) 巧合内聚
当几个模块内正好有一段代码相同时,将它们抽取出来形成单独的模块,即巧合内聚模块。这种模块没有独立功能,各部分之间没有联系或联系很松散。
3.1.4结构化设计的步骤
结构化设计的工作一般按以下步骤进行: 
1) 设计软件的体系结构图
按需求分析阶段的数据流图确定系统的流程类型是事务型还是变换型,对于事务型问题要确定事务中心及接收和发送分支,将其映射成事务结构图; 而对于变换型问题要确定变换中心及传入和传出分支,将其映射成变换结构图。然后对结构图进行综合评价和改进,最后按照有关规范编写结构设计说明书并进行复审。
2) 设计软件的接口
按需求分析阶段的顶层数据流图和用户描述设计用户界面、软件与硬件的接口及软件与其他软件系统的接口,然后按详细数据流图为软件各模块之间设计接口,最后按照有关规范编写接口设计说明书并进行复审。
3) 设计软件的数据模型
参考需求分析阶段的数据字典将ER图转换为数据库中的数据模型(目前常用的为关系数据模型)或设计文件系统,然后设计数据库中的关系数据模型的外模式(用户视图),最后按照有关规范编写数据模型设计说明书并进行复审。
4) 软件的详细设计
软件的详细设计也称为过程设计,按需求分析阶段的数据流图、状态转换图及数据字典设计软件每个模块的内部细节即每个模块功能的实现算法,一般采用程序流程图、盒图、PAD图、伪代码等工具设计算法。另外,对数据结构、数据操作和输入/输出格式的细节进行设计,最后编写设计说明书并进行复审。
5) 编写结构化设计说明书
按照国家标准《GB/T 8567—2006计算机软件文档编制规范》,涉及软件设计规格说明的文档有“软件设计说明”(SDD)、“数据库设计说明”(DBDD)和“接口设计说明”(IDD)。根据软件的规模和复杂性,也可以把软件设计说明和数据库设计说明合并成一个文档。

 3.2体系结构设计
一般通过功能划分过程来完成软件结构设计。功能划分过程从需求分析确立的目标系统的模型出发,对整个问题进行分割,使其每一部分用一个或几个软件模块加以解决,整个问题就解决了。


视频讲解


3.2.1体系结构的启发式设计原则
一个软件系统通常由很多模块组成,结构化程序设计中的函数和子程序都可称为模块,它是程序语句按逻辑关系建立起来的组合体。在体系结构图中,模块用矩形框表示,并用模块的名字标记它。
体系结构的设计应遵循以下启发式设计原则: 
1) 提高模块独立性
模块的独立性是指软件系统中每个模块只涉及软件要求的具体的子功能,和软件系统中其他的模块的接口是简单的。例如,若一个模块只具有单一的功能且与其他模块没有太多的联系,则称此模块具有模块独立性。一般采用两个准则度量模块独立性,即模块间的耦合和模块的内聚。
设计出软件的初步结构以后,应该审查分析这个结构,通过模块分解或合并,力求降低耦合并提高内聚。例如,多个模块共有的一个子功能可以独立成一个模块,由这些模块调用; 有时可以通过分解或合并模块以减少控制信息的传递及对全局数据的引用,并且降低接口的复杂程度。
2) 模块规模适中
尽管模块分解可以简化要解决的问题,但模块分解并不是越小越好。当模块数目增加时,每个模块的规模将减小,开发单个模块的成本确实减少了; 但是,随着模块数目增加,模块之间关系的复杂程度也会增加,设计模块间接口所需要的工作量也将增加; 所以模块规模的大小应设计适中。
模块的大小可以用模块中所含语句的数量的多少来衡量,通常规定其语句行数为50~100行,最多不超过500行。
过大的模块往往是由于分解不充分引入的,但是进一步分解必须符合问题结构,一般来说,分解后不应该降低模块独立性。对于过小的模块,特别是当只有一个模块调用它时,通常可以把它合并到上级模块中去。
3) 结构图的深度和宽度适中

结构图的设计一般采用树状结构,如图31所示。


图31树状结构图


结构图中模块的层次数称为结构图的深度,它表示了控制的层数,从某种意义上反映了程序的规模和程序结构的复杂程度。对于中等规模的程序,其深度为10左右,如果深度过大,则应考虑结构中的某些模块是否过分简单了。
结构图中同一层次模块的最大个数称为结构图的宽度,它表示了控制的总分布。一般来说,宽度越大系统越复杂,而对宽度影响最大的因素是模块的扇出。
4) 结构图中扇入和扇出适当
一个模块直接控制的下层模块的个数称为该模块的扇出数。好的系统的平均扇出数通常是3~4,最多是5~9,扇出过大时可以适当增加中间层次的控制模块,扇出过小时可以把下级模块进一步分解成若干个子功能模块或合并到上级模块中去,当然这种分解或合并不能影响模块的独立性。
多个模块可以有同一个下属模块,该下属模块的上级模块的个数称为扇入数。一个模块的扇入数越大,则共享该模块的上级模块数目越多,这属于好的情况。但如果一个模块的扇入数太大,比如超过8个,而它又不是公用模块,说明该模块可能具有多个功能,应当对它进一步分析并将其功能分解。
5) 模块的作用域应在控制域之内
模块的控制域是指它本身及其所有的从属模块的集合,模块的作用域是指受其判定影响的所有模块的集合。如果一个判定的作用域包含在这个判定所在模块的控制域之内,则这种结构是好的设计。
例如,图31中模块A的控制域为A、D、E、F、G、H、I和J模块的集合,则A的作用域不能超出该控制域的范围。模块A做出一个判定之后,若需要模块 K工作,则必须把信号回送给模块M,再由M把信号传送给模块B,这就表明A的作用域超出了其控制域范围,这样会增加模块间的耦合性,降低可靠性和可维护性。
6) 模块功能的完善化
一个完整的功能模块,不仅能够完成指定的功能,而且还应当能够告诉使用者完成任务的状态及不能完成的原因。一个完整的模块应当有以下几部分。
(1) 执行规定的功能的部分。
(2) 出错处理的部分。当模块不能完成规定的功能时,必须回送出错标志,向它的调用者报告出现这种例外情况的原因。
(3) 如果需要返回一系列数据给它的调用者,在完成数据加工或结束时,应当给它的调用者返回一个“结束标志”。
7) 消除重复功能,改善软件结构
对得到的结构图进行审查,如果发现相似的模块,可以加以改进。
如果在结构上完全相似,可能只是在数据类型上不一致,可以采取完全合并的方法。如果只是局部相似,不可以把两者合并为一,因为这样在合并后的模块内部必须设置许多查询开关,可以把相似部分独立出来,重新定义成一个下层模块。


视频讲解


3.2.2面向数据流的设计方法
基于数据流的设计方法也称为过程驱动的设计方法,这种方法与软件需求分析阶段的结构化分析方法相衔接,可以很方便地将用数据流图表示的信息转换成程序结构的设计描述,这种方法还能和编码阶段的“结构化程序设计方法”相适应,成为常用的结构化设计方法。面向数据流方法的设计过程如图32所示。



图32面向数据流方法的设计过程


此方法首先对需求分析阶段得到的数据流图进行复查,必要时进行修改和精化; 接着仔细分析系统数据流图,确定数据流图的类型,并按照相应的设计步骤将数据流图转化为软件结构; 最后根据体系结构的启发式设计原则对得到的软件结构进行精化。
1. 变换型数据流
通常,一个系统中的所有数据流都可以认为是变换型数据流,但是,当遇到有明显事务特性的数据流时,建议采用事务型映射方法进行设计。

变换型数据处理问题的工作过程大致分为3步,即取得数据、变换数据和给出数据,如图33所示。


图33变换型数据流


首先从外部取得数据C进入子系统,接着数据C通过加工处理变换成数据D,最后数据D离开子系统被输出给外部。其中,变换数据为子系统的核心。如果数据流具有这些特征,就可以称为变换型数据流。
变换型数据流映射成的变换结构图如图34所示。



图34变换型结构图


在图34中,主模块首先获得控制,然后沿着结构左分支一直到达底层取得数据A,在变换模块“A变换成B”中对A进行加工变成数据B,B向上送回,在变换模块“B变换成C”中对B进行加工变成数据C,C再向上送回,在变换模块“C变换成D”中对C进行加工变成数据D,D再向上送回主模块,主模块将数据D传出,在变换模块“D变换成E”中对D再加工成最终结果E,最后输出E。

变换型数据流向变换型结构的映射过程一般包括以下步骤。
1) 整合数据流图,划分边界

首先将最后一层数据流图整合成一个整体; 然后从数据流图的物理输入端出发,沿着数据流方向逐步向系统内部移动,直到遇到的数据流不再被看作系统的输入为止,其前一个数据流即为系统的逻辑输入; 同样地,从数据流图的物理输出端出发,沿着数据流的反方向逐步向系统内部移动,直到遇到的数据流不再被看作系统的输出为止,其后的数据流即为系统的逻辑输出; 最后,输入数据流和输出数据流之间的部分就是系统的变换中心。如图35所示即为划分边界后的数据流图。


图35划分边界后的数据流图


2) 进行一级分解,设计系统的上层模块
首先设计一个主模块,并用程序名为其命名,然后将它画在与中心变换相对应的位置上。第一层为每个逻辑输入设计一个输入模块,它的功能是为主模块提供数据; 为每个逻辑输出设计一个输出模块,它的功能是将主模块提供的数据输出; 为变换中心设计一个变换模块,它的功能是将逻辑输入转换成逻辑输出。图34的上半部分即为该系统的上层模块,如图36所示。


图36上层模块设计图


3) 进行二级分解,设计系统的中、下层模块
一个输入模块要有一个数据来源,并要为其上级模块提供数据,所以一个输入模块必须包含接收数据和转换数据的两个下属模块,但物理输入端为原子模块,没有下属模块。比如,图34中输入模块“取得C”的下属模块包括输入模块“取得B”和变换模块“B变换成C”; 输入模块“取得B”的下属模块包括输入模块“取得A”和变换模块“A变换成B”; 输入模块“取得A”为原子模块,即物理输入端。
一个输出模块要从它的上级模块接收数据并输出,所以一个输出模块应包含将接收数据转换成输出形式和进行数据输出的两个下属模块,但物理输出端为原子模块,没有下属模块。比如,图34中输出模块“给出D”的下属模块包括变换模块“D变换成E”和输出模块“给出E”; 输出模块“给出E”为原子模块,即物理输出端。
一个变换模块的下层分解没有通用的方法,一般就是按照数据流图中上、下层功能的分解来进行。另外,设计结构图时可以省略模块间的数据传递。


图37事务型数据流



视频讲解


2. 事务型数据流

事务型数据流的特征通常是接受一项事务,根据事务处理的特点和性质,选择分派一个适当的处理单元,然后给出结果。完成选择分派任务的部分称为事务处理中心或分派部件。事务型数据流如图37所示,其中,事务处理中心为T,它做出选择,分派处理单元D1、D2、D3或D4进行处理加工,各处理单元是并列的,分别完成不同的处理工作,最后得到一个需要的处理结果。

事务型数据流映射成的事务结构图如图38所示。


图38事务型结构图


在图38中,事务中心为顶层模块,它根据接受的事务类型选择某一事务模块执行。每个事务模块可能要调用若干操作模块,而每个操作模块可能又调用若干细节模块,某个操作模块和细节模块也可能被几个上层模块共享。

事务型结构图可以有多种形式,如对简单的系统进行设计时,分析作业和事务调度可以不单独给出,而是归入事务中心模块,也可能没有下面的操作层; 复杂的系统进行设计时则可能有多层操作层。
事务型数据流向事务型结构的映射过程一般包括以下步骤。
1) 整合数据流图,划分边界,明确其中的输入及输出
首先,将最后一层数据流图整合成一个整体; 然后,采用与变换型相同的方法确定事务输入; 接着确定事务中心,它位于多条加工路径的起点,如图37中的T,从事务中心经过的数据流分解为多个并列的数据流,而事务输入即为向事务中心提供数据的路径; 最后确定输出,与变换型数据流的输出确定方法相同。


图39事务型结构图上层

2) 建立上层模块
首先设计上层模块,事务型数据流图对应的软件结构上层即为“事务中心”。事务中心的下层一般必须有两个模块,分别为事务输入模块、事务调度模块,事务输入模块负责接收系统所需的数据,事务调度模块负责控制所有下层的并列事务模块。如果事务的处理结果需要输出,则还要包括第三个模块,即输出模块,否则可以没有此模块。事务型结构图的上层模块设计如图39所示,其中省略了模块间的数据传递。


3) 分解、细化,得到下层模块
首先设计调度模块下层的事务模块,这些模块应该是数据流图中紧邻事务中心后的各个并列的加工,每一个加工可以定义成一个事务模块,几个联系密切的事务或类似的事务也可以组成一个事务模块,但要保证模块的高内聚性。如果事务模块很少,也可以不设计调度模块,而是将调度功能合并到上层事务中心内。事务模块设计如图38中“事务1”、“事务2”、“事务3”和“事务4”所示。然后设计事务模块下层的操作模块,数据流图中作为事务模块的各个加工,在下层数据流图中分解出来的各子加工即为其结构图中的下层操作模块,不同事务模块下层相似的操作模块可构造成公用模块供多个事务共享。操作模块设计如
图38中“操作1”~“操作6”所示,其中“操作5”为“事务3”和“事务4”共享的操作模块。最后设计各操作模块的若干个操作细节,即细节模块,当然也可能有很多公用的细节模块。细节模块设计如图38中“细节1”~“细节7”所示,其中有多个操作模块共享的公用细节模块。大型系统可能有多层操作模块和细节模块,小型系统也可能没有操作模块和细节模块,所以操作模块和细节模块的层数与系统规模有关。


视频讲解


3. 混合型数据流
在实际应用中,很多系统的数据流图往往是事务型和变换型的混合形式。混合型结构图的设计一般以变换型设计为主,首先划分出软件系统的输入、变换中心和输出,即设计顶层主模块和第一层模块; 然后根据数据流图各部分的结构特点,利用事务分析或变换分析设计各部分下层模块,得到初步体系结构图; 最后依照体系结构的启发式设计原则对结构图进行精化和调整,得到最终体系结构图。
【例31】将图28的某医院患者监护系统数据流图向软件体系结构映射。
由于此系统主要包含事务型数据流,也含有变换型数据流部分,所以我们采用的是混合型结构进行设计。
1) 划分边界
将系统数据流图划分出软件系统的输入、变换中心和输出三部分,如图310所示。


图310数据流图划分边界


2) 设计系统的体系结构图
用A1表示医生输入的患者安全范围,T1表示设置患者安全范围(向数据存储文件写入),B1表示传送入计算机系统的病人的生理信号,B2表示接收到病人的生理信号后的计算机内表示,C表示取得的时钟周期,B3表示定时取样的病人生理信号,T2表示更新患者日志(向数据存储文件写入),操作1表示从数据存储文件读取患者安全范围,T3表示分析病人生理信号,A2表示护士输入的要求报告,操作2表示从数据存储文件读取患者日志信息,T4表示打印患者的病情报告,D表示超出安全范围的病人信息,E表示向护士发出的超出安全范围的病人的警告信息,其中T1、T2、T3、T4都是事务。患者监护系统的体系结构图如图311所示。


图311患者监护系统的体系结构图




视频讲解


3.2.3事务型体系结构设计实例
以高校图书借阅系统为例设计其体系结构图。首先将第2章图书借阅系统的二层数据流图整合为一个整体,然后分析其属于事务型还是变换型,最后根据上面的方法和步骤设计其体系结构图。
由于第2章二层数据流图整合后篇幅较大,可根据内容全面的一层数据流图和功能细分的二层数据流图综合分析,可以看出此系统包含信息维护、借书、续借、还书及信息查询的事务处理,所以具有事务型特征。

同样地,综合一层和二层数据流图来设计上层结构图,划分出输入、输出和中间部分的边界,其中借书的二层数据流图边界划分如图312所示,其他模块的划分方法相同,不一一给出。
(1) 图书借阅系统的上层结构图设计如图313所示。


图312借书的二层数据流图的边界划分



图313图书借阅系统的上层结构图



(2) “输入数据”模块的分解如图314所示。


图314输入模块的分解



(3) “输出数据”模块的分解如图315所示。


图315输出模块的分解


(4) “调度”模块的下层事务模块设计如图316所示,其中的图书信息维护和读者信息维护为软件后台管理员入口实现的功能(上一章已提到)。



图316调度模块的下层事务模块




(5) 设计“事务”层的下层“操作”模块及“细节”模块,如图317~图323所示。


图317读者信息维护模块分解




图318图书信息维护模块分解





图319借书模块分解




图320续借模块分解






图321还书模块分解




图322读者的信息查询模块分解





图323管理员的信息查询模块分解


(6) 按体系结构的启发式设计原则进行结构图整合以及精化和调整,将某些内部输入信息调整到相应模块,输出信息也调整到相应模块,查询结果的输出省略,图书和读者的信息维护也省略,得到最终图书借阅系统的体系结构图如图324所示。











图324图书借阅系统的体系结构




视频讲解



 3.3接口设计
接口设计主要包括3方面: 软件与人(用户)之间的交互界面设计、软件与硬件及其他软件系统之间的接口设计、软件内部模块之间的接口设计。
3.3.1软件与人之间的交互界面设计
软件与人之间的交互界面设计,又称为用户界面(User Interface,UI)设计,是指对软件的人机交互、操作逻辑、界面美观的整体设计,也是3种接口设计中最重要的一个。好的用户界面设计不仅要让软件变得有个性、有品位,还要让软件的操作变得舒适、简单、自由,以充分体现软件的定位和特点。
1. 用户界面设计原则
1) 简洁、实用
界面的设计要简洁,功能要排列有序,要让用户便于使用、了解产品,并减少用户发生错误选择的可能性。界面要具有HELP帮助功能、快速的系统响应、低的系统成本和一定容错能力等。
2) 清楚、一致
界面在视觉效果上要便于理解和使用,所以界面的结构设计必须清晰,不同界面之间的设计风格要保持一致,设计风格也必须与产品内容保持一致,这是每一个优秀界面都应具备的特点。
3) 从用户习惯考虑
用户总是按照他们自己的方法理解和使用软件,而界面是软件与用户交互的接口,设计者一定要多与用户沟通、交流,依照用户的习惯完成设计。
4) 用户记忆负担最小化
人脑不是计算机,在设计界面时必须要考虑人类大脑处理信息的限度。人类的短期记忆有限且极不稳定,24小时内存在约25%的遗忘率。因此对用户来说,浏览信息要比记忆更容易,不应该要求用户从一个窗口中记住某些信息,然后在另一个窗口中使用。
5) 安全、可靠
安全是指用户操作时能自由地作出选择,且所有选择都是可逆的,即可以返回或重选,在用户作出危险的选择时要有系统信息的提示。可靠是指用户界面应能保证用户正确、可靠地使用系统,保证有关程序和数据的安全性。
6) 灵活性和人性化
简单来说,灵活性就是要让用户使用时具有互动多样性,包括鼠标、键盘或手柄、软键盘等,即不局限于单一的工具。界面的高效率和高用户满意度是人性化的体现,所以其设计应具备专家级、中级和初级用户等不同级别,即用户可依据自己的级别定制界面。
2. 用户界面设计内容
用户界面的设计内容主要包括输入/输出设计、操作设计和用户手册。
对于输入/输出设计和操作设计的界面设计包括界面描述和处理方式设计。界面描述包括问题描述语言、图形、菜单、表格、对话、窗口等形式; 处理方式包括批处理、交互式、磁性媒体等方式。
对于界面描述形式的选择应从性能、优点、限制等多方面进行考虑,包括以下几方面。
(1) 使用的难易程度: 对于没有经验的用户,该界面使用的难度有多大?
(2) 学习的难易程度: 学习该界面的命令和功能的难度有多大?
(3) 操作速度: 在完成一个指定操作时,该界面在操作步骤、击键和反应时间等方面效率有多高?
(4) 实现的复杂程度: 该界面提供了什么功能?能否用新的方式组合这些功能以增强界面的执行效率?
(5) 操作的控制对象: 人机交互时,是由计算机还是由人发起和控制对话?
(6) 开发的难易程度: 该界面设计是否有难度?开发工作量有多大?

3. 设计详细的交互
用户界面设计中具体的人机交互的细节设计有若干准则,包括以下内容。
(1) 一致性: 人机交互要采用一致的术语、一致的步骤和一致的活动。
(2) 操作步骤尽可能地少: 使敲击键盘或点击鼠标的次数减到最少,甚至要减少做某些选择所需的下拉菜单的距离。
(3) 不要“哑播放”: 用户等待系统完成一个动作时,要给出一些反馈信息,说明进展情况,如显示一个进度条或提示还需要几分钟等。
(4) 提供Undo功能: 对于用户的基本的操作应能提供全部或部分恢复功能。
(5) 提高学习效率: 一般用户都不习惯也没有耐心阅读用户手册,所以应为某些功能提供联机帮助,以便用户在需要时容易找到。
3.3.2软件与硬件及其他软件系统之间的接口设计
软件与硬件的接口有很多常见的实例,如银行卡管理系统软件与POS机之间的接口、手机与SIM卡信息的交互接口、地图软件与车载导航设备之间的接口等; 软件与其他软件系统之间的接口实例也有很多,如许多网站或软件上与天气预报软件交互的接口、某些购物网站与银行系统或支付宝软件之间的接口等。
软件与硬件及其他软件系统之间的接口是根据数据流图中的边界来确定的,其具体实现需要软件工程师根据软件、硬件及其他相关软件的特性和规范进行详细的设计。
3.3.3模块之间的接口设计
软件与硬件及其他软件系统之间的接口属于软件的外部接口,而模块之间的接口属于软件的内部接口。模块之间的接口是根据数据流图中各加工之间的联系来确定的。
模块之间的接口主要是实现模块之间的通信、数据传递或数据交换等,因为内部模块之间的规范一致,需要考虑的主要是模块之间的通信效率问题,所以内部接口的设计相对比较简单。
3.3.4接口设计实例
对图书借阅系统进行接口设计分析如下。
(1) 图书借阅系统的用户界面设计,只要让软件的操作舒适、简单、自由且适合高校教职工和学生使用即可。
(2) 软件与硬件接口设计包括图书条形码的扫描和读者校园卡的扫描两个接口的设计,软件和其他软件系统之间的接口主要是读者信息通过学校的档案系统进行导入的接口,所以两个软件之间需要有接口的设计。
(3) 模块之间的接口设计比较简单,按数据流图中各加工之间的联系来确定即可,这里没有详细给出。
 3.4数据设计
数据是软件的处理对象,其存储方式的设计直接影响着软件的执行效率,在结构化软件设计阶段,主要考虑的是数据的存取方式和存储结构的设计。
目前数据的存储多采用数据库的方式,而数据库的数据模型多采用关系模型,即二维表结构。关系数据库管理系统(RDBMS)软件的数据库管理功能已相当成熟,而且功能强大,因此采用关系模型存储数据可以使程序设计人员的工作相对简化。但文件形式的数据存储和管理在多媒体、报表、档案、日志、配置文件及临时数据等方面还是具有一定的优势,所以数据设计一般包括文件设计和数据库设计两方面。


视频讲解


3.4.1文件设计
对于非结构化的多媒体数据、信息松散的数据、存取速度要求极高的数据等适合采用文件存储,而文件设计主要是根据软硬件设备条件和操作处理需求设计文件的类型、文件的组织方式等。
文件的类型包括mp3、mp4等多媒体文件,txt文本文件,XML文件,配置文件等。
文件的组织方式主要包括以下几种。
1) 顺序文件
顺序文件是最常用的文件组织形式,是记录按其在文件中的逻辑顺序依次进入存储介质而建立的,即顺序文件中物理记录的顺序和逻辑记录的顺序是一致的。若次序相继的两个物理记录在存储介质上的存储位置是相邻的,则称为连续文件; 若次序相继的两个物理记录在存储介质上的存储位置不一定是相邻的,而是通过指针将它们链接起来的,则称为串联文件。
顺序文件通常用于批处理应用中,处理速度很快,并且如果这类应用涉及对所有记录的处理,则顺序文件通常是最佳的。顺序文件组织是唯一可以很容易地存储在磁盘、磁带、只读光盘等设备上的文件组织形式。
顺序文件的结构比较简单,存储利用率高,而且顺序查询和顺序处理的效率也很高,但其缺点是不能直接存取某条记录的信息。
2) 随机文件
随机文件直接组织记录的存储与存储顺序无关,它与顺序组织完全不同,其中每一笔记录都存储在直接存取存储装置中的某一个特定的地址上。要读取任何一笔记录只要一个存取动作即可,不需要处理其他的记录。
要将记录存储在随机文件中,必须要为记录赋予一个地址。一般通过一个Hash函数计算每个记录的键值的Hash地址,当两个记录键值产生了相同的存储地址时,这种现象就叫作冲突。处理冲突的方法一般是将其中一个记录存储在另一个可用的存储位置内。
随机文件的优点包括: 随机查找文件中的数据速度最快; 查找任意数据所需时间几乎相同; 更新时,要改动的数据不需预先排序; 容易新增或删除。随机文件的缺点包括: 选取最佳的Hash函数比较困难; 随着文件的增大,出现冲突的机会也愈多,影响处理速度和效率; 容易产生空白区域,降低存储利用效率。
3) 索引文件
索引文件由数据文件组成,它是带索引的顺序文件,由索引表和主文件两部分构成。索引表本身非常小,它是一张指示逻辑记录和物理记录之间对应关系的表。索引表中的项称作索引项,索引项是按关键字或逻辑记录号顺序排列的。若文件本身也是按关键字顺序排列的,则称为索引顺序文件,否则,称为索引非顺序文件。
存取文件中记录的步骤为: 首先将整个索引文件都载入到内存中,然后用高效的算法(如折半查询法)查找目标关键字,最后按照检索到的目标记录的地址检索数据记录并返回给用户。
另外,还有主要用于存放程序的分区文件、能够统一处理整个内存和外存空间的虚拟存储文件及适合于候选属性查找的倒排文件等。


视频讲解


3.4.2数据库设计
根据数据库的组织,可以将数据库分为网状数据库、层次数据库、关系数据库、面向对象数据库等。
目前,关系数据库最为成熟,应用最为广泛,用户程序设计也比较简单,所以一般情况下,大多数设计者都会选择关系数据库。在关系数据库中,数据是以二维表的形式存储在预先定义好的数据库中,表的每一列表示一个属性,每一行将每一个数据项表示成一个属性值的元组。
在结构化设计方法中,很容易将结构化分析阶段建立的实体—关系模型(ER图)映射成关系数据库中的关系模型。
1. 实体的映射
一个实体可以映射为一个表。根据用户的数据操作需求,也可以分解为多个表,一般采用横切和竖切的方法进行分解。
竖切的分解方法常用于记录较少而属性很多的表,一般将经常使用的属性放在主表中,而将其他次要的属性放到另外的表中,从而提高数据查询和更新的效率。
横切的分解方法常常用于表中记录与时间相关的情况,一般在主表中只存放最近的数据记录,而将以前的数据记录转到对应的历史表中。
2. 联系的映射 
1) 两个实体间一对一联系的映射
可以在两个表中都引入对方实体的主键作为外键,进行双向导航; 
可以在任意一个表中引入对方实体的主键作为外键,进行单向导航; 
也可以将两个实体的联系单独构成一个表,此表包含两个实体的主键,加上两个实体映射成的表,总共映射成三个表; 还可以将两个实体合并成一个表。
2) 两个实体间一对多联系的映射
可以将联系中的“一”端毫无变化地映射到一张表,将联系中“多”端上的实体映射到带有外键的另一张表,外键即为“一”端实体的主键,满足关系的参照完整性; 也可以将两个实体的联系单独构成一个表,此表包含两个实体的主键,加上两个实体映射成的表,总共映射成三个表。
3) 两个实体间多对多联系的映射
为了表示多对多联系,关系模型必须将两个实体的联系单独构成一个表,即将两个实体的主键作为外键的第三个表。这样,两个数据实体之间的多对多联系就转换成了两个一对多联系。
3. 设计数据视图
视图作为一种数据库对象,为用户提供了一个可以检索数据表中数据的方式。视图是一个虚表,可以视为另一种形式的表,是从一个或多个表中使用SELECT语句导出的虚表,其中用来导出视图的表称为基本表。
视图并不是以一组数据的形式存储在数据库中,数据库中只存储视图的定义,而不存储视图对应的数据,这些数据仍存储在导出视图的基本表中,视图实际上是一个查询结果。当基本表中的数据发生变化时,视图中的数据也随之改变。
使用视图可以集中、简化和定制用户的数据库显示,用户可以通过视图来访问数据,而不必直接去访问该视图的基本表。
视图的优点包括: 
(1) 降低数据的复杂性。为用户集中数据,使分散在多个表中的数据通过视图定义在一起,用户不必输入复杂的查询语句,只需针对此视图做简单的查询即可。
(2) 保证数据的逻辑独立性。用户的数据查询只依赖于视图的定义,当构成视图的基本表结构需要修改时,只需要修改视图定义中的子查询部分,而不用改变基于视图的查询。
(3) 提高数据的安全性。对不同的用户定义不同的视图,使用户只能看到与自己有关的数据,简化了用户权限的管理,增加了数据的安全性。
总之,设计视图就是根据各用户的需求确定视图中包含的数据信息。


视频讲解


3.4.3数据设计实例
将高校图书借阅系统的ER图(图219)映射为关系数据模型。
1. 实体的映射
ER图中有6个实体,映射为6个表,表模式如下: 
图书(书号,书名,作者,单价,类别,出版社,出版日期)
单本图书(条码号,图书状态)
读者(读者号,身份证号,密码,姓名,性别,电话)
读者类别(类别号,类别名,最大借书天数,最大续借天数,最大借书数量)
存放区域(区域名,最大存放数量)
管理员(编号,姓名,密码,电话)
2. 联系的映射
图书实体和单本图书实体之间为一对多联系,可以在“多”端单本图书实体中加入“一”端图书实体的主键作为外键,形成两个表的联系,即在单本图书实体中加入书号属性。

存放区域实体和图书实体之间的为一对多联系,可以在“多”端图书实体中加入“一”端存放区域实体的主键作为外键,形成两个表的联系,即在图书实体中加入存放区域名属性。
管理员实体和存放区域实体之间为一对多联系,可以在“多”端管理员实体中加入“一”端存放区域实体的主键作为外键,形成两个表的联系,即在管理员实体中加入管理的区域名属性。
读者类别实体和读者实体之间为一对多联系,可以在“多”端读者实体中加入“一”端读者类别实体的主键作为外键,形成两个表的联系,即在读者实体中加入类别号属性。
读者实体和单本图书实体之间为多对多联系,必须产生一个新的关系模式形成两个表的联系,该关系模式设计为: 借阅(读者号,图书条码号,借书日期,还书日期,是否归还,续借日期,罚款金额,是否交罚款)。
3. 映射汇总
实体和联系的映射汇总后生成的关系表模式包括以下7个: 
(1) 图书(书号,书名,作者,单价,类别,出版社,出版日期,存放区域)
其中,书号为主键; 存放区域为外键,与存放区域表的主键相关联。
如果图书馆的图书数量巨大,并且存在有些图书借阅非常频繁而有些图书很少有人借阅的情况,那么可以把图书表横切为两个表。
(2) 单本图书(条码号,图书状态,书号)
其中,条码号为主键; 书号为外键,与图书表的主键相关联。
与图书表相对应,单本图书也可以横切为两个表。
(3) 读者类别(类别号,类别名,最大借书天数,最大续借天数,最大借书数量)
其中,类别号为主键。
(4) 读者(读者号,身份证号,密码,姓名,性别,电话,读者类别号)
其中,读者号为主键; 读者类别号为外键,与类别表的主键相关联。
(5) 存放区域(区域名,最大存放数量)
其中,区域名为主键。
(6) 管理员(编号,姓名,密码,电话,管理的区域名)
其中,编号为主键; 管理的区域名为外键,与存放区域表的主键相关联。
(7) 借阅(读者号,图书条码号,借书日期,还书日期,是否归还,续借日期,罚款金额,是否交罚款)。
其中,读者号、图书条码号和借书日期的组合为主键; 读者号为外键,与读者表的主键相关联; 图书条码号为外键,与单本图书表的主键相关联。
根据程序性能的需求,可以按借阅情况的时间将借阅表横切为借阅历史记录表和最近借阅信息表。
4. 设计视图
根据系统功能需求,需设计两个视图: 
(1) 读者或管理员需要查询的图书相关信息: 
图书视图(条码号,图书状态,书号,书名,作者,单价,类别,出版社,出版日期,存放区域名)

(2) 读者或管理员需要查询的读者详细信息: 
读者视图(读者号,身份证号,密码,姓名,性别,电话,读者类别号,读者类别名,最大借书天数,最大续借天数,最大借书数量)

 3.5过程设计
概要设计的任务完成后,就进入详细设计阶段,即过程设计阶段。在这个阶段,要决定各个模块的实现算法,并使用过程描述工具精确地描述这些算法。


视频讲解


3.5.1过程设计的任务和原则
过程设计阶段的目标是确定应该怎样具体地实现所要求的系统,从而在软件实现阶段可以把系统设计直接翻译成某种程序设计语言编码实现,因此过程设计最重要的是尽可能地将各模块的处理过程描述得简明易懂。
过程设计的任务包括: 
1) 算法设计
用图形、表格、语言等工具将每个模块处理过程的详细算法实现描述出来。
2) 数据结构细节和数据操作的设计
对需求分析和总体设计的数据从数据类型、数据之间关系、数据的安全性和完整性及数据操作方法等方面进行详细的设计。

3) 输入/输出格式设计
对每个模块操作中基本的输入和输出数据的格式进行符合用户操作需求的设计; 对实时交互系统设计具体的交互方式、内容和格式。
4) 编写过程设计说明书
按照国家标准《GB/T 8567—2006计算机软件文档编制规范》编写过程设计说明书。
过程设计应遵循以下设计原则: 
(1) 采用结构化程序设计方法,使用顺序、选择、循环等有限的控制结构,确保结构简单。
(2) 如果只允许使用顺序、IFTHENELSE型分支和DOWHILE型循环这三种基本控制结构,则称为经典的结构化程序设计,这样的程序设计结构清晰流畅、易读易理解且容易测试; 在实际应用中为了方便,如果还允许使用DOCASE型多分支结构和DOUNTIL型循环结构,则称为扩展的结构化程序设计; 为了程序效率,如果再允许使用CONTINUE、BREAK结构,则称为修正的结构化程序设计。
(3) 每个控制结构的设计只有一个入口和一个出口,每个模块的详细设计也必须是单入口单出口,保证程序易理解且其结构与执行情况一致。
(4) 严格控制GOTO语句,仅在下列情形才可使用: 
① 用非结构化的程序设计语言去实现结构化的构造。
② 若不使用GOTO语句就会使程序功能模糊。
③ 在某种可以改善而不是损害程序可读性的情况下。例如,在查找结束时,在文件访问结束时,在出现错误情况要从循环中转出时,使用布尔变量和条件结构来实现就不如用GOTO语句来得简洁易懂。
(5) 在程序设计过程中,尽量采用自顶向下、逐步细化的原则,由粗到细,一步步展开,这样可增加程序的易读性和可维护性。此方法符合人类解决复杂问题的普遍规律,因此可以显著提高软件开发过程的成功率和生产率。

3.5.2过程设计的工具
表达过程规格说明的工具称为过程描述工具,即详细算法实现的描述工具。可以将过程描述工具分为以下3类。
(1) 图形工具: 把过程的细节用图形方式描述出来,如程序流程图、NS图、PAD图等。
(2) 语言工具: 用某种类高级语言(伪代码)来描述过程的细节,如很多数据结构教材中使用类PASCAL、类C语言、类C++语言来描述算法。
(3) 表格工具: 用一张表来表达过程的细节。这张表列出了各种可能的操作及其相应的条件,即描述了输入、处理和输出信息,如判定表、判定树等。


视频讲解


1. 图形工具
1) 程序流程图
程序流程图也称为程序框图,从20世纪40年代末到20世纪70年代中期,程序流程图一直是软件设计的主要工具。它的主要优点是对控制流程的描绘很直观,便于初学者掌握。由于程序流程图历史悠久,是软件开发者最熟悉的算法表达工具,所以尽管它有很多缺点(如表示程序流程的箭头不受任何约束,可以随意转移),但至今仍在广泛使用着。

国际标准化组织规定了标准程序流程图中的基本符号,如图325所示。


图325标准程序流程图的基本符号


此标准也已成为我国的国家标准,绝大部分符号都符合人们的使用习惯。关于这些图形符号的几点说明如下: 
(1) 程序流程图中的流线代表控制流,自上而下或自左向右地自然流动时,可以省略箭头。
(2) 循环的上下界限有一对专门的符号,上下对应。一般这对符号应在同一条竖线上,循环体夹在中间,用法如图326所示。当然,循环结构也可以用条件判断符号来实现。
(3) 注解作为程序设计中必不可少的部分,也是程序流程图中的重要组成部分。注解符内注明注解内容,用虚线连在相关的符号上或连在一组用虚线框起来的符号上,用法如图327所示。


图326循环结构的标准符号




图327注解的标准符号



(4) 除了注解中的虚线外,程序流程图中的虚线表示两个或多个符号间的选择关系,即只能选择一个符号。
(5) 外接符和内接符表示流线在其他位置续接或与外部环境的转入/转出。
用程序流程图进行程序设计的5种基本控制结构包括: 
(1) 顺序结构: 由几个连续的加工步骤依次排列构成,如图328所示。
(2) 选择结构: 由某个逻辑判断式的取值决定选择两个加工中的一个,如图329所示。
(3) 先判断(WHILE)型循环结构: 在循环控制条件成立时,重复执行特定的加工,如图330所示。


图328顺序结构




图329选择结构




图330先判断(WHILE)型循环结构



(4) 后判断(UNTIL)型循环结构: 重复执行某些特定的加工,直至控制条件成立,如图331所示。
(5) 多分支(CASE)型选择结构: 列举多种加工情况,根据控制变量的取值选择执行其一,如图332所示。



图331后判断(UNTIL)型循环结构



图332多分支(CSAE)型选择结构


2) NS图
Nassi和Shneiderman 提出了一种符合结构化程序设计原则的图形描述工具,叫作盒图(boxdiagram),也叫作NS图。
在NS图中,表示5种基本控制结构的图形如图333所示。


图333NS图表示的5种基本控制结构


图333(a)的A框中语句和B框中语句按时间先后顺序执行; 图333(b)中P表示判断条件,条件成立时执行A框中语句,条件不成立时执行B框中语句,“箭头”表示条件P不成立时执行空操作; 图333(c)和图333(d)中P为循环判断条件,S为循环体; 图333(e)中根据P值的判断确定执行A1到An框中语句哪一个分支。

NS图的特点包括: 
(1) 除CASE型结构中表示条件取值的矩形框外,图中每个矩形框都是明确定义了的一个特定控制结构的作用域。
(2) NS图不能进行随意的控制转移,需要严格遵守结构化程序设计的要求。
(3) 结构清晰,很容易确定变量的作用域,很容易表现嵌套关系,也可以表示模块的层次结构。
3) PAD图
PAD(Problem Analysis Diagram)是由日本日立公司提出的图形工具,它由程序流程图演化而来,用结构化程序设计思想表现程序逻辑结构。

PAD也设置了5种基本控制结构,并允许递归使用,如图334所示。


图334PAD图的5种基本控制结构


图334(a)的A框中语句和B框中语句按时间先后顺序执行; 图334(b)中P表示判断条件,条件成立时执行A框中语句,条件不成立时执行B框中语句,无框表示条件P不成立时执行空操作; 图334(c)和图334(d)中P为循环判断条件,条件框的右侧为双竖线,以区别一般的矩形框,S为循环体; 图334(e)中根据P值的判断确定执行A1到An框中语句哪一个分支。


PAD的优点包括: 
(1) 使用PAD符号所设计出来的程序不能进行随意的控制转移,必然是结构化程序。
(2) PAD图描绘程序结构清晰,图中竖线的总条数就是程序的层次数,所以用PAD图表现程序逻辑易读、易懂、易记。
(3) 容易将PAD图自动转换为高级语言源程序。
(4) PAD图既可以表示程序逻辑,也可描绘数据结构。
(5) PAD图的符号支持自顶向下、逐步求精方法的使用。
4) 图形工具程序设计举例
利用以上给出的3种图形工具的5种控制结构,分别给出一个程序设计的实例: 输入年份,判断是否为闰年,如果输入的年份为0,则判断结束。
(1) 程序流程图实现,如图335所示。



图335判断输入的年份是否为闰年的流程图


(2) NS图实现,如图336所示。


图336判断输入的年份是否为闰年的NS图



(3) PAD图实现,如图337所示。



图337判断输入的年份是否为闰年的PAD图




视频讲解


2. 语言工具
伪代码是一种介于自然语言和形式化语言之间的半形式化语言,是一种用于描述功能模块的算法设计和加工细节的语言,也称为程序设计语言(Program Design Language,PDL)。
伪代码的语法规则分为“外语法”和“内语法”。外语法应当符合一般程序设计语言常用语句的语法规则,PDL具有严格的关键字外部语法,用于定义控制结构和数据结构; 内语法可以用英语中一些简单的句子、短语和通用的数学符号来描述程序应执行的功能,所以表示实际操作和条件的内部语法通常是灵活自由的,以便可以适应各种工程项目的需要。

因此,一般来说,PDL是一种“混杂”语言,它使用某种自然语言的词汇,同时又使用某种结构化程序设计语言的语法。
PDL应该具有下述特点: 
(1) 结构化程序设计语言的关键字提供了结构化控制结构、数据说明和模块化的特点。为了使结构清晰和可读性好,通常在所有可能嵌套使用的控制结构的头和尾都有关键字,如if…then…else…,while…do…等。
(2) 自然语言的自由语法,它描述处理的特点。
(3) 数据说明的手段应该既包括简单的数据结构(如单变量和数组),又包括复杂的数据结构(如链表或层次的数据结构)。
(4) 模块定义和调用的技术,应该提供各种接口描述模式。
PDL作为一种设计工具有如下一些优点: 
(1) 可以作为注释直接插在源程序中间。这样做能促使维护人员在修改程序代码的同时也相应地修改PDL注释,因此,有助于保持文档和程序的一致性,提高了文档的质量。

(2) 可以使用普通的文字处理系统,很方便地完成PDL的编辑。
(3) 可以自动由PDL生成程序代码。
PDL的缺点是不如图形工具形象直观,描述复杂的条件组合与动作间的对应关系时,不如表格工具清晰简单。
用PDL语言实现判断输入年份是否为闰年的程序设计实例如下: 

while( year不等于0 )

do if (year能被4整除) then

if (year能被100整除) then

if (year能被400整除) then

输出year是闰年

else 输出year不是闰年

endif

else 输出year是闰年

endif

else 输出year不是闰年

endif

输入下一个year

endwhile

3. 表格工具
表格工具清晰简单,非常适合描述复杂的条件组合与应做的动作之间的对应关系,通常用于复杂的加工规格说明的描述。上一章已对判定表和判定树进行了详细介绍,这里就不进行介绍了。


视频讲解


4. 设计实例
以高校图书借阅系统为例进行程序流程图的设计。
这里主要设计两个复杂的模块,借书时检查此读者是否有超期未还图书和还书时检查此图书是否超期未交罚款。检查是否有超期未还图书模块的流程图如图338所示。


图338检查是否有超期未还图书模块的程序流程图


检查是否超期未交罚款模块的流程图如图339所示。


图339检查是否超期未交罚款模块的程序流程图




视频讲解


3.5.3数据结构细节和数据操作的设计
在详细设计阶段需要对数据库文件属性、数据类型、数据完整性和数据安全性进行设计,同时要对数据的操作方式和操作细节进行设计。
1. 具体设计内容
(1) 若要创建数据库,必须要确定数据库的大小及存储该数据库的文件和文件组等。创建数据库时,根据数据库中预期的最大数据量,应创建尽可能大的数据文件。
(2) 在数据库中,表是由数据按一定的顺序和格式构成的数据集合,是存放数据的基本单位。定义数据表的字段时,需设置一个数据类型,目的是指定该字段所存放的数据是整数、字符串、货币、日期时间或是其他类型的数据,以及会用多少空间来存储数据。
(3) 数据的完整性设计包括实体完整性(主键约束和唯一性约束)、参照完整性(外键约束)、域完整性(Check约束和Default约束)及用触发器实现的复杂约束。
(4) 数据的安全性包括设计数据库的保护口令、按用户需求将不同的数据访问权限授予各用户、数据加密及设计数据库的备份和还原策略等。
(5) 设计视图的具体结构,根据系统功能设计存储过程、函数和触发器,以及为加快查询设计索引键。
存储过程是一个具有独立功能的子程序,它以特定的名称存储在数据库中,可以在其中声明变量并完成各项强大的程序设计功能。存储过程的优势主要表现在模块化程序设计、加快SQL语句的执行速度、减少网络流量和增加数据库的安全性等方面。
触发器也是一种存储过程,当对某一张表进行诸如UPDATE、INSERT、DELETE这些操作时,就会自动执行触发器所定义的SQL语句。由于在触发器中可以包含复杂的处理逻辑,因此,一般用触发器来保持低级的数据的完整性。

索引是对数据库表中一个或多个列的值进行排序的结构,其主要目的是加快数据的查询速度和减少系统的响应时间。系统会自动按主键列创建索引,另外,可根据数据的查询需求选择表中合适的列作为索引键创建索引。
2. 设计实例
以高校图书借阅系统为例进行数据结构细节和数据操作的设计。
由于图书借阅系统的主要操作是对数据库中数据的维护和查询,算法设计并不是很复杂,输入/输出格式也主要通过交互界面来实现,所以这里重点给出图书借阅系统数据结构细节和数据操作的设计。
1) 数据库数据文件和日志文件设计
高校图书借阅系统的数据库根据读者数量、图书数量、每个读者的平均借阅数量来确定; 估算每年平均增长的图书、读者及借阅数量来确定数据库数据文件的最大初始大小和增长方式; 根据数据库的操作频率和平均数据操作数量确定日志文件的最大初始大小和增长方式。


2) 设计基本表的具体结构
高校图书借阅系统的数据库中一共设计了7个表,各表的表结构如表31~表37所示,其中包含了主键、外键、索引键、取值范围、默认值和是否允许为空的完整性约束。


表31图书表(T_Book)




字段
含义
数据类型
键值
取 值 范 围
允许空否
BNO
书号
char(13)
主键
数字
否
BName
书名
nvarchar(30)
索引

否
Author
作者
nvarchar(10)
索引

否
Price
单价
money


否
Category
类别
nvarchar(10)

数学、文学、计算机等
否
Publisher
出版社
nvarchar(20)


否
PublishDate
出版日期
date


否
StorageArea
存放区域名
nvarchar(15)
外键、索引

否



表32单本图书表(T_SingleBook)




字段
含义
数据类型
键值
取 值 范 围
允许空否
Barcode
条码号
char(8)
主键
数字
否
BNO
书号
char(13)
外键、索引

否
BState
图书状态

nvarchar(3)

已借出、未借出、不可借、已下架
否



表33读者类别表(T_ReaderKind)




字段
含义
数据类型
键值
取 值 范 围
允许空否
KNO
类别号
char(3)
主键
数字
否
KName
类别名
nvarchar(10)
索引
学生、教师、工人
否
MaxBorrowDays
最大借书天数
int

60、180、90
否
MaxRenewDays
最大续借天数
int

30、90、60
否
MaxBorrowNum
最大借书数量
int

5、20、10
否



表34 读者表(TReader)




字段
含义
数据类型
键值
取 值 范 围
允许空否
RNO
读者号
char(10)
主键
数字
否
RIDNO
身份证号
char(18)
唯一索引
数字、X
否
RName
姓名
nvarchar(10)


否
RSex
性别
nvarchar(1)

男、女
否
RPassword
密码
varchar(12)

6到12位字母、数字、特殊符号
否
RTelephone
电话
char(11)

数字
否
RKNO
读者类别号
char(3)
外键、索引
数字
否



表35存放区域(T SArea)




字段
含义
数据类型
键值
允 许 空 否
AName
区域名
nvarchar(15)
主键
否
MaxStorageNum
最大存放数量
char(13)

否



表36管理员表(T_Manager)




字段
含义
数据类型
键值
取 值 范 围
允 许 空 否
MNO
编号
char(10)
主键
数字
否
MName
姓名
nvarchar(10)


否
MPassword
密码
nvarchar(18)


否
MTelephone
电话
char(11)

数字
否
ManageArea
管理的区域名
char(3)
外键

否



表37借阅表(T_Borrow)




字段
含义
数据类型
键值
取 值 范 围
默认值
允许空否

RNO
读者号
char(10)

Barcode
图书条码号

char(8)
主键
外键、索引
数字

否

外键、索引
数字

否
BDateTime
借书日期
datetime
索引
当前日
期时间

否
RDateTime
还书日期
datetime

>=BDateTime
NULL
是
IsReturn
是否归还
nchar(1)

是、否
否
否
IsRenew
续借日期
datetime


NULL
是
fine
罚款金额
float


NULL
是
IsPayFine
是否交罚款
nchar(1)

是、否
否
否

3) 设计视图的具体结构
读者或管理员需要查询的图书相关信息视图设计如表38所示。
读者或管理员需要查询的读者详细信息视图设计如表39所示。



表38图书信息视图(V_Book)




字段
含义
数据源
索引
Barcode
条码号
T_SingleBook.Barcode
是
BState
图书状态

T_SingleBook.BState

BNO
书号
T_Book. BNO

BName
书名
T_Book.BName

Author
作者
T_Book.Author

Price
单价
T_Book.Price

Category
类别
T_Book.Price

Publisher
出版社
T_Book.Category

PublishDate
出版日期
T_Book.PublishDate

StorageArea
存放区域名
T_Book.StorageArea



表39读者详细信息视图(V_Reader)





字段
含义
数据源
索引
RNO
读者号
T_ Reader. RNO
是
RName
姓名
T_ Reader.RName

RIDNO
身份证号
T_ Reader.RIDNO

RSex
性别
T_ Reader.RSex

RPassword
密码
T_ Reader.RPassword

RTelephone
电话
T_ Reader.RTelephone

RKNO
读者类别号
T_ Reader.RKNO

RKName
读者类别名
T_ReaderKind.KName

MaxBorrowDays
最大借书天数
T_ReaderKind.MaxBorrowDays

MaxRenewDays
最大续借天数
T_ReaderKind.MaxRenewDays

MaxBorrowNum
最大借书数量
T_ReaderKind.MaxBorrowNum

4) 设计存储过程、函数和触发器
为了提高软件的工作效率及保护数据库的安全性和完整性,可以设计存储过程、函数和触发器。

读者借阅图书的过程可以通过执行一系列的存储过程、函数或触发器来完成。读者可以先查询自己想借的图书的存放区域,通过一个存储过程P_SelectBookArea完成。读者拿到图书后扫描校园卡,此时系统会调用一个函数F_BorrowDaysMax(Rno),计算当前读者所有续借日期是空值且未归还的图书中当前日期减去借书日期的最大值,如果此值大于该读者的最大借书天数则说明该读者有超期未还图书,那么查询并显示此读者的超期信息,提示无法再借阅。如果没有超期未还图书,则调用一个函数F_RenewDaysMax(Rno),计算当前读者所有续借日期不是空值且未归还的图书中当前日期减去续借日期的最大值,如果此值大于该读者的最大续借天数则说明该读者有超期未还图书,那么查询并显示此读者的续借超期信息,提示无法再借阅。如果还是没有超期未还图书,
则调用一个函数F_BorrowNum(Rno),计算当前读者的最大借书量和其未还图书数量之差,如果该值为0则提示无法再借阅; 否
则提示读者扫描图书条形码完成借阅,系统向借阅表插入一行信息,此插入操作可以用一个存储过程P_InsertBorrow来实现,借书日期为当前日期时间,还书日期为“空”,是否归还为“否”,续借日期为“空”,罚款金额为“空”,是否交罚款为“否”,同时可以利用一个触发器修改单本图书表中图书状态为“已借出”。

读者还书时,首先扫描图书条形码,然后系统调用一个存储过程P_CheckOutTime检查此图书是否超期未交罚款。如果其续借日期是空值,则用当前日期减去借书日期,如果该值大于此读者的最大借书天数则超期; 如果其续借日期不是空值,则用当前日期减去续借日期,如果该值大于此读者的最大续借天数则超期。如果是否交罚款为“否”,则系统提示超期未交罚款,系统会调用函数F_CompFine(RNO,Barcode)计算罚款金额,并修改借阅表中罚款金额列的值,然后出现“交罚款”按钮,读者选择“交罚款”,从校园卡中支付完成后,系统将是否交罚款属性改为“是”,则还书可以完成。如果没有超期,则根据图书条码号和查到的读者号完成还书。还书时通过一个存储过程P_UpdateBorrow来修改还书日期为系统当前日期,并将是否归还改为“是”,同时可以利用一个触发器修改单本图书表中图书状态为“未借出”。

函数F_CompFine(RNO,Barcode)用于计算某读者所借的某本超期图书的罚款金额,系统通过一个存储过程P_Update_Fine修改罚款金额列的值。如果未续借,则罚款金额等于当前日期减去(借书日期+最大借书天数)再乘以超期一天的罚款数; 如果已续借,则罚款金额等于当前日期减去(续借日期+最大续借天数)再乘以超期一天的罚款数。
读者续借图书时,因为未进行过续借(续借日期为“空”)且未超期的图书可续借一次,所以系统将可续借图书显示出来供读者选择,然后将读者所选图书的借阅表中续借日期改为当前日期。
另外,读者可以随时查询个人信息、个人借阅信息及个人罚款信息,分别通过存储过程P_SelectReader、P_SelectBorrow和P_ SelectFine来完成。
5) 数据库的安全性设计
(1) 设置用户权限。数据库管理员具有最高权限,可以操作和管理数据库中所有数据和对象。程序员要实现图书管理员和读者的数据操作功能需具有的权限如表310所示。


表310程序员权限



对 象 类 型
对 象 名 称
权限

基本表
T_Book
Select、Insert、Update、Delete

T_Reader
Select、Insert、Update、Delete
T_ Borrow
Select、Insert、Update、Delete
T_SingleBook
Select、Insert、Update、Delete
T_ReaderKind
Select、Insert、Update、Delete
T_Manager
Select、Insert、Update、Delete

视图
V_Book
Select

V_Reader
Select

存储过程
P_SelectBookArea

P_InsertBorrow
P_CheckOutTime
P_UpdateBorrow
P_Update_Fine
P_SelectReader
P_SelectBorrow
P_ SelectFine
Execute
续表



对 象 类 型
对 象 名 称
权限

函数
F_BorrowDaysMax(Rno)

F_RenewDaysMax(Rno)
F_BorrowNum(Rno)
F_CompFine(RNO,Barcode)
Select

(2) 设置数据加密。读者表(T_Reader)和管理员表(T_Manager)中的身份证号、密码是敏感信息,所以应该设置为加密保存。
(3) 设置数据库的备份和还原策略。因为高校图书借阅系统的数据库每天的数据都有一些变化,所以可以在隔天系统应用最少的时间段(一般为3点—5点)进行一次差异数据库备份,每10天进行一次完整数据库备份,只保留近3次完整备份和相应的差异备份。


视频讲解


 3.6机票预订系统的结构化设计项目实践

3.6.1机票预订系统体系结构设计

在进行航空公司机票预订系统的体系结构设计时,可以首先将第2章机票预订系统的二层数据流图整合为一个整体,然后分析其属于事务型还是变换型,最后根据3.2节的方法和步骤设计其体系结构图。
由于第2章二层数据流图整合后篇幅较大,可根据内容全面的一层数据流图和功能细分的二层数据流图综合分析,可以看出此系统包含信息维护、订票、取票、退票及信息查询的事务处理,所以具有事务型特征。
同样地,综合一层和二层数据流图来设计上层结构图,划分出输入、输出和中间部分的边界,其中订票的二层数据流图边界划分如图340所示,其他模块的划分方法相同,不一一给出。



图340订票二层数据流图的边界划分


(1) 机票预订系统的上层结构图设计如图341所示。



图341机票预订系统的上层结构图


(2) “输入数据”模块的分解如图342所示。



图342输入模块的分解



(3) “输出数据”模块的分解如图343所示。


图343输出模块的分解



(4) “调度”模块的下层事务模块设计如图344所示。其中的航班信息维护可以不作为本体系结构的设计内容,直接在软件后台管理员入口实现即可(上一章已提到)。


图344调度模块的下层事务模块


(5) 设计“事务”层的下层“操作”模块及“细节”模块,如图345~图351所示。
(6) 按体系结构的启发式设计原则进行结构图整合、精化和调整,得到最终机票预订系统的体系结构图,如图352所示。


图345航班信息维护模块分解




图346旅客信息维护模块分解







图347订票模块分解




图348取票模块分解





图349退票模块分解




图350旅客信息查询模块分解





图351操作员信息查询模块分解












图352机票预订系统的体系结构



3.6.2机票预订系统接口设计
接口设计主要包括3方面: 软件与人(用户)之间的交互界面设计、软件与硬件及其他软件系统之间的接口设计、模块之间的接口设计。
对机票预订系统接口设计分析如下。
(1) 机票预订系统的用户是世界各地、各行各业的旅客,因此需要让软件具有一定的品位,界面布局简洁,操作舒适、简单且步骤清晰。

(2) 软件与硬件接口主要是取票模块需要设计旅客身份证的扫描接口。
(3) 模块之间的接口可根据数据流图中各加工之间的联系来确定,其设计比较简单。

3.6.3机票预订系统数据设计
航空公司机票预订系统不需要其他数据文件的设计,只需要进行数据库的设计,即将ER图(图235)映射为关系数据模型并设计视图。
1. 实体的映射
ER图中有5个实体,映射为5个表,表模式如下: 
航班(航班号,起飞站,起飞时间,到达站,到达时间,登机时间,登机口)
旅客(身份证号,密码,姓名,电话)
航班票务(航班号,日期,舱位,票价,余票)
订单(订单号,折扣,订单状态,订票时间)
机票(订单号,座位,机票状态)
2. 联系的映射
航班实体和航班票务实体之间为一对多联系,可以在“多”端航班票务实体中加入“一”端航班实体的主键作为外键,形成两个表的联系。目前,航班票务实体已经有航班实体的主键“航班号”,所以不需要再改变。
航班票务实体和订单实体之间的订票联系为一对多联系,可以在“多”端订单实体中加入“一”端航班票务实体的主键作为外键,形成两个表的联系。订单表模式变为: 订单(订单号,航班号,日期,舱位,折扣,订单状态,订票时间)。
旅客实体和订单实体之间为一对多联系,可以在“多”端订单实体中加入“一”端旅客实体的主键作为外键,形成两个表的联系。订单表模式变为: 订单(订单号,身份证号,航班号,日期,舱位,折扣,订单状态,订票时间)。
机票实体和订单实体之间为一对一联系,可以在任意“一”端实体中加入另一端实体的主键作为外键,形成两个表的联系。目前两个表的主键都为订单号,同时机票实体中订单号也为外键,两个表联系直接产生。
3. 映射汇总
实体和联系的映射汇总后生成的关系表模式包括以下5个: 
(1) 航班(航班号,起飞站,起飞时间,到达站,到达时间,登机时间,登机口)
其中,航班号为主键。
(2) 旅客(身份证号,密码,姓名,电话)
其中,身份证号为主键。
(3) 航班票务(航班号,日期,舱位,票价,余票)
其中,航班号、日期和舱位的组合为主键; 航班号为外键,与航班表的主键相关联。

根据程序性能的需求,可以按日期将航班票务表横切为航班票务历史记录表和近期航班票务表。
(4) 订单(订单号,身份证号,航班号,航班日期,舱位,折扣,订单状态,订票时间)
其中,订单号为主键; 身份证号为外键,与旅客表的主键相关联; 航班号、日期和舱位的组合为外键,与航班票务表的主键相关联。
根据程序性能的需求,可以按订单时间将订单表横切为订单历史记录表和最近订单信息表。
(5) 机票(订单号,座位,机票状态)
其中,订单号为主键; 订单号也为外键,与订单表的主键相关联。

4. 设计视图
根据系统功能需求,需设计两个视图: 
(1) 旅客订票时需要查询的航班票务信息: 
航班票务视图(航班号,起飞站,起飞时间,到达站,到达时间,日期,舱位,票价,余票)
(2) 旅客需要打印的机票详细信息: 
机票详细信息视图(身份证号,姓名,航班号,日期,舱位,座位,登机时间,登机口,起飞站,起飞时间,到达站,到达时间)
3.6.4机票预订系统过程设计
机票预订系统是一种事务型软件系统,其算法比较简单,主要是要进行数据结构细节和数据操作的设计及输入/输出交互界面和格式的设计,这里重点介绍数据结构细节和数据操作的设计。
1. 算法设计
机票预订系统的所有功能模块中,只有退票时计算退款金额模块相对复杂,其流程图如图353所示。

另外,航空公司行李托运费用的计算比较复杂,包含多重嵌套的条件选择,在2.4节的加工规格说明举例中,采用判定表和判定树进行了描述。订票系统没有包括此功能,这里就不进行具体的算法设计了。
2. 数据结构细节和数据操作的设计
1) 数据库数据文件和日志文件设计
航空公司机票预订系统的数据库根据航班数量、注册用户的数量、每个用户的平均订单数量及机票出票数量来确定; 根据估算每年平均增长的航班、注册用户及订单数量来确定数据库数据文件的最大初始大小和增长方式; 根据数据库的操作频率和平均数据操作数量确定日志文件的最大初始大小和增长方式。

2) 设计基本表的具体结构

航空公司机票预订系统的数据库中一共设计了5个表,各表的表结构如表311~表315







图353计算退款金额模块的程序流程图



所示,其中包含了主键、外键、索引键、取值范围、默认值和是否允许为空的完整性约束。


表311航班表(T_Flight)




字段
含义
数据类型
键值
取 值 范 围
允  许 空 否
Flight
航班号
char(8)
主键

否
DEPA
起飞站
nvarchar(20)
索引

否
DEPATime
起飞时间
time


否
DEST
到达站
nvarchar(20)


否
DESTTime
到达时间
time


否
Boarding
登机时间
time


否
Gate
登机口
int


否





表312旅客表(T_Passenger)




字段
含义
数据类型
键值
取 值 范 围
允许空否
IDNO
身份证号
char(18)
主键
前17位为数字,18位为数字或x
否
PWD
密码
nvarchar(20)

6到20位英文字母、数字、符号组合
否
PName
姓名
nvarchar(20)
索引

否
Telephone
电话
varchar(12)


否



表313航班票务表(T_ FlightTicket)




字段名
含义
数据类型
键值
取 值 范 围
默认值
允许空否

Flight
航班号
char(8)

Fdate
日期
date
Fclass
舱位
nvarchar(3)
主键
外键


否

索引


否

经济舱、头等舱或商务舱
经济舱
否

Price
票价
float


50到20000

否
Tickets
余票
int


0到500

否



表314订单表(T_Order)





字段
含义
数据类型
键值
取 值 范 围
允许空否
OrderNO
订单号
char(20)
主键

否

IDNO
身份证号
char(18)
外键
索引
前17位为数字,18位为数字或x
否

Flight
航班号
char(8)

Fdate
航班日期
date

Fclass
舱位
nchar(3)

外键
索引

否

索引

否


经济舱、头等舱或商务舱
否

Discount
折扣
float


0.1到0.99
否
OrderState
订单状态
nchar(3)


未付款、已付款、已取消、已退款或已完成
否
OrderTime
订票时间
datetime



否



表315机票表(T_Ticket)




字段
含义
数据类型
键值
取 值 范 围
允许空否
OrderNO
订单号
char(18)
主键、外键

否
Seat
座位
char(5)


否
TicketState
机票状态
nchar(3)

未取票、已取票或已退票
否

3) 设计视图的具体结构
(1) 旅客订票时需要查询的航班票务信息视图设计如表316所示。


表316航班票务信息视图(V_FlightTicket)




字段
含义
数据源
索引

Flight
航班号
T_Flight. Flight

Fdate
日期
T_ FlightTicket. Fdate
Fclass
舱位
T_ FlightTicket. Fclass

是

DEPA
起飞站
T_Flight. DEPA

DEPATime
起飞时间
T_Flight. DEPATime

DEST
到达站
T_Flight. DESTTime

DESTTime
到达时间
T_Flight. DESTTime

Price
票价
T_ FlightTicket.Price

Tickets
余票
T_ FlightTicket.Tickets

(2) 旅客需要打印的机票含有的详细信息视图设计如表317所示。


表317机票详细信息视图(V_TicketDetails)




字段
含义
数据源
索引

IDNO
身份证号
T_ Order. IDNO

Flight
航班号
T_ Order. Flight
Fdate
日期
T_ Order. Fdate

是

PName
姓名
T_Passenger. PName

Fclass
舱位
T_ Order . Fclass

DEPA
起飞站
T_Flight. DEPA

DEPATime
起飞时间
T_Flight. DEPATime

DEST
到达站
T_Flight. DEST

DESTTime
到达时间
T_Flight. DESTTime

Boarding
登机时间
T_Flight. Boarding

Gate
登机口
T_Flight. Gate

Seat
座位
T_Ticket. Seat

4) 设计存储过程和触发器
为了提高软件的工作效率及保护数据库的安全性和完整性,可以设计存储过程和触发器。
旅客预订机票可以通过执行一系列的存储过程或触发器来完成。旅客可以通过日期、起飞站、到达站、航班号查询航班信息,这里先创建两个存储过程P_FlightTicket1和P_FlightTicket2,分别以日期、起飞站、到达站为参数查询V_FlightTicket视图,以日期、航班号为参数查询V_FlightTicket视图。旅客查询航班信息后下订单,系统生成订单即向订单表插入一行信息,此插入操作可以用一个存储过程P_InsertOrder来实现,订单状态为“未付款”。如果用户付款成功,则将此用户的订单号、安排的座位号和机票状态(未取票)生成一行机票信息,此插入操作也可以用一个存储过程P_InsertTicket来实现,生成机票的同时可以利用一个触发器修改订单状态为“已付款”,并利用一个触发器将此航班票务信息中的余票减1,通过一个存储过程P_PassengerFlightTicket查询出旅客姓名、航班号、日期、舱位和座位号作为取票通知发送到旅客的手机中; 如果用户未付款而取消订单,则不生成机票,利用一个存储过程P_UpdateOrder1将订单状态修改为“已取消”; 如果旅客在已付款但未取票的情况下选择了“取消订单”,则在有效时间范围内可以取消订单,首先利用存储过程P_UpdateOrder1将订单状态修改为“已取消”,然后等待系统完成退款,退款成功后利用一个存储过程P_UpdateOrder2修改此订单状态为“已退款”,最后利用一个存储过程P_DeleteTicket删除已生成的机票。
旅客取票时通过身份证号和机票状态(未取票)查询出机票详细信息视图(V_TicketDetails)中的用户机票并打印,此查询可用存储过程P_TicketDetails来实现。同时可以利用一个存储过程P_UpdateOrder3修改此订单状态为“已完成”,利用一个触发器修改机票状态为“已取票”。
旅客退票时通过身份证号和机票状态(未取票)利用一个存储过程P_SelectTicket查询出机票表(T_Ticket)中的用户机票信息,系统首先调用一个存储过程P_RefundTicket审核航班起飞时间和机票折扣,确定是否可以退票。如果可以退票,则调用一个存储过程P_ComputeRefund,根据航班起飞时间和机票折扣计算退款金额,联系第三方处理退款并提示预期到账时间,然后利用一个存储过程P_Update Ticket修改机票状态为“已退票”,利用存储过程P_UpdateOrder2修改此订单状态为“已退款”,最后向旅客发送退票通知。
如果旅客已取票后希望退票,则需要在期限范围内到航空公司由操作员完成退票,除机票状态为已取票,操作过程与旅客退票时的操作相同。
另外,旅客可以随时查询个人信息、个人订单信息和个人详细的机票信息,分别通过存储过程P_SelectPassenger、P_SelectOrder和P_ TicketDetails来完成。
5) 数据库的安全性设计
(1) 设置用户权限。数据库管理员具有最高权限,可以操作和管理数据库中所有数据和对象。程序员要实现航空公司操作员、旅客的数据操作功能需具有的权限如表318和表319所示。
(2) 设置数据加密。旅客表(T_Passenger)中的身份证号和旅客密码都是敏感信息,所以应该设置为加密保存。
(3) 设置数据库的备份和还原策略。因为航空公司机票预订系统的数据库每天的数据都有很多变化,所以可以在每天系统应用最少的时间段(一般为2点—5点)进行一次差异数据库备份,每5天进行一次完整数据库备份,只保留近3次完整备份和相应的差异备份。


表318完成航空公司操作员的功能数据操作需具有的权限




对 象 类 型
对 象 名 称
权限

基本表
T_Flight
Select、Insert、Update、Delete

T_Passenger
Select、Delete
T_ FlightTicket
Select、Insert、Update、Delete

视图
V_FlightTicket
Select

V_TicketDetails
Select



表319完成旅客的数据操作功能需具有的权限



对 象 类 型
对 象 名 称
权限
基本表
T_Passenger
Select、Insert、Update

视图
V_FlightTicket
Select

V_TicketDetails
Select
续表



对 象 类 型
对 象 名 称
权限


存储过程
P_FlightTicket1

P_FlightTicket2
P_InsertOrder
P_InsertTicket

P_PassengerFlightTicket

P_UpdateOrder1
P_ TicketDetails
P_UpdateOrder2
P_UpdateOrder3
P_SelectTicket
P_UpdateTicket
P_RefundTicket
P_ComputeRefund
P_DeleteTicket

P_SelectPassenger

P_SelecOrder

Execute


 3.7小结
本章主要介绍了结构化软件设计的全过程,包括结构化总体设计和结构化详细设计。其中详细介绍了总体设计阶段的体系结构设计、接口设计和数据设计的方法和过程以及结构化详细设计的方法和过程,并在理论介绍的同时给出与每一步骤相对应的“高校图书借阅系统”的设计实例,最后用一个“航空公司机票预订系统”的项目案例完整地实现了结构化设计的全过程。
在进行结构化软件设计时,所有设计阶段的结果都应该按国家标准编写设计说明书。另外,最后一步是对软件设计的评审,即对所有设计模型和文档进行评审。对总体设计的评审包括体系结构、接口和数据设计的可行性、清晰度、一致性、可维护性等方面,对详细设计的评审包括清晰性、完整性、一致性、规范性、详细程度、可测试性等方面。只有评审通过,才可以进入软件工程的下一个阶段。
 习题3
1. 结构化设计通常划分成哪两个步骤?
2. 什么是过程设计?
3. 简述结构化设计的原则。
4. 什么是模块独立性?它的两个定性标准度量是什么?
5. 什么是耦合性?一般分为哪7种类型?
6. 什么是模块的内聚?一般分为哪7种类型?
7. 解释数据耦合和功能内聚。
8. 简述体系结构的设计应遵循的启发式设计原则。
9. 简述体系结构的设计中面向数据流方法的设计过程。
10. 简述变换型数据流向变换型结构映射的一般步骤。
11. 事务型数据流的特征是什么?
12. 简单解释顺序文件、随机文件和索引文件。
13. 将ER图映射成关系数据库中的关系模型时,数据对象实体如何映射?
14. 将ER图映射成关系数据库中的关系模型时,两个实体间一对一联系如何映射?
15. 将ER图映射成关系数据库中的关系模型时,两个实体间一对多联系如何映射?
16. 将ER图映射成关系数据库中的关系模型时,两个实体间多对多联系如何映射?
17. 简述视图的优点。
18. 简述过程设计阶段的目标和任务。
19. 程序流程图包括哪5种基本控制结构?
20. 简述NS图的特点。
21. 简述PAD的优点。

22. 分析如图354所示的程序流程图的功能,并画出相应的NS图和PAD图。


23. 分析如图355的程序流程图的功能,并画出相应的NS图和PAD图。


图354第22题程序流程图




图355第23题程序流程图



24. 简述PDL语言的特点和优点。
25. 有一个系统的变换型数据流图如图356所示,其中用虚线划分出了逻辑输入、逻辑输出和变换中心。请画出此系统的体系结构图。




图356第25题数据流图


26. 为习题2第19题的仓库库存管理系统设计体系结构,将ER图转换为关系数据模型并设计表结构和视图,对复杂的模块进行程序流程图的设计。