




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第3章
面向对象的软件构造第3章面向对象的软件构造学习如何运用面向对象的软件构造技术管理和控制软件的复杂性。继续探讨分解和模块化,学习把抽象和封装的原则表示成数学模型——抽象数据类型,用面向对象方法实现。通过面向对象的设计,理解软件设计及其原则和设计模式。学习调试技术和工具,并初步学习自动化测试框架。2016秋数据科学与软件工程学院2第3章面向对象的软件构造故事4小强离校外出实习,找好友小雨帮忙,并告诉了华经理。小雨刚刚学完面向对象技术,正想练习一下,就参考小强的描述和程序,重新编写了程序。2016秋数据科学与软件工程学院3第3章面向对象的软件构造随着要解决的问题及其程序变得越来越复杂,程序不断增大,在编码前考虑如何运用良好的原则把程序功能(用户需求)分解到模块,考虑各个模块之间的交互、每个模块的数据结构与算法等,称之为设计(动词),结果称为方案或设计(名词),这个开发活动的重要性凸现。2016秋数据科学与软件工程学院4第3章面向对象的软件构造模块化是在函数级,通过函数间的交互表示程序结构、分配程序功能,暂时忽略了函数的内部实现。面向对象技术把数据及其操作封装在一个对象中,并把具有相同属性(数据名称)和方法(函数)的所有对象抽象成类,使得能在比函数更抽象、更大程序单元粒度的层次上进行软件开发。2016秋数据科学与软件工程学院5第3章面向对象的软件构造传统设计工程的目标是创作出坚固、适用和赏心悦目的模型或设计表示。坚固或称为可靠,是指程序不含任何妨碍其功能的缺陷。适用指满足用户需求,符合程序的开发目标。赏心悦目则是指程序具有友好的界面,使用程序的快乐体验。为此,设计师必须首先获得多种设计信息和方案,然后将其汇聚,从中精心挑选各种设计元素、得到某种特定的配置,最终形成满足设计目标的产品或系统的设计。2016秋数据科学与软件工程学院6第3章面向对象的软件构造软件设计的多样化和聚合需要直觉和判断力,其质量取决于构造类似实体的经验、一系列指导面向演化的原则和启发、一系列质量评价标准及最终设计的表示的迭代过程。软件设计在开发过程中处于技术核心,它使用的技术与软件过程无关。软件设计是软件建模的最后一个活动,接着进入构造阶段。软件工程的一个独特性是从分析到设计、从设计到程序的变迁。2016秋数据科学与软件工程学院7第3章面向对象的软件构造3.1抽象与封装3.2认识面向对象3.3面向对象的设计3.4调试的基本技术3.5软件自动化测试3.6案例分析与实践3.7讨论与提高3.8思考与练习题2016秋数据科学与软件工程学院83.1抽象与封装3.1.1模块产生与合成3.1.2抽象与封装3.1.3抽象数据类型2016秋数据科学与软件工程学院93.1.1模块产生与合成2016秋数据科学与软件工程学院103.1.1模块产生与合成函数簇包含了对核心数据的产生、变更和使用的操作函数。函数簇与其之外的其他函数通常不能产生、变更函数簇内的核心数据,仅仅使用。从模块化理解,一个函数簇实现了一组围绕核心数据的功能,具备通信内聚和功能内聚,属于强内聚。函数簇其他函数、函数簇、模块的连接方式主要是数据的传递及对理解函数簇数据的函数的调用。2016秋数据科学与软件工程学院113.1.1模块产生与合成局部化,是实现模块化的一种重要机制。如函数和复合语句的内部变量函数调用可以视为模块组合的一种机制。通过函数调用把函数联系起来,构成更大规模的程序。2016秋数据科学与软件工程学院123.1.1模块产生与合成数据结构,如数组或C的结构体为组成更大、更复杂的数据提供了构建具有层次结构的组织方式。单纯的数据结构不含对数据的操作,也不能保护其中的数据元素。可以在数据结构和数据类型的基础上实现模块化机制,这就需要抽象与封装。2016秋数据科学与软件工程学院133.1.2抽象与封装抽象是指对于一个过程或一件事物的某些细节有目的地隐藏,以便把其他方面、细节或结构表达得更加清楚。抽象是从众多的事物中抽取出共同的、本质性的特征,而舍弃其非本质的特征。抽象的目的是通过把相关的属性和其他不相关的属性分开,分离关注点。抽象是处理复杂问题的一个手段。抽象是分离对象特性、限制对它们在当前环境关注的一个机制。2016秋数据科学与软件工程学院143.1.2抽象与封装如,教学管理系统,把学生抽象成符号串(姓名、学号、学院、专业、课程)、数字(出生日期、课程成绩)等用数据类型或数据结构表示的属性;查找一个学生的信息通过一个检索函数实现,使用者不必关心使用了什么检索方法。又如,对口算题进行了抽象,是有两个运算数、一个运算符及一个运算结果的符号串或数据结构,不考虑算式表示的涵义、物理属性、表现形式等。2016秋数据科学与软件工程学院153.1.2抽象与封装程序设计有两种抽象,分别是过程抽象(函数抽象)和数据抽象。过程抽象是在使用一个函数或方法时知道它干什么,而不知道它是如何完成的。数据抽象是将一个数据类型的特性(值及其运算)与其实现分离。在软件构造中,我们需要一种机制来实现抽象,呈现关注点,隐藏其他细节。2016秋数据科学与软件工程学院163.1.2抽象与封装封装有两个含义:①把描述一个事物的性质和行为结合在一起成为构件,对外形成该事物的一个界限,封装使构件能够集中而完整地对应并描述具体的事物,体现了事物的相对独立性;②信息隐蔽,即外界不能直接存取构件的内部信息(属性)及隐藏起来的内部操作,外界也不必知道操作的内部实现细节;信息隐藏强制封装。2016秋数据科学与软件工程学院173.1.2抽象与封装封装具有如下优势构件外部只能通过外部可用的操作来访问内部数据和操作,降低了构件间的耦合度。构件内部修改对外部的影响变小,减少了修改引起整个程序范围的“波动效应”。更容易快速开发正确的程序,一旦程序员们确定了构件间的交互,每个人都可以独立地开发和测试分配的构件。改善通用性和维护性。2016秋数据科学与软件工程学院183.1.2抽象与封装严格的封装也会带来诸如编程麻烦、执行效率的问题。有些语言不强调严格的封装和信息隐藏,而采取可见性控制来解决这些问题。例如,C++和Java语言通过定义对象的属性和操作的可见性,规定了其他对象对其属性和操作的可访问性;另外,一个对象也可以通过把相应的可见性指定为受保护的或私有的,而提供仅局限于特定对象的属性和操作。2016秋数据科学与软件工程学院193.1.2抽象与封装【例3.1】一个商店中可能有一个人负责货架(保管员),一个人负责进货(采购员)。对于保管员,货架是存放商品位置的抽象,只需关注货架的位置信息如行、列、层等,而不必关心货架的材质、色彩等。同样,采购员对饮料进行抽象,他只需知道饮料的名称、编码、价格、供应商等有关信息,而不必关心饮料容器的大小、材料、色泽等。而保管员则必须知道这些信息,以便把商品放到正确的位置。2016秋数据科学与软件工程学院203.1.2抽象与封装封装使得各行其责。当保管员注意到库存的饮料少了,只需通知采购员订货。保管员无须知道饮料的价格和来源。采购员也不关心饮料放在货架的具体位置。封装使得这些工作更加容易和安全。当然,保管员和采购员相互独立的职责有可能造成“采购员本周休假,饮料缺货”的情形;或者保管员不在,仓库有货却无法上架。2016秋数据科学与软件工程学院213.1.3抽象数据类型数据类型是一个值的集合和定义在值集上的一组操作的总称。明显或隐含地规定了数据的取值范围、存储方式及其运算。数据类型可分为:原子类型和结构类型。程序设计语言都提供了基本数据类型。每个数据都属于某种数据类型。对于复杂的信息,编程处理时仅仅使用基本数据类型是不够的。比如,可以把“学生”的取值集合与规定的一组操作定义成一种数据类型。2016秋数据科学与软件工程学院223.1.3抽象数据类型抽象数据类型(AbstractDataType,ADT)是一个数据模型及定义在该模型上的一组操作。定义一个ADT时,必须给出它的名字及各操作的名称,并且规定这些函数的参数性质。一旦定义了一个ADT及具体实现,程序设计中就可以像使用基本数据类型那样,十分方便地使用ADT。学生ADT,包含各种属性及取值范围;还有一组操作,如按照不同属性查询学生的信息、更改一些信息。2016秋数据科学与软件工程学院233.1.3抽象数据类型一个程序员定义的ADT要通过高级编程语言中已有的数据类型和数据结构来实现。利用基本的数据结构可以构造一些复杂的数据结构,如栈、队列、树、图等,对数据集进行抽象而不必让使用者(程序员)关心实际数据的存储细节(ADT的数据结构)。2016秋数据科学与软件工程学院243.1.3抽象数据类型【例3.2】一个ADTStack提供如下操作。Stack():创建一个新的空栈;push(item):把参数item放在栈顶;pop():把栈顶元素从栈中移出并返回,若栈为空,则出错;top():返回栈顶元素,但不移出,若栈为空,则出错;isEmpty():若栈为空,返回真值,否则,返回假值;size():返回栈的元素的个数。2016秋数据科学与软件工程学院253.1.3抽象数据类型无论如何实现该栈,它只提供这6个操作,除此之外没有其他操作。使用者不知道、也不必关心它是用数组、还是通用表等基本类型实现的。2016秋数据科学与软件工程学院263.1.3抽象数据类型ADT的定义与其实现分离,使其用户只需关注如何使用,而不是它的实现细节。这种分离要求与ADT的交互使用接口(定义的操作集)。通过封装实现细节,要求通过接口访问ADT,使得我们能使用抽象进行工作,专注ADT提供的功能,而不必理解这些功能的实现。2016秋数据科学与软件工程学院273.1.3抽象数据类型【例3.3】第2章把Equation当成一个整体。如果Equation的定义包含运算结果value,按照ADT的概念,value是Equation的一个成员,使用Equation的程序(函数)是不允许访问它的。但C可以通过equation.value访问,包括更改它的值。这样,就会导致equation的不一致:算式实际的运算结果与存放结果value的值不一样。所以在定义类型Equation时没有包含它的运算结果,而是用一个函数动态地计算,才能使得一个算式保持一致。但是,这个计算显然要占用资源。而且,在使用一个算式值时不能忘记这个计算函数。2016秋数据科学与软件工程学院283.1.3抽象数据类型面向对象为实现ADT提供了良好的机制。类:ADT的一种实现方式。加上继承、聚合、多态等特性,不仅提高了软件开发效率,还能提高软件产品的质量,使得面向对象的程序设计获得普遍应用。面向对象语言提供了良好的编程机制,但语言本身并不能保证开发出高质量程序,因而还需要学习和运用设计、编码、测试等软件构造的基本原理,更好地运用面向对象语言的特性来构造出高质量的程序。2016秋数据科学与软件工程学院293.2认识面向对象面向对象技术包括软件开发方法和程序设计语言,在传统面向过程程序设计语言、结构化设计方法的基础上做出了改进,并在软件开发、编程语言方面提出了新的理论和实践。3.2.1设计类3.2.2设计操作3.2.3分类2016秋数据科学与软件工程学院303.2.1设计类用面向对象开发软件时,我们把系统模块化成类,它们封装了属性及其操作。决定一个类知道什么、做什么,就是抽象出一个类。在设计一个类如何做事情时,就是把它们封装起来。良好设计的类限制访问它的属性及其操作,实质上就是隐藏了信息及其处理。2016秋数据科学与软件工程学院313.2.1设计类抽象是设计类的基本方法。抽象是在某个东西周围画上一个白盒子的动作:识别出它做什么、不做什么。抽象是对某个东西定义接口的动作。抽象告诉我们存储学生的姓名、学号,也能让学生选课。但是,抽象不告诉我们是如何做到这些的。2016秋数据科学与软件工程学院323.2.1设计类封装则处理如何将这些特性模块化。封装解决的是如何划分一个系统的功能的设计问题。封装是在某个东西周围画上一个黑盒子的动作:它明确某事能完成,但是不告诉是怎样做到的。换句话说,封装对类的使用者隐藏了实现细节。为了使应用程序容易维护,要限制访问类的数据和操作。2016秋数据科学与软件工程学院333.2.1设计类模块化原则——紧内聚、松耦合仍然适用于评价面向对象程序。包括类的内聚、方法的内聚;不同类之间的耦合、同一个类不同对象之间的耦合及同一个类内函数之间的耦合。类的模块化准则要求一个类应当是完整的原始的充分的2016秋数据科学与软件工程学院343.2.2设计操作类的设计要尽量使其所有的操作都是原始的,每个操作仅提供简单、良好定义的行为。根据松散耦合的原则,也倾向于分离操作、减少它们之间的沟通。矛盾:把复杂的行为集中在一个方法中,简化了接口,但其实现复杂了;反之,方法行为和实现简单了,但方法多了,接口复杂了。2016秋数据科学与软件工程学院353.2.2设计操作通常在面向对象开发中,把类的方法作为整体来设计,这是因为所有这些方法的合作构成了抽象的全部协议。设计时考虑以下建议。复用:这个行为在更多的环境中更有意义吗?复杂:实现这个行为有多难?适应:这个行为与其置身的类有多少关系?实现知识:实现这个行为要依赖于类的内部细节吗?2016秋数据科学与软件工程学院363.2.2设计操作多态多态是类型理论的一个概念,一个名字可以表示多个不同类的实例,只要它们具有某个共同的超类而且相关。所以,被这个名字表示的任何对象都能以不同的方式对一组某些相同的操作做出响应。由于多态,一个操作就能在层次结构中的所有类以不同方式实现。这样,子类就能扩展超类的能力或者覆盖超类的操作。2016秋数据科学与软件工程学院373.2.2设计操作很多类具有相同协议时,多态最有用。如果没有多态,程序中会出现大量的if或switch语句。【例3.4】一个几何图形类Geometry有子类Rectangel、Segment、Triangle和Circle,显示图形的抽象方法display,每个子类都有自己的实现。2016秋数据科学与软件工程学院383.2.2设计操作当一个图形编辑GraphicsEditor要显示一个Geometry对象时,不用多态的代码结构可能是:2016秋数据科学与软件工程学院393.2.2设计操作如果使用多态,则代码精简:新增一个子类Polygon,要重新实现display,无须改变程序的其他部分,尤其不用改变使用Geometry的GraphicsEditor。2016秋数据科学与软件工程学院403.2.3分类关键抽象是构成问题域术语的一个类或对象。其主要价值在于识别确定问题边界的抽象,指出在系统中出现的问题相关的类(领域类)、因而与设计相关的事情。机制用于描述通过对象的协作提供满足问题需求的某种行为的任何结构。因为类的设计具体表达了单个对象行为的知识,机制就是一个关于一组对象如何协作的设计决策。机制就是行为模式。2016秋数据科学与软件工程学院413.2.3分类分类是对整理知识的一致手段。识别类和对象是面向对象开发的一个挑战。识别包含发现和发明。通过发现,我们认识到构成问题域词语的关键抽象和机制。通过发明,设计出一般化的抽象和机制,说明对象是如何协作的。发现和发明都是分类问题,其核心就是发现问题的共性。分类就是试图把具有共同结构或表现出共同行为的事情分为一组。2016秋数据科学与软件工程学院423.2.3分类1.类之间的关系在类之间建立关系的原因,首先是一种类关系会指出某种共享。其次,一种类关系会指出某种语义联系。面向对象中有三种类关系。普通与特殊(继承),即“是一种”。例如,加法算式是一种二元算式。整体-部分(聚合),即“是成员”。例如,算式是习题的一部分。关联,表示没有其他关系的类之间的某种语义依赖。如,“学生”和“教师”是两个独立的类,但是它们都和“课程”相关。2016秋数据科学与软件工程学院433.2.3分类面向对象软件还有一种常见的关系——依赖。依赖表示关系一端的成员以某种方式依赖于关系另一端的成员。它告诉开发者,如果这些元素发生变化,会影响其他成员。例如,以几何图形的显示display为例,除了显示图形的形状,还可以显示图形的颜色和线条,类Geometry则依赖类Color和Style(粗细、实线、虚线)。2016秋数据科学与软件工程学院443.2.3分类2.接口与实现Meyer认为程序设计本质上是契约:一个较大问题的功能通过把它们分包到不同元素的设计,而分解成若干较小的问题。类的内部和外部视角。类的接口提供了外部视角,重在抽象,同时隐藏了它的结构和组成。接口主要包括声明。类的实现是其内部视角,包含其行为,主要由所有定义在类接口操作的实现组成。2016秋数据科学与软件工程学院453.2.3分类类的接口可以进一步分成4类。公共的:对所有用户可访问的声明;保护的:仅允许类本身及其子类访问的声明;私有的:仅允许类本身访问的声明;包:仅允许和类在用一个包的声明。接口是一些面向对象语言的基本元素,如Java语言的接口Interface,必须有具体的类才能实现接口定义的操作。2016秋数据科学与软件工程学院463.3面向对象的设计本节由浅入深地讨论如何运用面向对象的原则和原理设计并开发良好的程序。初步识别出两个类,分别是加减法的二元运算的算式及存放算式的练习,分别命名为算式类BinaryOperation和习题类Exercise。3.3.1面向对象的设计符号3.3.2案例设计一3.3.3案例设计二2016秋数据科学与软件工程学院473.3.1面向对象的设计符号软件设计语言或符号,如可视化图形设计符号。在面向对象设计中,普遍采用的包括描述程序静态结构的类图、描述程序动态行为的交互图。它们掩藏了类中方法的实现细节,突出了类的组成和类之间的关系,简洁清晰地表达设计意图和内容。复杂的算法、数据结构等操作的实现,仍然使用代码和伪代码补充说明。2016秋数据科学与软件工程学院483.3.1面向对象的设计符号统一建模语言UML类图类用一个带有类名、属性和操作的矩形表示。分隔线用来分离类名、属性和操作。类名在矩形的最上方,其次是属性,然后是操作。类名:具体类的名称正常书写;抽象类名加abstract前缀,或用斜体书写;接口名加前缀interface,属性空着。2016秋数据科学与软件工程学院493.3.1面向对象的设计符号属性类似程序语言的声明——可见性、变量名、类型、初始值;前缀表示可见性:“+”公用,“−”私有,“#”保护。静态变量或常量用大写字母的标识符,成员变量允许具有初始值。操作用签名表示——可见性、返回类型、操作名称、参数及类型,可见性符号与属性的相同。2016秋数据科学与软件工程学院503.3.1面向对象的设计符号2016秋数据科学与软件工程学院513.3.1面向对象的设计符号为了表示程序中类之间的关系,可以只用一个标示类名的矩形表示类。2016秋数据科学与软件工程学院523.3.1面向对象的设计符号类之间的关联用一根线表示,包括每个关联类的角色名、数目、方向和约束。泛化是一端带空心三角形的连线,从子类到父类,空心三角形一端是父类。聚合用来描述一个元素(整体)包含另外的元素(部分),部分可以脱离整体作为一个独立的个体存在。聚合的整体端用空心菱形表示。组合是一种语义更强的聚合,部分组成整体,不可分割,整体消失部分也跟着消失,部分不能脱离整体而单独存在。组合的整体端用实心菱形表示。2016秋数据科学与软件工程学院533.3.1面向对象的设计符号图3.3表示设计的解释:机械工程师、电气工程师和软件工程师都属于员工,他们组成一个飞机建造团队。飞机由零件组成,零件还可以(递归)有零件。UML不仅能使软件建模可视化,还有助于分析、评估和验证软件设计,支持从UML自动产生部分代码,指导产生测试用例。2016秋数据科学与软件工程学院543.3.2案例设计一1.算式类BinaryOperation2016秋数据科学与软件工程学院553.3.2案例设计一2.习题类Exercise2016秋数据科学与软件工程学院563.3.3案例设计二1.算式类BinaryOperation软件设计中的单一职责原则(SingleResponsibilityPrinciple,SRP)是最容易理解和运用的。单一职能原则实际上是内聚原则在面向对象方法中的具体表现,含义是就单个类而言,应该只有一个引起它变化的原因。2016秋数据科学与软件工程学院573.3.3案例设计二类BinaryOperation把其中的公共部分抽象出来,把差异部分细化成BinaryOperation的两个子类:加法算式AdditionOperation减法算式SubstractOperation每个类只负责完成各自单一的功能,两个子类相互独立。这样的程序结构还便于程序扩展,如增加乘法、除法子类,不影响已经存在的类。2016秋数据科学与软件工程学院583.3.3案例设计二里氏代换原则(LiskovSubstitutionPrinciple,LSP)是设计类层次结构的基本原则,它要求子类型必须能够替换其基类型。使用里氏代换原则的两个要点如下。(1)子类的所有方法必须在父类中声明,或子类必须实现父类中声明的所有方法。(2)尽量把父类设计为抽象类或接口,让子类继承父类或实现父接口,并实现在父类中声明的所有方法。2016秋数据科学与软件工程学院593.3.3案例设计二基类BinaryOperation设计成抽象类。子类AdditionOperation和SubstractOperation在基类中定义抽象方法intcalculate()返回运算式的计算结果,抽象方法booleancheckingCalculation()检查运算结果。具体实现则分别在两个子类中。2016秋数据科学与软件工程学院603.3.3案例设计二2016秋数据科学与软件工程学院613.3.3案例设计二2.抽象类abstract类和接口interface的比较2016秋数据科学与软件工程学院623.3.3案例设计二3.依赖倒转原则子类必须实现抽象父类定义的抽象方法才能生成对象,即低层的子类依赖高层的、抽象的父类。这种设计思想运用了面向对象技术中的依赖倒转原则(DependencyInversionPrinciple,DIP),它转换了依赖关系:高层模块不依赖于低层模块,两者都依赖于抽象。抽象不依赖于实现,实现依赖于抽象。换言之,就是高层模块定义接口,低层模块负责实现。“上转型对象”是面向对象方法中实现依赖倒转原则的有效技术。2016秋数据科学与软件工程学院633.3.3案例设计二4.习题类Exercise按照单一职责原则,把类Exercise的产生职责和使用职责分离出来,使类Exercise仅仅作为一个存储和管理一定数量的算式题的数据集容器,同时建立一个使用习题的新类ExerciseSheet。两个类之间是依赖关系:ExerciseSheet按照Exercise提供的方法使用它,当然受其影响。2016秋数据科学与软件工程学院643.3.3案例设计二在面向对象中,依赖关系可以视为具有特殊语义的关联。UML类图用带箭头的虚线连接两个有依赖关系的类:虚线起端表示使用、受影响的类,带箭头的末端表示产生影响、被使用的类。2016秋数据科学与软件工程学院653.3.3案例设计二2016秋数据科学与软件工程学院663.3.3案例设计二5.数据集的数据结构ExerciseSheet无法访问类Exercise中存放算式的私有成员operationList。为了能让其他对象使用Exercise中存储在Array中的算式,它必须提供公共操作,如检索、遍历等。类Exercise可以选择其他数据集的数据结构,存放算式。面向对象语言的容器型数据结构,如List、Queue、Stack等。Java语言的Collection(C#的ICollection)类层次结构提供了丰富的管理数据集的数据结构、接口和(抽象)类。2016秋数据科学与软件工程学院673.3.3案例设计二策略1:实现接口。队列Queue的操作如contains、isEmpty、iterator等,完全满足案例目前对Exercise的要求,可以让Exercise实现接口Queue。在Java中使用队列Queue,除了要实现这4个方法以外,还必须实现Queue及其继承的所有其他所有方法,否则不能构造对象实例。这违背了接口隔离原则(InterfaceSegregationPrinciple,ISP),根据该原则,不应该强迫客户程序依赖于它们不用的方法2016秋数据科学与软件工程学院683.3.3案例设计二策略2:运用继承。让Exercise继承容器数据结构中的一个,如具有动态改变容器数量的ArrayList。ArrayList可以视为动态数组,即数组大小随需增长。它提供了普通数组的操作,如按下标添加、插入、查询、删除及迭代遍历数据成员等方法,涵盖了Exercise的设计要求。但这个设计策略暴露了存储算式的内部数据结构,因而违背了信息隐藏的基本原则。另外,同接口一样,不能选择性地继承操作或属性,子类Exercise继承了一些不需要的操作。2016秋数据科学与软件工程学院693.3.3案例设计二策略3:封装结构。Exercise定义容器类数据结构(如Array、ArrayList、Queue、List)为私有成员变量封装,Exercise提供访问的next、hasNext等方法,以便ExerciseSheet能够实现遍历等操作。不同的应用需要Exercise提供的操作可能不完全一样。例如,目前不需要从练习中删除运算题,就可以不实现删除操作。而且,不同的容器类数据结构,如Array和ArrayList,对这些操作的实现也不同。ArrayList能提供包含上述要求的操作,甚至更多、更方便。2016秋数据科学与软件工程学院703.4调试的基本技术在Eclipse中,Java视图中选择要调试的函数/类右击,选择debugas→JavaApplication,出现debug视图。2016秋数据科学与软件工程学院713.4调试的基本技术启动调试程序的两种方式:(1)选择菜单Run→DebugAs;(2)选择debug的图标。使用调试器调试程序的基本模式如下:首先设置(若干)断点,启动运行调试器;遇到一个断点后停下,单步调试一段代码,可以检查、改变断点的程序状态和行为。然后恢复,让调试器继续执行程序,直到遇到下一个断点或执行到程序的结束。调试可在任何时刻终止。2016秋数据科学与软件工程学院723.4调试的基本技术3.4.1单步调试源程序3.4.2检查/更改变量的值3.4.3设置监视点观察变量3.4.4上下移动调用栈2016秋数据科学与软件工程学院733.4.1单步调试源程序1.设置断点在要检查的语句上设置断点,程序执行到断点处会暂停。通过窗口观察此刻变量的值、检查程序运行情况;可以输入改变变量或表达式的值,然后让程序继续运行。Eclipse中在代码行左边的页边空白处双击设置断点。2016秋数据科学与软件工程学院743.4.1单步调试源程序2.单步调试利用单步命令,从断点处开始一次处理一条语句。变量值有助于程序员仔细观察程序的执行流程、了解程序变量值的变化、调查可疑代码。在debug视图中有三种方式执行视图中的图标右击出现的选择(含图标)快捷键2016秋数据科学与软件工程学院753.4.1单步调试源程序单步调试的主要操作StepInto,F5,进入方法内部。StepOver,F6,执行方法下一条语句。StepReturn,F7,从当前方法跳出,跳转到该方法的结尾代码处。Resume,F8,恢复操作。跳出单步调试方式,让程序继续运行到下一个断点或执行完。DropToFrame,使调试器重新跳到当前方法的开始处重新执行,所有上下文变量的值也恢复。可以在关注的状态下反复调试,而不用重新启动调试器。2016秋数据科学与软件工程学院763.4.1单步调试源程序3.临时断点有时需要在显示的代码中临时设置有期限的断点,以便细致观察程序。在Eclipse中,突出显示源码窗口中要设置临时断点的代码行,然后右击并选择RuntoLine。2016秋数据科学与软件工程学院773.4.2检查/更改变量的值当调试器暂停了程序运行后,可以执行一些调试命令来显示、改变程序变量的值。不使用调试器,在程序中增加打印语句显示程序变量值的变化也可以。在图(a)选中变量右击选ChangePrimitiveValue,出现图(b)所示的对话框。2016秋数据科学与软件工程学院783.4.3设置监视点观察变量监视点(watchpoint)结合了断点和变量检查的概念。每当指定变量的值发生变化时,都暂停程序的运行。监视点对局部变量的用途一般没有对作用域更宽的变量的用途大,因为一旦变量超出作用域(如函数结束),在局部变量上设置的监视点就会被取消。main()中的局部变量例外,因为其中的变量要等到程序执行结束时才会被释放。2016秋数据科学与软件工程学院793.4.3设置监视点观察变量在Eclipse中设置监视点的方法:在源码窗口中右击,选择Watch,然后在对话框中填写适当的表达式,如图3.11所示。代码的执行结果将显示在表达式窗口中。选中一句或一段代码右击,选择Inspect(检查)项,可以直接显示表达式的值。2016秋数据科学与软件工程学院803.4.4上下移动调用栈与函数关联的运行时信息存储在称为帧的内存区域中。帧中包含了函数局部变量的值、形参,以及调用该函数的位置。系统为每个调用函数创建一个帧,并将其放在一个运行栈上;运行栈最上面的帧表示当前正在运行的函数,当函数退出时,这个帧就退出运行栈并释放所占的内存。运用调试器可以观察运行栈,追踪函数之间的调用关系和变量值的来源、变化等信息。Eclipse中,运行栈在debug透视图本身连续可见。2016秋数据科学与软件工程学院813.5软件自动化测试合适的测试工具和构建工具,可以提高构建效率,是现代软件开发的基础。JUnit已经成为现代软件开发方法和工具的核心组成。它是Java语言的测试框架,是包含测试用例、测试执行、测试记录等一组Java类和接口。JUnit由于简单、实用、易用,特别适合自动化的单元测试和回归测试。2016秋数据科学与软件工程学院823.5软件自动化测试3.5.1初识Junit3.5.2编写Junit测试代码2016秋数据科学与软件工程学院833.5.1初识Junit使用JUnit进行测试的基本步骤如下。(1)建立测试类,命名规则:待测类名+Test,如BinaryOperationTest。在该类的前面用@RunWith指定测试运行器,默认JUnit4。(2)在用@Before注解的setUp()中为测试做必要准备(测试装置fixture)。(3)为待测类的成员方法/函数编写测试方法,命名规则:test+待测方法,以@Test注解这个待测方法,其中务必包含测试断言。(4)运行测试,查看运行结果,更改代码。(5)增加方法或修改代码时,重复(3、4)。2016秋数据科学与软件工程学院843.5.2编写Junit测试代码1.基本测试2.追踪失败的测试2016秋数据科学与软件工程学院853.6案例分析与实践3.6.1分析3.6.2构造2016秋数据科学与软件工程学院863.6.1分析构造任务3.1:实现BinaryOperation及其子类。构造任务3.2:实现Exercise和ExerciseSheet。开发方式(1)顺序,即完成子任务1的程序后开始2;(2)并行,同时开始子任务1和2的编程。在子任务2编程期间,可以使用简单的算式类代替BinaryOperation,最后再用编写好的BinaryOperation替换,完成整个任务。2016秋数据科学与软件工程学院873.6.1分析小强和小雨俩人的合作方式可以是:(1)两人分别执行一个子任务;(2)两人协作执行一个子任务——一个人编写程序,另一个人设计测试,等程序完成了就立刻执行测试;整个开发期间两人可以交换工作。合作方式(2)蕴含了敏捷开发方法中两种实践的基本思想——测试驱动开发与结对编程。2016秋数据科学与软件工程学院883.6.2构造2016秋数据科学与软件工程学院893.7讨论与提高3.7.1对调试的进一步认识3.7.2设计原则与设计模式3.7.3面向对象的设计原则2016秋数据科学与软件工程学院903.7.1对调试的进一步认识1.调试与测试调试与测试都分析程序代码、选择性地运行程序,并观察程序的结果或运行过程。测试与调试的目标不同,采用了不同的技术、方法和工具。在软件构造过程中,开发者交替进行测试与调试:测试发现程序可能存在错误,然后通过调试来修改错误,之后再通过测试确认程序错误得到了修改。2016秋数据科学与软件工程学院913.7.1对调试的进一步认识2.不调试就是最好的调试精通程序调试不仅要掌握专门的调试器,还要充分利用其他编程辅助工具。最好的调试方法就是一开始就不要错误地编程!首先,要熟练掌握编辑器的使用。充分利用支持编程语言的编辑器是最容易忽略的“预调试”方式。其次,充分利用编译器。第三,使用静态代码检查器。3.调试的智力活动2016秋数据科学与软件工程学院923.7.2设计原则与设计模式面向对象技术在软件开发过程中出现了一些可反复使用、解决实际问题的解决方案,称为设计模式。一个设计模式针对一个具体问题,用抽象方式描述解决一类特殊问题的、通用的设计方案元素。设计模式的核心元素包括:标示模式的名称,适用环境的场景,描述设计的模板。在面向对象技术中,用类图描述设计模式的结构,用交互图描述设计模式的行为。2016秋数据科学与软件工程学院933.7.2设计原则与设计模式1.策略模式(1)问题分析。算法多种多样、经常改变,其他类不使用的算法。如何在运行时根据需要透明地更改对象的算法?将算法与对象本身解耦,从而避免上述问题?(2)解决思路。使用一个抽象的策略算法,用子类继承这个公共的抽象类,定义一个个具体的策略算法,把它们封装起来,通过实现抽象类的抽象算法使它们可互相替换。该模式使得算法可独立于使用它的应用客户而变化和扩展。2016秋数据科学与软件工程学院943.7.2设计原则与设计模式1.策略模式(3)设计结构。2016秋数据科学与软件工程学院953.7.2设计原则与设计模式1.策略模式(4)模式特点。策略类及其子类提供了一系列可重用的封装算法,通过面向对象的多态、动态绑定技术,对象在运行时根据需要在各个算法之间进行切换。策略模式容易造成很多的策略类。(5)案例研究。策略类BinaryOperation包含两抽象方法calculate和checkingCalculation,两个实现具体策略的子类AdditionOperation和SubstractOperation分别实现了这两个方法。2016秋数据科学与软件工程学院963.7.2设计原则与设计模式2.迭代器模式(1)问题分析。在软件构建过程中要处理集合数据,集合对象的内部结构变化各异。对于这些集合对象,希望在不暴露其内部结构的同时,让外部客户代码透明地顺序访问其中的每个成员对象;同时也为同一种算法在多种集合对象上进行操作提供可能。(2)解决思路。提供一种方法有效地按顺序访问一个聚合对象中的各个成员对象,而又不暴露该聚合对象的内部表示。2016秋数据科学与软件工程学院973.7.2设计原则与设计模式2.迭代器模式(3)设计结构。2016秋数据科学与软件工程学院983.7.2设计原则与设计模式2.迭代器模式(4)模式特点。迭代抽象——访问一个聚合对象的内容而无须暴露它的内部表示。迭代多态——为遍历不同的集合结构提供一个统一的接口,从而支持同样的算法在不同的集合结构上进行操作。健壮性考虑——遍历的同时有可能更改迭代器所在的集合结构,导致问题。2016秋数据科学与软件工程学院993.7.2设计原则与设计模式2.迭代器模式(5)案例研究。①Java的CollectionsFramework是迭代器模式的典型实现。它的接口Collection和Iterator分别对应模式中的Aggregate和Iterator。②案例设计二中的策略3的封闭结构可以视为迭代器模式的(变形的)应用。Exercise封装了ArrayList,BinaryOperation是ArrayList泛型的具体类型。客户ExerciseSheet直接使
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 枣庄市精神卫生中心招聘笔试真题2024
- 2024年厦门市集美区蔡林学校招聘考试真题
- 2024年南平市武夷山职业学院招聘考试真题
- 临沂市平邑县事业单位招聘教师笔试真题2024
- 2024年甘肃特岗:甘肃特岗教师考试真题
- 食品博览会安全应急预案演练计划
- 2025年骨瓷餐具项目发展计划
- 2025年自动气体灭火系统项目发展计划
- 2025年毛球修剪器项目发展计划
- 2025年氨基比林项目合作计划书
- 五年级下册数学课件 -4.1 用数对确定位置 ︳青岛版 (共20张PPT)
- 柏拉图分析案例
- 岩棉项目申报书_参考模板
- 二衬带模注浆施工方案
- 施工组织设计方案交底记录
- 《英语委婉语与忌语》PPT课件.ppt
- ISO9001-14001-2015内部审核检查表
- 风险和机遇应对措施有效性评审记录表副本
- 调查问卷设计-课件PPT
- 照金参观学习心得
- 井下电缆着火应急演练预案
评论
0/150
提交评论