第二部分、开发阶段系统设计总体设计体系结构设计模块设计详细设计用户界面设计数据结构与算法设计系统实现编码和单元测试综合测试1体系结构就如同人的骨架。如果某个家伙的骨架是猴子,那么无论怎样喂养和美容,他始终都是猴子,不会成为人。模块就如同人的器官,具有特定的功能。人体中最出色的模块设计之一是手,手只有几种动作,却能做无限多的事情。人体中最糟糕的模块设计之一是嘴巴,嘴巴将最有价值但毫无相干的几种功能如吃饭、说话混为一体,使之无法并行处理,真乃人类之不幸。用户界面就如同人的外表,最容易让人一见钟情或一见恶心。象人类追求心灵美和外表美那样,软件系统也追求(内在的)功能强大和(外表的)界面友好。但随着生活节奏的加快,人们已少有兴趣去品味深藏不露的内在美。Unix系统-Windows系统对比,想不到Windows系统竟然能兴风作浪,占去大半市场。数据结构与算法就如同人的血脉和神经,它让器官具有生命并能发挥功能。数据结构与算法分布在体系结构和模块中,它将协调系统的各个功能。人的耳朵和嘴巴虽然是相对独立的器官,但如果耳朵失聪了,嘴巴就只能发出“啊”“呜”的声音,等于丧失了说话的功能,可人们却又能用手势代替说话。人体的数据结构与算法设计真是十分神奇并且十分可笑。软件工程中南大学CentralSouthUniversity第五章总体设计通过这个阶段的工作将划分出组成系统的物理元素——程序、文件、数据库、人工过程和文档等等,但是每个物理元素仍然处于黑盒子级,这些黑盒子里的具体内容将在以后仔细设计。总体设计阶段的另一项重要任务是设计软件的结构,也就是要确定系统中每个程序是由哪些模块组成的,以及这些模块相互间的关系。3总体设计阶段的任务在详细设计之前进行总体设计可以站在全局高度上,花较少成本,从较抽象的层次上分析对比多种可能的系统实现方案和软件结构,从中选出最佳方案和最合理的软件结构,从而用较低成本开发出较高质量的软件系统。4总体设计的意义5.1总体设计的过程总体设计过程通常由两个主要阶段组成:系统设计:确定系统的具体实现方案。结构设计:确定软件结构。9个步骤:①设想供选择的方案②选取合理的方案③推荐最佳方案④功能分解⑤设计软件结构⑥设计数据库⑦制定测试计划⑧书写文档⑨审查和复审565.1总体设计的过程①设想供选择的方案在总体设计阶段分析员应该考虑各种可能的实现方案,并且力求从中选出最佳方案。需求分析阶段得出的数据流图是总体设计的极好的出发点。设想把数据流图中的处理分组的各种可能的方法,抛弃在技术上行不通的分组方法(例如,组内不同处理的执行时间不相容),余下的分组方法代表可能的实现策略,并且可以启示供选择的物理系统。在总体设计的该步骤中分析员仅仅一个边界一个边界地设想并且列出供选择的方案,并不评价这些方案。75.1总体设计的过程②选取合理的方案至少选取低成本、中等成本和高成本三种方案。每种方案准备四份资料:系统流程图;组成系统的物理元素清单;成本/效益分析;实现这个系统的进度计划。85.1总体设计的过程③推荐最佳方案分析员应该综合分析对比各种合理方案的利弊,推荐一个最佳的方案,并且为推荐的方案制定详细的实现计划。在使用部门的负责人接受了分析员所推荐的方案之后,将进入总体设计过程的下一个重要阶段——结构设计。95.1总体设计的过程④功能分解程序(特别是复杂的大型程序)的设计,通常分为两个阶段完成:结构设计:结构设计是总体设计阶段的任务。结构设计确定程序由哪些模块组成,以及这些模块之间的关系。过程设计:过程设计是详细设计阶段的任务。过程设计确定每个模块的处理过程。为确定软件结构,首先需要从实现角度把复杂的功能进一步分解。一般说来,经过分解之后应该使每个功能对大多数程序员而言都是明显易懂的。功能分解导致数据流图的进一步细化,同时还应该用IPO图或其他适当的工具简要描述细化后每个处理的算法。10115.1总体设计的过程⑤设计软件结构通常程序中的一个模块完成一个适当的子功能。应该把模块组织成良好的层次系统,顶层模块调用它的下层模块以实现程序的完整功能,每个下层模块再调用更下层的模块,从而完成程序的一个子功能,最下层的模块完成最具体的功能。软件结构(即由模块组成的层次系统)可以用层次图或结构图来描绘。(5.4节)125.1总体设计的过程⑥设计数据库如需使用数据库,分析员应该在需求分析阶段对系统数据要求所做的分析的基础上进一步设计数据库。包括下述四个步骤:模式设计:模式设计的目的是确定物理数据库结构。子模式设计:子模式是用户使用的数据视图。完整性和安全性设计。优化:主要目的是改进模式和子模式以优化数据的存取。⑦制定测试计划在软件开发的早期阶段考虑测试问题,能促使软件设计人员在设计时注意提高软件的可测试性。135.1总体设计的过程⑧书写文档系统说明用系统流程图描绘的系统构成方案;组成系统的物理元素清单;成本/效益分析;对最佳方案的概括描述;精化的数据流图;用层次图或结构图描绘的软件结构;用IPO图或其他工具(例如,PDL语言)简要描述的各个模块的算法;模块间的接口关系;需求、功能和模块三者之间的交叉参照关系等等。用户手册修改更正在需求分析阶段产生的初步的用户手册。测试计划包括测试策略,测试方案,预期的测试结果,测试进度计划等等。详细的实现计划数据库设计结果145.1总体设计的过程⑨审查和复审最后应该对总体设计的结果进行严格的技术审查,在技术审查通过之后再由使用部门的负责人从管理角度进行复审。155.2设计原理在软件设计过程中应该遵循的基本原理和相关概念模块化抽象逐步求精信息隐蔽和局部化模块独立165.2.1模块化模块是边界元素限定的相邻程序元素(例如:数据说明、可执行的语句)的序列。例如:过程、函数、子程序、宏等都可以作为模块。模块化就是把程序划分成若干个模块,每个模块完成一个子功能,把这些模块集中起来组成一个整体,可以完成指定的功能,满足问题的要求。175.2.1模块化如果一个大型程序仅由一个模块组成,很难被人理解。设函数C(x)定义问题x的复杂程度,函数E(x)定义解决问题x需要的工作量(时间)。对于两个问题P1和P2,如果:C(P1)C(P2)那么E(P1)E(P2)根据解决问题的经验,有一个规律是:C(P1+P2)C(P1)+C(P2)于是有E(P1+P2)E(P1)+E(P2)“各个击破”的结论——把复杂的问题分解成许多容易解决的小问题,原来的问题也就容易解决了随着模块数目增加,设计模块间接口所需要的工作量也将增加。根据这两个因素,得出了图中的总成本曲线。每个程序都相应地有一个最适当的模块数目M,使得系统的开发成本最小。185.2.1模块化模块化的优点可以使软件结构清晰,不仅容易设计也容易阅读和理解;可以使软件容易测试和调试,因而有助于提高软件的可靠性;能够提高软件的可修改性;有助于软件开发工程的组织管理。195.2.1模块化5.2.2抽象抽象就是抽出事物的本质特性而暂时不考虑它们的细节。处理复杂系统的唯一有效的方法是用层次的方式构造和分析它。一个复杂的动态系统首先可以用一些高级的抽象概念构造和理解,这些高级概念又可以用一些较低级的概念构造和理解,如此进行下去,直至最低层次的具体元素。2021软件工程中的抽象:软件工程过程中的每一步都是对软件解决方法抽象层次的一次细化。①在可行性研究(即系统定义)阶段,软件作为整个计算机系统的一个元素(完整部件)。②在需求分析阶段,软件解决方案使用问题环境中的术语来描述。③从概要设计到详细设计阶段抽象层次逐步降低,将面向问题的计算机术语和面向实现的计算机术语结合起来描述解决方法。④最低层抽象层次,是产生源代码,用可以直接实现的方法叙述问题的解决方法。5.2.2抽象22抽象在软件设计中的作用:抽象与逐步求精,模块化密切相关;抽象帮助我们定义软件结构中模块的实体;由抽象到具体地分析和构造出软件的层次结构,提高软件的可理解性。5.2.2抽象23什么是逐步求精逐步求精是人类解决复杂问题时采用的基本方法,也是许多软件工程技术(例如,规格说明技术,设计和实现技术)的基础。可以把逐步求精定义为:“为了能集中精力解决主要问题而尽量推迟对问题细节的考虑。”逐步求精的重要性人类的认知过程遵守Miller法则:一个人在任何时候都只能把注意力集中在(7±2)个知识块上。一个程序通常不止使用7个数据,一个用户也往往有不止7个方面的需求。逐步求精方法帮助软件工程师把精力集中在与当前开发阶段最相关的那些方面上,而忽略那些对整体解决方案来说虽然是必要的,然而目前还不需要考虑的细节,这些细节将留到以后再考虑。5.2.3逐步求精24抽象与求精的关系抽象与求精是一对互补的概念。抽象使得设计者能够说明过程和数据,同时却忽略低层细节。求精则帮助设计者在设计过程中逐步揭示出低层细节。这两个概念都有助于设计者在设计演化过程中创造出完整的设计模型。5.2.3逐步求精5.2.4信息隐蔽和局部化信息隐蔽原理:应该这样设计和确定模块,使得一个模块内包含的信息(过程和数据)对于不需要这些信息的模块来说,是不能访问的。“隐蔽”意味着模块彼此间仅仅交换那些为了完成系统功能而必须交换的信息。“局部化”是指把一些关系密切的软件元素物理地放得彼此靠近。局部化有助于实现信息隐蔽。信息隐蔽和局部化的优点测试期间和软件维护期间需要修改软件,使用信息隐蔽原理作为模块化系统设计的标准就会带来极大好处。因为绝大多数数据和过程对于软件的其他部分而言是隐蔽的(也就是“看”不见的),在修改期间由于疏忽而引入的错误就很少可能传播到软件的其他部分。255.2.5模块独立模块独立的概念是模块化、抽象、信息隐蔽和局部化概念的直接结果。为什么模块的独立性很重要呢?模块独立是做好设计的关键,而设计又是决定软件质量的关键环节。有效的模块化(即具有独立的模块)的软件比较容易开发出来。(当许多人分工合作开发同一个软件时,这个优点尤其重要。)独立的模块比较容易测试和维护。(相对说来,修改设计和程序需要的工作量比较小,错误传播范围小,需要扩充功能时能够“插入”模块。)模块的独立程度可以由两个定性标准度量,这两个标准分别称为耦合和内聚。262019/12/1527耦合性是对一个软件结构中不同模块之间互连程度的度量。模块间的耦合程度强烈影响系统的可理解性、可测试性、可靠性和可维护性。耦合是影响软件复杂程度的一个重要因素。由强到弱分成五级:数据耦合(数据通信)同构耦合(使用相同的数据结构)控制耦合(一方控制另一方)公用耦合(涉及共同的数据区)内容耦合(一方涉及另一方)5.2.5模块独立——耦合2019/12/1528应该采取下述设计原则:尽量使用数据耦合,少用控制耦合,限制公共环境耦合的范围,完全不用内容耦合。5.2.5模块独立——耦合(1)非直接耦合如果两个模块之间没有直接关系,它们之间的联系完全是通过主模块的控制和调用来实现的,这就是非直接耦合。这种耦合的模块独立性最强。但是,在一个软件系统中不可能所有模块之间都没有任何连接。2019/12/15295.2.5模块独立——耦合(2)数据耦合如果一个模块访问另一个模块时,彼此之间是通过数据参数(不是控制参数、公共数据结构或外部变量,而是简单的数据)来交换输入、输出信息的,则称这种耦合为数据耦合。数据耦合是松散的耦合,模块之间的独立性比较强。在软件程序结构中至少必须有这类耦合。最好的耦合方式2019/12/15305.2.5模块独立——耦合main(){intx,y;printf(x+y=%d,sum(x,y));}主函数与sum函数之间即为数据耦合关系sum(inta,intb){intc;c=a+b;return(c);}(3)同构(标记)耦合如果一组模块通过参数表传递记录信息,(把整个数据结构作为参数传递),而被调用的模块只需要使用其中一部分数据元素,