资源描述
,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,SIT,软件工程,讲稿,第二部分 课程内容,1,第五章 软件设计,学习目标,:,了解软件体系结构的概念,研究的内容与范畴;,掌握软件体系结构设计原则和熟练掌握几种典型的体系结构。,理解面向行为和面向数据两种设计技术的差别;,掌握软件设计阶段三个活动(结构设计、详细设计、设计测试)的主要内容;掌握结构化设计方法(数据流分析、扩展、事务分析);,了解面向数据结构的设计方法(,Jackson,方法);,了解在设计阶段的所使用测试和度量方法和工具;,2,5.1,软件体系结构概述,良好的体系结构意味着普适、高效和稳定。抽象地说,软件体系结构包括构成系统的设计元素的描述,设计元素的交互,设计元素组合的模式,以及在这些模式中的约束。一般来说,一个具体的系统由构件的集合以及它们之间的关系组成。这样的系统又有可能成为一个更大的系统的组成元素。,5.1.1,软件体系结构研究领域,IEEE 610.1221990,软件工程标准词汇中的体系结构的定义,,软件体系结构是以构件、构件之间的关系、构件与环境之间的关系为内容的某一系统的基本组织结构,以及指导上述内容设计与演化的原理。,3,5.1,软件体系结构概述,软件体系结构是指一个或者多个结构。结构中包括软件的组件,组件的外部可见属性以及它们之间的相互关系。体系结构的设计是设计过程的第一个阶段,并且成为设计和需求工程过程之间的桥梁,时常与一些需求描述活动齐头并进。体系结构设计所关心的是建立一个基本的结构框架,能够识别出系统的组件(又称系统成份或构件)以及他们之间的通信。,5.1.2,软件体系结构研究的内容和范畴,软件体系结构研究的主要内容,涉及软件体系结构描述、软件体系结构风格、软件体系结构评价和软件体系结构的形式化方法等。解决好软件的重用、质量和维护问题是研究软件体系结构的根本目的。,将当前软件体系结构分为,4,个研究领域:,4,5.1,软件体系结构概述,第一类,是通过提供一种新的体系结构描述语言解决体系结构描述问题。,第二类,是体系结构领域知识的总结性研究。,第三类,是针对特定领域的框架,SEI90,Tra94,的研究。这类研究产生了针对一类特殊软件的体系结构框架,比如,航空电子控制系统、移动机器人、用户界面。,第四类,是软件体系结构形式化支持的研究。,5.1.3,风格、设计模式、框架,1.,体系结构风格(,Architecture Styles,),体系结构风格是描述特定系统组织方式的惯用范例,强调组织模式和惯用范例。,5,5.1,软件体系结构概述,2.,设计模式(,Design Pattern,),设计模式是软件问题高效和成熟的设计模板,模板包含了固有问题的解决方案。,3.,应用框架(,Application Framework,),应用框架是整个或部分系统的可重用设计,表现为一组抽象构件的集合以及构件实例间交互的方法。,6,5.2,软件体系结构设计原则,软件工程师在多年的实践中,对软件体系结构的设计总结出一些带有普遍性的原则,,这些基本原则包括,:,抽象,分而治之,封装和信息隐蔽,模块化,高内聚和低耦合,关注点分离,策略和实现的分离,7,5.2,软件体系结构设计原则,1,抽象的原则,抽象是人们认识复杂事物的基本方法。它的实质是集中表现事物的主要特征和属性,隐藏和忽略细节部分,并用于概括普遍的、具有相同特征和属性的事物。,2,分而治之的原则,将大的问题分成几个小的问题,软件设计中的分解包括:,横向分解:按照从底层基础到上层问题的方式,将问题分解成相互独立的层次。每层完成局部问题并对上层提供支持。,纵向分解:在每个层次上,将问题分解成多项,相互配合实现完整的解。,8,5.2,软件体系结构设计原则,3,封装和信息隐藏原则,采用封装的方式,隐藏各部分处理的复杂性,只留出简单的、统一形式的访问方式。这样可以减少各部分的依赖程度,增强可维护性。封装填补了抽象留下的空白。抽象是说:,“,可以让你从高层的细节来看待一个对象。,”,而封装则说:,“,除此之外,你不能看到对象的任何其他细节层次。,”,4,模块化原则,模块是软件被划分成独立命名的,并可被独立访问的成分。模块划分,粒度可大可小。划分的依据是对应用逻辑结构的理解。,9,5.2,软件体系结构设计原则,5,高内聚和低耦合,内聚性是指软件成分的内部特性。成分中各处理元素的关联越紧密越好。耦合性是指软件成分间关系的特性。软件成分间的关联越松散越好。,6,关注点分离原则,软件成分被用于不同的场景时,会有对于不同场景的适应性问题。但是,所必须适应的内容并非全部,只是一部分,即所谓的关注点。软件设计要将关注点和非关注点分离,关注点的部分可以设定,而非关注点的部分用来复用,非关注点应选择与条件、场景独立的软件成分。,10,5.2,软件体系结构设计原则,7,策略和实现的分离原则,策略指的是软件中用于处理上下文相关的决策、信息语义和解释转换、参数选择等成分。实现指的是软件中规范且完整的执行算法。,软件设计中要将策略成分和实现成分分离,至少在一个软件成分中明显分开。这样可以提高维护性。因为实现的变动远比策略要少的多。,5.2.1,软件体系结构风格研究,软件体系结构风格是指在众多系统中所拥有的共同的组织结构框架和语义特性,指导如何将各个模块和子系统组织成一个完整的系统。,1,C/S,(,Client/Server,)客户端,/,服务器结构风格,11,5.2,软件体系结构设计原则,典型的,C/S,结构由三部分组成,:客户端组件、服务器组件和中间层组件。,客户端组件,是用户前端部分,一般表示为图形用户界面;,中间层组件,是体系结构的连接器,一般由一些,API,和协议组成;,服务器组件,是,C/S,结构的核心,用于执行客户端请求。,C/S,结构应用系统基本运行关系为,“,请求,/,响应,”,模式。,当需要服务时客户端发出,“,请求,”,,服务器接受,“,请求,”,并,“,响应,”,,然后执行相应的服务,把执行结果送回给客户端,由它进一步处理后再提交给用户。,C/S,结构最鲜明的特征是共享资源,,,C/S,结构的缺点是客户端很庞大,应用程序升级和维护十分困难。,2,MVC,结构风格,模型(,Model,),-,视图(,View,),-,控制器(,Controller,)风格简称为,MVC,风格。,12,5.2,软件体系结构设计原则,它强制性的使应用程序的输入、处理和输出分开。使用,MVC,结构的应用程序被分成,三个核心部件,:模型、视图、控制器,它们各自处理自己的任务。其中,视图,为用户显示模型信息。视图从模型获取数据,一个模型可以对应有多个视图。,模型,是应用程序的核心,它封装内核数据和状态,对模型的修改将扩散到所有视图中,所有需要从模型获取信息的对象都必须注册为模型的视图。,控制器,是提供给用户进行操作的接口。每个视图与一个控制器构件相关联。控制器接收用户输入,将输入翻译成服务请求,送到模型或视图,用户只通过控制器与系统交互。目前这种三层架构的风格应用的最为广泛。,MVC,的优点如下:,低耦合性,13,5.2,软件体系结构设计原则,高重用性和可适用性,较低的生命周期成本,快速的部署,可维护性,有利于软件工程化管理,3,管道,/,过滤器风格,管道,/,过滤器,(Pipe/Filter),风格的软件体系结构中,,每个部件都有一组输入和输出,,每个部件从各自的输入读取数据流,经过内部处理,在各自的输出产生数据流。这个过程通常通过对输入流应用一个逻辑的转换过程和递进的计算过程来完成,所以在输入被完全消费之前,输出便产生了,因此这里的部件被称为,“,过滤器,”,。,14,5.2,软件体系结构设计原则,这种风格的连接器就像是数据流传输的管道,将一个过滤器的输出传到另一过滤器的输入,因此连接器被称为,“,管道,”,。管道,/,过滤器风格的软件体系结构的,优点,是不再需要中间文件,但是也可以使用中间文件;通过使用过滤器增加了灵活性;过滤器组件还可以重用;是流水线的快速原型,可以实现并行处理提高效率。这种结构也存在一些,弱点,,比如共享状态信息或者昂贵,或者不灵活;数据转换需要额外开销;错误处理能力不强等等。,4,正交软件体系结构风格,正交软件体系结构是一种以垂直线索为基础的层次化结构,它由组织层(,Layer,)和线索(,Thread,)的构件构成,不同线索中的构件之间没有相互调用,即线索之间是相互,15,5.2,软件体系结构设计原则,独立的。层由一组具有相同抽象级别的构件构成。线索是子系统的特例,它由完成不同层次功能的构件组成(可通过相互调用来关联),每一条线索完成整个系统中相对独立的一部分功能。正交软件体系结构,基本思想,是把应用系统的结构按功能的正交相关性(即相互独立性),垂直分割为若干个线索(子系统),线索又分为几个层次,每个线索由多个具有不同层次功能和不同抽象级别的构件构成。如果不同线索间的构件之间完全没有相互调用,那么此结构就是完全正交的。正交软件体系结构具有结构清晰、易于理解、修改、可维护性强和可移植性强等优点。它可以为一个领域内的所有应用程序所共享,这些软件有着相同或类似的层次和线索,可以实现体系结构级的重用。,16,5.2,软件体系结构设计原则,5.2.2,软件体系结构描述语言研究,目前软件体系结构在表示形式上仍然不正规、不完备,为了解决这些问题,许多机构正致力于开发,体系结构的形式化表示,即体系结构描述语言,ADL,(,Architecture Description Language,),,ADL,描述的是软件系统的高层设计而不是系统的实现细节或源代码模块,,它主要有助于体系结构设计者能以更好的方式清楚地描述体系结构,以便于其他人对于这种描述的理解,更重要的是有助于利用工具来分析设计体系结构。,ADL,也有其负面的影响,每种,ADL,语法不同且互不兼容,现有的,ADL,大多是与领域相关的,不利于对不用领域体系结构的说明,,ADL,在某些方面又大同小异,容易造成冗余。,17,5.2,软件体系结构设计原则,5.2.3,软件体系结构求精方法研究,软件体系结构求精是指,在对软件体系结构进行抽象描述之后对其分层细化、逐层求精,直至形成具体的可实现的软件体系结构。由于求精是由抽象到具体的一个过程,抽象层次和具体层次之间的求精关系能够保证应用的完整性和一致性。,目前对软件体系结构求精方法的研究尚处在起步和探索阶段,主要有基于行为替代的体系结构求精、基于风格的体系结构求精和基于构件的体系结构求精等方法。这些求精方法大都以一种形式化方法为基础,从体系结构或构成体系结构的基本元素入手对体系结构实施求精。,18,5.2,软件体系结构设计原则,5.2.4,软件体系结构测试技术研究,软件体系结构测试主要是为了检查在,ADL,描述的软件体系结构规约中所描述的结构是否存在缺陷。具体地讲,需要检查软件体系结构的总体拓扑结构是否存在问题?构件模型的结构是否合理?构件的接口和连接子的角色之间是否匹配?是否满足相应的约束等等。,基本的研究主题主要集中在,结构测试,一致性测试和回归测试三个方面。,结构测试,包括单元结构测试和集成结构测试。,单元结构测试,目的是为了发现软件体系结构基本组成元素中存在的结构问题。,集成结构测试,目的是为了对软件体系结构自身的结构及配置进行分析和检查,以便在软件生命周期的早期阶段发现缺陷;,一致性测试,主要目的是测试实现,19,5.2,软件体系结构设计原则,系统的行为是否与软件体系结构规约定义的行为一致;,回归测试,的目标就是检查新的代码是否满足初始的软件体系结构规约,尽可能多地利用现有测试用例来测试新的软件体系结构规约和新的代码,以确认新的软件体系结构是否正确,以及新的代码是否与新的软件体系结构一致。,5.2.5,基于软件体系结构的软件开发过程研究,所有软件开发方法都要解决从需求到实现之间的转换问题。软件开发过程模型是跨越整个软件生存周期的系统开发、运行、维护所实施的全部工作和任务的结构框架,给出了软件开发活动各阶段之间的关系。基于体系结构的软件开发包含三个主要阶段:,20,5.2,软件体系结构设计原则,通过对特定领域应用软件进行分析,提炼出其中的稳定需求和易变需求,建立可重用的领域模型。,在领域模型的基础上,根据需求规格说明提炼出特定领域的软件体系结构。,解决软件体系结构中具体组件和连接件的设计问题。,5.2.6,典型体系结构介绍,1,),TAFIM,体系结构,Tafim,体系结构的,主要目的,是为了实现互操作和信息系统集成的,所以首先提出了信息管理与集成模型。集成的目的是实现和改进系统的互操作性,与各种国际、政府标准相兼容,并为用户提供一个单一的接口。,21,5.2,软件体系结构设计原则,1,、集成的类型和层次,集成既可在层次内部,也可在层次之间,但是集成类型的需求必须被定义。,功能函数集成:通常包括将两个或者是多个具有相似的功能的软件模块融合为一个新的软件模块,或者将两个或者是多个不相似的软件模块通过一个公共数据库相关联。,技术集成:通常包括硬件互操作性的兼容性和连接性,以及软件的相关性(例如:协议之间的对话)。,2.Tafim,通用技术参考模型,通用技术参考模型是一个概念、实体、接口、以及提供标准规范基础图标的集合。,22,5.2,软件体系结构设计原则,图,5.4 Tafim,通用技术参考模型,23,5.2,软件体系结构设计原则,2,),DOD,体系结构,DOD,的体系结构研究着眼于从大系统的整体性出发,统一组织制定公共的体系结构框架等规范文件来指导美军各军兵种和,DOD,各机构的体系结构开发,,DOD,体系结构研究的重点是体系结构框架。,DOD,技术参考模型:,DOD,技术参考模型集成了服务视图和接口视图,如图,5.6,所示。按照应用软件、应用平台和外部环境三个层次排列,左侧为服务视图,提供了服务相关说明,右侧为接口视图,表示提供相应服务的接口,。,24,5.2,软件体系结构设计原则,图,5.6 DOD,技术参考模型服务视图和接口视图,25,5.2,软件体系结构设计原则,3,),TOGAF,体系结构,TOGAF,是设计用于支持技术,(IT),体系结构的开发。它也支持对,IT,体系结构开发有影响的一部分商业体系结构。它主要关心有意支持核心配置和任务关键性应用的软件基础结构。,TOGAF,包括两个主要部分:,TOGAF,基础体系结构,公共服务和功能的体系结构,为构建具体的体系结构和体系结构构造块提供基础。,TOGAF,体系结构开发方法,(ADM),,正确地解释如何从基础体系结构获取具体组织的体系结构。,26,5.2,软件体系结构设计原则,推荐一个循环的体系结构开发途径,如图,5.7,所示。,ADM,各阶段描述,Phase A,:初始化和框架:确认需求,初始化体系结构开发循环,Phase B,:基线描述:捕获相关的现有环境,Phase C,:目标体系结构定义目标体系结构,Phase D,:时机和解决方案:评价和选择主工作包,Phase E,:移植计划:区分工作的优先级,开发概要计划,Phase F,:实现:开发完整计划并执行,Phase G,:体系结构维护:建立维护新基线的进程,27,5.2,软件体系结构设计原则,图,5.7,体系结构开发循环,28,5.3,设计过程,软件设计过程由三个活动组成,:,概要设计,(体系结构设计,逻辑设计,高层设计):对软件产品进行模块化分解,,即仔细分析规格说明,产生具有所需功能的模块结构。,详细设计,(模块化设计,物理设计,低层设计):对每个模块进行详细设计。例如,选择特定的算法和数据结构。,设计测试,:与结构设计和详细设计形成不可分割的完整实体,像是整个软件开发和维护过程的一个完整的部分。,29,5.3,设计过程,5.3.1,概要设计,概要设计的基本目的就是回答,“,概括地说,系统应该如何实现,”,这个问题。在详细设计之前进行概要设计可以站在全局的角度上,花较少的成本,从抽象层次上对比分析多种可能的系统实现方案和软件结构,从而用较低成本开发出较高质量的软件系统。,1,软件体系结构,体系结构的设计是设计过程的第一个阶段,并且变现为设计和需求工程过程之间的桥梁,时常与一些需求描述活动齐头并进。体系结构设计所关心的是建立一个基本的结构框架,能够识别出系统的系统成份以及他们之间的通信。,30,5.3,设计过程,(,1,)体系结构的设计,识别组成系统的子系统和子系统控制和通信的设计过程是体系结构设计,这个设计过程的输出是软件体系结构的描述。,(,2,)清晰的体系结构的优点,第一个是体系结构可能被当作系统信息持有者讨论的一个焦点,并成为信息持有者之间的沟通桥梁;第二个是通过体系结构的清晰分析,对系统能否符合它的非功能需求的判别是可能的;第三个是有利于实现复用。,(,3,)体系结构的设计过程,首先是系统构成,系统被分解成一些主要的子系统,同时识别出他们之间的通信;其次是控制与建模,建立了系统,31,5.3,设计过程,的不同部分之间的控制关系模型;最后是模块的分解,将被识别的子系统分解成组件。,(,4,)子系统和组件,一个子系统本身就是一个系统,它的操作独立于由其他的子系统提供的服务。一个模块是一个系统组件,它能提供服务给其他组件,但是不能认为是一个独立的系统。,(,5,)体系结构模型,可能在设计过程期间会创建不同的体系结构模型,每个模型代表了从不同角度对系统结构的认识。,2,数据设计,数据设计是把在分析模型中定义的数据对象转化成组件级的数据结构,并且在必要时转化为应用程序集的数据库,32,5.3,设计过程,体系结构。如何从这样庞大的数据环境中提取有用的信息。为了解决这个问题,可以采取,数据挖掘技术,和,数据仓库,(,data warehouse,)。数据挖掘技术也称为,数据库中的知识发现,(,KDD,:,knowledge discovery in database,)。,考虑到需求分析和设计活动经常会重叠,在此只考虑以下数据规格说明原则:,(,1,)应用于功能和行为的系统分析原则也可应用于数据。,(,2,)标识所有数据结构及其完成的操作。,(,3,)应该建立定义数据对象内容的机制,并且用于定义数据及其操作。,33,5.3,设计过程,(,4,)低层的数据设计决策应该延迟到设计过程的后期。,(,5,)只有那些直接使用数据结构内部数据的模块才能够看到该数据结构的表示。,(,6,)应该开发一个由有用的数据结构及其操作组成的库。,(,7,)软件设计和程序设计语言应该支持抽象数据类型的规格说明和实现。,3.,体系结构风格与模式,一种体系结构风格,就是一种加在整个系统设计上面的变换。它的,目的,就是为系统的所有组件建立一个结构。,34,5.3,设计过程,在对已有体系结构进行再加工时,强制采用一种体系结构风格会导致软件结构的根本性改变,包括对构件功能的再分配。,与体系结构风格一样,,体系结构模式,也对体系结构的设计施加一种变换。然而,体系结构模式与体系结构风格在许多基本方面存在,不同,:,一是,体系结构模式涉及的范围要小一些,它更多集中在体系结构的某一局部而不是体系结构整体;,二是,模式在体系结构上施加规则,描述了软件是如何在基础设施层次上处理某些功能性方面的问题;,三是,体系结构模式倾向于在系统结构的环境中处理特定的行为问题,例如,一个实时应用系统如何处理同步和中断。模式可以和体系结构风格结合起来,用于建立整个系统结构的外形。,35,5.3,设计过程,4.,体系结构设计,在体系结构设计开始的时候,软件必须放在所处环境进行开发,一旦建立了软件的环境模型,并描述出所有的外部软件接口,那么设计师就可以通过定义和求精实现体系结构的组件来描述系统的结构。这个过程不停地迭代,直到获得一个完善的体系结构。在体系结构设计之初,软件架构师用体系结构环境图(,ACD,)对软件与外部实体交互方式进行建模。然后,定义一个原始模型,即一个类或者一个模式,描述了一个目标系统体系结构设计的核心抽象。整个系统的体系结构可以用,UML,构件图表示。至此所建立的体系结构设计仍然处于比较高的层次,需更进一步的精化。,36,5.3,设计过程,5.,评估可选的体系结构设计,设计会导致多种可供选择的候选体系结构,其中每一种候选体系结构都需要评估,以确定哪种体系结构最适合要解决的问题。体系结构权衡分析方法(,ATAM,),该方法建立了一个迭代的软件体系结构评估过程。,(,1,)收集场景。开发一系列的用例,从用户的角度描述系统。,(,2,)诱导需求、约束和环境描述。,(,3,)描述那些已被选用于解决场景和需求的体系结构风格,/,模式。,(,4,)通过孤立地考虑每个属性来评估质量属性。,37,5.3,设计过程,(,5,)针对特定的体系结构风格,弄清质量属性对各种体系结构属性的敏感性。这可以通过对体系结构做小的变更并确定某质量属性(如性能)对该变更的敏感性而进行。受体系结构的变更影响很大的属性称为敏感点。,(,6,)使用在第,5,步中进行的敏感性分析鉴定候选的体系结构。,这,6,个步骤描述了第一次,ATAM,迭代。基于第,5,步和第,6,步的结果,某些候选体系结构可能被删除,剩余的体系结构可能被修改和进一步细化,然后,,ATAM,步骤被再次应用。,38,5.3,设计过程,5.3.2,详细设计,选择完系统结构之后,就需要决定采用什么样的方法将子系统分解为一些模块。在系统组成和模块分解之间并没有一个非常严格的界限。然而,模块中的组件总是小于子系统的。在详细设计阶段,全部的数据和软件的程序结构都已经建立起来。其目的是将设计模型转化为运行软件。,1.,模块设计,一个模块由一个单独的代码块组成,它可像过程、函数或方法一样被调用。,特别强调的是:传统范型的过程和函数都是模块。在面向对象范型中,一个对象是模块,对象内的方法也是模块。,39,5.3,设计过程,模块的设计需要遵循,高内聚、低耦合,和一些启发式规则,下面将逐一阐述。,(,1,)内聚,模块,“,内聚,”,:,一个模块内部的交互程度,模块,“,耦合,”,:两个模块之间的交互程度,区分以下概念:,模块行为,:模块做什么,也就是它的工作情况。,模块逻辑,:指模块如何完成它的行为。,模块内容,:指的是模块的特定用途。,结构化设计的,关键,是制定模块是根据它的行为,而不是它的逻辑和内容。内聚标志着一个模块内各个元素彼此结合的紧密程度,它是信息隐藏和局部化概念的自然扩展。,40,5.3,设计过程,简单地说,理想内聚的模块只做一件事情。,内聚,按模块内各个元素彼此结合的紧密程度通常分为高内聚、中内聚和低内聚三类,设计时应力求做到高内聚。图,5.11,展示了内聚的级别。,图,5.11,内聚的级别,41,5.3,设计过程,低内聚有,偶然性内聚、逻辑性内聚和时间性内聚。,偶然性内聚:如果一个模块执行多个完全不相关的行为,则其具有偶然性的内聚。,逻辑性内聚:当一个模块进行一系列的相关操作,每个操作由调用模块来选择时,该模块就具有逻辑性的内聚。,时间性内聚:当模块执行一系列与时间有关的操作时,该模块具有时间性内聚。,中内聚有,过程性内聚和通信性内聚。,过程性内聚:如果一个模块执行一系列与产品要遵循的步骤顺序有关的操作,则该模块具有过程性内聚。,通信性内聚:如果一个模块执行一系列与产品要遵循的步骤顺序有关的操作,并且所有操作都在相同的数据上,42,5.3,设计过程,进行,则该模块具有通信性内聚。,高内聚有,功能性内聚和信息性内聚。,功能性内聚:只执行一个操作或只达到一个单一目标的模块具有功能性内聚。,信息性内聚:如果模块进行许多操作,每个都有各自的入口点。每个操作的代码相对独立,而且所有操作都在相同的数据结构上完成,则该模块具有信息性内聚。,逻辑性内聚和信息性内聚之间的主要,区别,是逻辑性内聚模块的各个操作之间是互相纠缠的,而信息性内聚模块的各操作间代码是完全独立的。,43,5.3,设计过程,(,2,)耦合,耦合,是对一个软件结构内不同模块之间互相关联程度的度量。耦合强弱取决于模块间接口的复杂程度,进入或访问一个模块的点,以及通过接口的数据。在软件设计中应该追求尽可能松散耦合的系统。模块间的耦合程度强烈影响着系统的可理解性、可测试性、可靠性和可维护性。根据模块间相互关联的程度,,耦合可以被分为,数据耦合、印记耦合、控制耦合、共用耦合和内容耦合,图,5.13,说明了耦合的级别。,44,5.3,设计过程,图,5.13,耦合的级别,45,5.3,设计过程,数据耦合是低耦合。,如果两个模块的所有参数是同构的数据项,则它们具有数据耦合,即,每个参数或者是简单的参数,或者是数据结构(该数据结构中的所有元素为被调用的模块所使用)。系统中至少必须存在这种耦合,因为只有当某些模块的输出数据作为另一些模块的输入数据时,系统才能完成有价值的功能。一般来说,一个系统内可以只包含数据耦合。如果两个模块是数据耦合的,那么维护很容易,因为对一个模块的修改很少会给另一个模块产生连带的错误。,46,5.3,设计过程,印记耦合,是把数据结构作为参数进行传递,但被调用的模块只在该数据结构的一些个别组件上进行操作。印记耦合也会造成调用过程传递了比需要更多的数据,对数据访问无法控制的问题和计算机犯罪的问题都会出现。例如:在像,C,或,C,这样的语言中,把指向记录的指针作为参数传递时就会出现印记耦合。,图,5.14,控制耦合示例,47,5.3,设计过程,控制耦合是中等程度的耦合。,如果两个模块中一个模块给另一个模块传递控制要素(而非简单的数据),则它们具有控制耦合,即一个模块明确地控制另一个模块的逻辑。例如图,5.14,所示控制耦合的例子,如果模块,q,给模块,p,传回信息,而且模块,p,决定收到信息后进行什么操作,那么,q,在传递数据。但如果模块,q,不仅传回信息,还传回模块,p,应执行什么操作的指示,那么二者之间存在着控制耦合,如图,14,所示。控制耦合的一个主要的问题是两个模块是非独立的,被调用的模块(如,q,)需要知道模块,p,的内部结构和逻辑,因此降低了复用的可能性。,48,5.3,设计过程,共用耦合是高耦合。,如果两个模块都可存取相同的全局数据(而非传递参数),则它们是共用耦合。共用耦合的两个或多个模块通过一个公共的数据环境相互作用,这个公共环境可以是全程变量、共享的通信区、内存的公共覆盖区、任何存储介质上的文件或物理设备。,共用耦合的复杂程度,随着耦合模块个数而变化,当耦合的模块数增加时,负责程度显著增加。这种形式的耦合存在问题是它与结构化编程相矛盾,因为生成的代码完全不可读。共用耦合的模块难以复用,因为每次复用该模块时必须提供使用同一个全局变量的清单。一个潜在的最危险的问题是计算机犯罪,因为公共环境可能暴露出比需要更多的数据。,49,5.3,设计过程,内容耦合,是最高程度的耦合。如果发生了下列情况之一,两个模块间就发生了内容耦合。,一个模块访问另一个模块的内部数据;,一个模块不通过正常入口而转到另一个模块的内部;,两个模块有一部分程序代码重叠(只可能出现在汇编程序中);,一个模块有多个入口(意味着一个模块有多种功能)。,内聚和耦合是密切相关的,模块内的高内聚往往意味着模块间的松耦合。,内聚和耦合都是进行模块化设计的有力工具,但是实践表明内聚更重要,应该把更多注意力集中到提高模块的内聚程度上,有能力通过修改设计提高模块的内聚程度并且降低模块间的耦合程度,从而获得较高的模块独立性。,50,5.3,设计过程,(,3,)启发规则,启发式规则能帮助设计人员提高软件设计质量。主要有:,改进软件结构提高模块的独立性。设计出软件的初步结构以后,应该审查分析这个结构,通过模块分解与合并,力求降低耦合提高内聚。,模块的规模应适中。经验表明,一个模块的规模不应过大,最好能写在一张纸内(通常不超过,60,行语句)。,51,5.3,设计过程,深度、宽度、扇出、扇入应适当。,深度,表示软件结构中控制的层数,它往往能粗略地标志一个系统的大小和复杂的程度。,宽度,是软件结构内同一个层次上的模块总数的最大值。一般说来,宽度越大系统越复杂。对宽度影响最大的因素是模块的扇出。,扇出,是一个模块直接控制(调用)的模块数目,扇出过大意味着模块过分复杂,需要控制和协调过多的下级模块;扇出过小也不好。一个模块的,扇入,表明有多少个上级模块直接调用它,扇入越大则共享该模块的上级模块数目越多,这是有好处的,但是,不能违背模块独立原理单纯追求高扇入。,52,5.3,设计过程,模块的作用域应该在控制域内。,模块的作用域定义,为该模块内一个判定影响的所有模块的集合。模块的控制域是这个模块本身以及所有直接或间接从属于它的模块的集合。在一个设计得很好的系统中,所有受判定影响的模块应该都从属于做出判定的那个模块,最好局限于做出判定的那个模块本身及它的直属下级模块。,力争模块接口简单。模块接口复杂是软件发生错误的一个主要原因。应该仔细设计模块接口,使得信息传递简单并且和模块的功能一致。接口复杂或不一致是紧耦合和低内聚的征兆,应该重新分析这个模块的独立性。应尽可能保证模块是单入口和单出口的,杜绝内容耦合的出现,提高软件的可理解性和可维护性。,53,5.3,设计过程,2.,从模块到对象,(,1,)数据封装,数据封装,就是数据结构连同在该数据结构上进行的操作。使用数据封装设计产品的好处有:,数据封装有利于产品开发,数据封装是,“,抽象,”,的一个例子。,“,抽象,”,只是一种通过抑制不必要的细节并强调有关的细节达到逐步求精的方法。,“,封装,”,是把真实世界中的实体的各个方面集中在一个对该实体进行建模的单元中。,数据封装有利于产品维护,数据封装以简化产品维护的方式支持了数据抽象的实现,从而减小了出现回归错误的可能性。,54,5.3,设计过程,(,2,)抽象数据类型,过程抽象,是指具有明确和有限功能的指令序列。,数据抽象,是描述数据对象的冠名数据集合。在过程抽象,“,开,”,的情形下,我们可以定义一个名为,“,门,”,的数据抽象。同任何数据对象一样,门的数据抽象将包含一组属性(例如,门的类型、转动方向、开门机构、重量和尺寸)。因此,过程抽象开将利用数据抽象门的属性所包含的信息。,一个数据类型连同在该数据类型上进行的操作,这样的构造称为,抽象的数据类型,。它支持数据抽象和过程抽象。当修改产品时,通常不会修改抽象的数据类型,最多需要增加额外的操作到抽象数据类型中。,55,5.3,设计过程,(,3,)信息隐藏,模块内部的数据与过程,应该对不需要了解这些数据与过程的模块隐藏起来。其目的是为了提高模块的独立性。,隐藏意味着通过定义一系列独立的模块可以得到有效的模块化,独立模块之间只交流实现软件功能所必需的那些信息。抽象有助于定义构成软件的过程(或信息)实体。隐藏定义并加强了模块内的过程细节和模块所适用的任何局部数据结构的访问约束。,(,4,)对象,在面向对象的语言中,可以将,“,类,”,定义为支持集成的抽象数据类型,那么,“,对象,”,就是类的实例。对象是一种模块。一个类可包含两种操作,继承的方法和该类专有的,56,5.3,设计过程,方法。若两个类具有相同的功能,则他们具有相同层次的内聚。继承并没有产生新的耦合形式。无论传统范型与面向对象范型有多大区别,面向对象范型并不能产生新的内聚或耦合类型。,看待软件产品有两种方式,,一种方式,是只考虑数据,包括局部和全局的变量,参数、动态数据结构、文件等等。,另一种方式,是只考虑对数据的操作,也就是说过程和函数。按照把软件分为数据和行为这种分法,结构化技术主要分为两组:,面向数据的,:强调产品的数据,只在数据的框架内考察行为。,面向行为的,:强调行为,只在深入分析产品行为后考察数据。,57,5.3,设计过程,面向对象的技术可以同等地对待数据和行为。,一个对象是由数据和行为组成的,。从模块设计的角度看,有,三种设计思想,:面向过程的、面向功能的、面向对象的。,第一种,思想的设计结果,各模块的功能可能相互交叉或重叠,模块间常常存在数据的共享或数据结构的共享,很难把这些模块移用到其他应用中去。,第二种,思想设计出来的模块,各模块的功能单一,如能将与其他模块的数据共享降低到最低限度,就可以在某些应用中复用。,第三种,思想设计出来的是一个个独立的单位,不仅复用性好,而且易于测试、联调和维护。,58,5.4,面向行为的设计,面向行为的设计将一个产品分解成为具有高内聚和低耦合的模块。,常用的技术为:数据流分析和事务分析,。理论上说,只要规格说明可以用数据流图来描述,就可以使用数据流分析来设计,一般的规格说明都用数据流图来说明,因此数据流分析方法被广泛的使用。,5.4.1,数据流分析,1.,数据流分析的概念,数据流分析是一种获得高内聚模块的设计技术。根据规格说明文件中的数据流图,软件设计人员就可以得到关于产品输入输出的精确和完整的信息。,59,5.4,面向行为的设计,2.,结构图,结构图是进行软件结构设计的一个有力工具,可用于基于数据流分析的设计工作。图中一个方框代表一个模块,框内注明模块的名字或主要功能;方框之间的箭头(或直线)表示模块的调用关系。因为按照惯例总是图中位于上方的方框代表的模块调用下方的模块,即使不用箭头也不会产生二义性,为了简单起见,可以用直线而不用箭头表示模块间的调用关系。,在结构图中通常还用带注释的箭头表示模块调用过程中传递的信息。如果希望进一步表明传递的信息是数据还是控制信息,则可以利用注释箭头尾部的形状来区分:尾部是空心圆表示传递的是数据,实心圆表示传递的是控制信息。,60,5.4,面向行为的设计,图,5.17,给出了一个结构图的例子。此外,还有一些特殊的符号,可以表示模块的选择调用或循环调用。图,5.18,表示当模块,M,中某个判定为真时调用模块,A,,为假时调用模块,B,。图,5.19,表示模块,M,循环调用模块,A,、,B,和,C,。,图,5.17,结构图的例子,产生最佳解的一般结构,61,5.4,面向行为的设计,图,5.18,选择调用,图,5.19,循环调用,注意,结构图并不严格表示模块的调用次序,也并不指明什么时候调用下层模块。,62,5.4,面向行为的设计,3.,过程设计语言,详细设计可以采用程序描述语言,PDL,。,PDL,本质上是由所选择的实现语言的控制语句连接起来的注释组成的,代码清单显示了模块的详细设计,它可以是用带有,C,或,Java,风格的,PDL,编写的。,PDL,的,优点,在于它通常是清晰和准确的,实现步骤常常仅由少数的从注释到相应的编程语言的翻译组成。,缺点,是容易变成模块完整的代码实现。,4.,数据流分析示例,设计一个软件产品,将一个文件名作为输入,并返回那个文件中的字数。使用图,5.20,中的两个最高抽取点分解产品的结果显示在图,5.21,中。,63,5.4,面向行为的设计,图,5.21,中的两个模块(,“,读取并确认文件名,”,模块和,“,格式化并显示字数统计,”,模块)具有通信性内聚。必须对它们做进一步分解,最后结果显示在图,5.22,中。全部,8,个模块拥有功能性内聚,在它们之间或者有数据耦合或者没有数据耦合。,图,5.20,数据流图:第一次求精,64,5.4,面向行为的设计,图,5.21,结构图:第一次求精,65,5.4,面向行为的设计,图,5.22,结构图:第二次求精,66,5.4,面向行为的设计,结构化设计完成后,下一步就是详细设计此处,只针对数据结构和算法,每个模块的详细设计交给程序员完成。,5.,例子的扩展,图,5.23,显示了具有多个输入流和输出流的数据流图。在这种复杂情况下进行数据流分析的方法是重复下面三个步骤,直至生成的模块具有高内聚。,找到每个输入流的输入最高抽取点。,找到每个输出流的输出最高抽取点。,使用这些最高抽取点分解数据流图。,如果得到的耦合太紧,调整设计。,67,5.4,面向行为的设计,图,5.23,具有多个输入流和输出流的数据流图,68,5.4,面向行为的设计,5.4.2,事务分析,事务,是从产品用户的观点来看一个操作,如,“,处理一个请求,”,或,“,打印一份今天订单的列表,”,。例如在实时系统
展开阅读全文