2019年12月19日第3章面向对象程序设计主讲教师:杨建军Talentscomefromdiligence,andknowledgeisgainedbyaccumulation.天才源于勤奋,知识源于积累。教学重点♣软件的需求定义♣软件系统设计♣软件系统实现♣软件测试♣软件维护6.1软件工程过程和软件的生命周期♣软件工程过程是指为获得软件产品,在软件工具支持下由软件工程师完成的一系列软件工程活动。不同的组织有不同的软件过程,这些活动可以重叠,执行时也可以有迭代。♣软件生存周期是指软件产品从考虑其概念开始到该软件产品交付使用,直至最终淘汰为止的整个过程,一般包括计划、分析、设计、实现、测试、集成、交付、维护等阶段。6.2软件的需求定义♣6.2.1系统可行性分析♣可行性研究的任务是系统分析员进行概要分析研究,初步确定项目的规模、目标、约束和限制,然后进行简要的需求分析,抽象出项目的逻辑结构,建立逻辑模型。从逻辑模型出发,经过快速原型设计,探索出若干种可供选择的解决方法,对各种解决方法都要研究它的可行性。主要从以下几个方面考虑:♣(1)技术可行性。一般考虑的情况包括:开发的风险即设计出的系统能否达到要求的功能和性能、资源的有效性、相关技术的发展是否支持。♣(2)经济可行性。进行开发成本的估算以及了解取得效益的评估,确定要开发的项目是否值得投资。♣(3)社会可行性。要开发的项目是否存在任何侵权问题,运行方式在拥护组织内是否可行,现有管理制度、人员素质、操作方式是否可行。♣(4)提出并评价实现的各种开发方案,选出最适合该项目的切实可行的方案。♣6.2.2软件开发计划♣软件开发计划的内容♣在进行了可行性研究之后,开发软件系统可行的话,接着要制定软件的开发计划。软件项目开发包括如下几个方面:♣①项目概述:说明项目的各项主要工作;说明软件的功能、性能;为完成项目应具有的条件;用户及合同承包者承担的工作完成的期限及其他条件限制;应交付的程序名称;所使用的语言及存储形式;应交付的文档。♣②实施计划:说明任务的划分,各个任务的责任人,项目开发的进度,项目的预算,各阶段的费用支出,各阶段应完成的任务,用图表说明每项任务的开始和完成时间。♣③人员组织及分工:所需人员类型、数量、组成结构。♣④交付期限:最后完工日期。♣归纳起来,关键问题就是软件的资源计划、成本预算和进度安排。♣6.2.3软件的需求分析♣软件需求分析工作是软件生存期中重要的一步,也是决定性的一步。通过软件需求分析,才能把软件功能和性能的总体概念描述为具体的软件需求规格说明,从而奠定软件开发的基础。软件需求分析工作也是一个不断认识和逐步细化的过程。整个过程将软件计划阶段所确定的软件范围(工作域),逐步细化到可详细定义的程度,并分析出各种不同的软件元素,然后为这些元素找到可行的解决方法。♣制定软件的需求规格说明不只是软件开发人员的事,用户也起着至关重要的作用。用户必须对软件功能和性能提出初步要求,并澄清一些模糊概念。而软件分析人员则要认真了解用户的要求,细致地进行调查分析,把用户“做什么”的要求最终转换成一个完全的、精细的软件逻辑模型并写出软件的需求规格说明,准确地表达用户的要求。6.3软件系统设计♣6.3.1软件概要设计概述问题定义、可行性研究和需求分析构成了软件计划阶段,在这个阶段确定了系统的开发目标和系统需求规格,而软件开发阶段的任务是回答系统如何实现的问题。软件开发阶段包括概要设计、详细设计、编码和测试等。♥概要设计阶段需要编写的文档有:概要设计说明书,初步的用户操作手册。♥概要设计的主要目标是把需求转换为软件的体系结构,而软件体系结构包括两部分:程序的模块结构和数据结构。♣6.3.2软件设计的基本原则♣在软件设计中,要遵循一些基本的软件设计概念与原则。这些概念与原则是经过多年的实践发展和总结出来的,它已成为软件设计人员完成复杂设计问题的基础。♣1.模块化与模块独立性♣模块是数据说明、可执行语句等程序对象的集合。模块可以被单独命名,而且可通过名字来访问,例如,过程、函数、子程序、宏等等都可作为模块。在面向对象的方法学中,对象和对象内的方法也是模块。在软件的体系结构中,模块是可组合、分解和更换的单元。模块是构成程序的基本构件。♣模块独立性是软件系统中每个模块只涉及软件要求的具体子功能。而和软件系统中其他的模块接口是简单的联系。例如,如果一个模块只具有单一的功能,并且与其他的模块没有太多的联系,则称此模块具有模块独立性。♣6.3.2软件设计的基本原则♣2.抽象与细化♣抽象是人类在认识复杂现象的过程中使用的最强有力的思维工具。抽象就是抽取出事物的本质特性而暂时忽略它们的细节。由于人类思维能力的限制,如果每次面临的因素太多,是不可能做出精确思维。处理复杂系统的惟一有效的方法是用层次的方式构造和分析它。因此在进行模块化软件设计时,可以在不同的抽象层次进行设计。在抽象的最高层次使用问题环境的语言,以概括的方式叙述问题的解法;在较低抽象层次采用更过程化的方法,把面向问题的术语和面向实现的术语结合起来叙述问题的解法;最后在最低的抽象层次用可直接实现的方式叙述问题的解法。♣细化实际上是一个详细描述的过程。在高层抽象定义时,从功能说明或信息描述开始。也就是说给出功能说明或信息的概念,而不给出功能内部的工作细节或信息的内部结构。♣6.3.2软件设计的基本原则♣3.信息隐藏♣信息隐藏是指在设计和确定模块时,使一个模块内包含的信息(过程和数据)对于不需要这些信息的模块来说,是不能访问的。也就是说,模块中所包括的信息不允许其他不需要这些信息的模块调用。隐藏意味着有效的模块化可以通过定义一组独立的模块而实现,这些独立的模块彼此间仅仅交换那些为了完成系统功能而必须交换的信息。隐藏并不是隐藏有关模块的一切信息,而是模块的实现细节。通过抽象,可以确定组成软件的过程实体;而通过信急隐藏,则可以定义和实施对模块的过程细节和局部数据结构的存取限制。♣6.3.2软件设计的基本原则♣4.可重用♣现代的软件开发越来越重视生产率和质量,其中提高软件的可重用是一个重要的途径。所谓重用也叫再用或复用,是指同一事物不作修改或稍加改动就多次重复使用。软件复用的范围基本上可归纳为数据复用、模块复用、结构复用、设计复用和规格说明复用五个层次。♣6.3.3软件详细设计♣详细设计又称过程设计,在概要设计阶段,已经确定了系统的总体结构,给出系统中各个组成模块的功能和模块间的联系,详细设计就是要在概要设计的基础上,考虑“怎样实现”这个软件系统,直到对系统中的每个模块给出足够详细的过程性描述。需要指出,这些描述应该用详细设计的表达工具来表示,但它们还不是程序,一般不能够在计算机上运行。♣6.3.4软件详细设计表示方法♣在数据和程序结构建立以后,就可以进入详细设计。详细设计中应采用合适的方式来描述模块内问题解决过程的细节,采用结构化的图形设计表示法是人们易于使用、易于理解的方式。♣常用的图形设计表示法有流程图、盒图等。6.4软件系统实现6.4.1程序设计语言的特征和选择1.程序设计语言的特征程序设计语言有三个特性,它们是:心理特性、工程特性和技术特性。♥2.程序设计语言的选择♥总的来说,高级语言明显优于汇编语言。因此,除了在很特殊的应用领域,或者大型系统中执行时间非常关键的(或直接依赖于硬件的)一小部分代码需要用汇编语言书写之外,其它程序应该用高级语言书写。♣6.4.2程序设计风格♣程序设计风格就是编写程序时所表现出的特点、习惯和逻辑思路。主导的程序设计风格:清晰第一、效率第二。♣形成良好的程序设计风格,应考虑以下因素:源程序的文档化、数据说明方法、语句的结构、输入和输出、效率。6.5软件的测试♣软件测试就是在软件投入运行或发布前,对软件需求分析、设计规格说明和编码进行最终复审的活动。软件测试的目的是为了检验软件系统是否满足需求。♣从用户的角度来看,普遍希望通过软件测试暴露软件中隐藏的错误和缺陷,所以软件测试应该是“为了发现错误而执行程序的过程”。或者说,软件测试应该根据软件开发各阶段的规格说明和程序的内部结构而精心设计一批测试用例(即输入数据及其预期的输出结果),并利用这些测试用例去运行程序,以发现程序错误或缺陷。♣6.5.1软件测试技术分类♣软件测试的分类方法多种多样,以下的分类仅供读者参考。关键是应该理解每一种测试的功能、意义及适用范围,以便在实际的测试中加以恰当的选择。♣(1)按测试步骤与策略来分:单元测试、集成测试、确认测试、系统测试、Alpha测试和Beta测试。♣(2)按测试技术来分:白盒测试与黑盒测试。♣(3)按测试的环境来分:静态分析与动态测试。♣(4)按测试的功能来分:配置测试、兼容性测试、语言测试、易用性测试、文档测试、特殊测试等。♣6.5.2测试用例♣任何软件的测试都必须是有计划、有组织的,不能是随意的。软件测试计划就是组织调控整个测试过程的指导性文件。在软件测试计划中有一个重要的组成部分就是测试用例的说明。所谓测试用例是为某个测试目标而编制的一组测试输入、执行条件以及预期结果的方案,以便测试某个程序路径或核实是否满足某个特定需求。♣6.5.36.5.3调试♣1.调式方法♣测试本身的目的是尽可能多地暴露程序中的错误,发现错误的最终目的还是为了改正错误。软件工程的根本目标是以较低的成本开发出高质量的完全符合用户要求的软件。因此在成功的测试之后,还必须进一步诊断和改正程序中的错误,这就是调试的任务。调试是软件开发过程中最艰巨的脑力劳动。♣常用的一些调试方法有:输出存储器内容、适当插入打印语句、使用专门的调试工具♣6.5.3调试♣2.调试策略♣调试过程的关键不是调试技术,而是用来推断错误原因的基本策略。通常调试策略有四种。♣(1)试探法♣调试人员分析错误征兆,猜测故障的大致位置,然后使用前述的某种调试技术,获取程序中被怀疑的地方附近的信息,这种策略效率极低。♣(2)回溯法♣调试人员检查错误征兆,确定最先发现“症状”的地方,然后人工按照程序的控制流往回追踪程序代码,直到找出错误的根源或确定故障范围为止。也可以正向追踪,使用输出语句检查一系列中间结果,确定最先出现错误的地方。回溯法对小程序而言是一种比较好的调试策略,往往可把故障范围缩小,但随着程序规模的扩大,应用回溯的路径数目也变得越来越多,彻底回溯将是不可能的了。♣(3)归纳法♣归纳法是一种系统化的思考方法,从个别到一般,从错误征兆出发,通过分析这些线索之间的关系找出故障。这种方法的主要步骤如下。♣(4)演绎法♣从一般原理或前提出发,经过删除和精化推导结论。开始先列出所有看来可能成立的原因和假设,然后一个一个地排除列举出的原因,最后剩下的原因是错误的根源。6.6软件维护♣6.6.1软件维护的定义和特点♣任何软件在交付使用之后,由于本身潜在的错误或者满足新的需求,都需要对软件进行维护。♣1.软件维护的定义♣国标GB/T11457-89对软件维护给出了如下两个定义:♣(1)在软件产品交付使用后对其进行修改,以纠正故障。♣(2)在软件产品交付使用后对其进行修改,以纠正故障,改进其性能和其他属性,以使产品适应改变了的环境。♣2.软件维护的特点♣我们把为了改正软件系统中的错误,使软件能够满足预期的正常运行状态的要求而进行的维护叫做改正型维护,随着计算机科学技术领域的各个方面都在迅速的进步,特别是80年代之后,大约每过36个月就有新一代的硬件宣告出现,经常推出新的操作,软件驱动的外围设备的增加或者发生变更时所做的软件维护,我们称适应型维护。当一个软件顺利地进行时,常常会出现第三项维护的活动:在维护的使用过程中用户往往会提出增加新功能或修改已有功能的建议,还有可能提出一些改进的意见,为了满足这类要求,需要进行完善型的维护,据统计,这类维护活动通常占软件维护的一半左右。为了改进软件执行效率,提高可靠性和可维护性而进行的维护,是第四项维护的内容,第四项维护的活动在我们现代的软件业中是很少的♣6.6.2软件维护的实施♣首先的工作是要建立一个机构,对每一个维护申请写出报告并对其过程进行评价,而