软件工程导论第12章
合集下载
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
7
5. 类型检查 弱类型语言:语言仅要求每个变量或属性隶属于一 个对象,如Smalltalk(实际是无类型语言(所有变 量都是未指定类的对象));用来快速开发原型。 强类型语言:语法规定每个变量或属性必须准确地 属于某个特定的类,如C++和Eiffel 。用来开发软 件产品。 强类型语言优点: 一、有利于在编译时发现程序错误, 二、增加了优化的可能性。有助于提高软件的可靠 性和运行效率。
25
12.2.3 提高健壮性
程序员在编写实现方法的代码时,既应该考虑效率, 也应该考虑健壮性。 为提高健壮性应该遵守以下几条准则。 1. 预防用户的操作错误 软件系统必须具有处理用户操作错误的能力。即使 发现了非常严重的错误,也应该给出恰当的提示信 息,并准备再次接收用户的输入。
26
2. 检查参数的合法性 对公有方法,尤其应该着重检查其参数的合法性, 因为用户在使用公有方法时可能违反参数的约束条 件。 3. 不要预先确定限制条件 在设计阶段,往往很难准确地预测出应用系统中使 用的数据结构的最大容量需求。因此不应该预先设 定限制条件。 4. 先测试后优化 为在效率与健壮性之间做出合理的折衷,应该在为 提高效率而进行优化之前,先测试程序的性能,经 过测试,合理地确定为提高性能应该着重优化的关 键部分。
12.2 程序设计风格
良好的程序设计风格对面向对象实现来说尤其重要, 不仅能明显减少维护或扩充的开销,而且有助于在 新项目中重用已有的程序代码。 面向对象程序设计风格,既包括传统的程序设计风 格准则,也包括为适应面向对象方法所特有的概念 (如继承性)而必须遵循的一些新准则。
15
12.2.1 提高可重用性
2
面向对象语言的优点: 1. 一致的表示方法 从问题域到OOA到OOD到面向对象编程(OOP)始 终稳定不变。既有利于在软件开发过程中始终使用 统一的概念,也有利于维护人员理解软件的各种配 臵成分。 2. 可重用性 软件开发组织既可能重用问题域内的OOA结果, 也可重用相应的OOD和OOP结果。
3
30
12.3.3 面向对象的确认测试
面向对象方法的主要目标:提高软件的可重用性。 编码阶段主要涉及代码重用问题。
16
有助于实现重用的程序设计准则: 1. 提高方法的内聚 一个方法(即服务)应该只完成单个功能。否则分解。 2. 减小方法的规模 代码长度超过一页纸可能就太大了,应该分解。 3. 保持方法的一致性 功能相似的方法应该有一致的名字、参数特征(包 括参数个数、类型和次序)、返回值类型、使用条 件及出错条件等。
18
5. 全面覆盖 如果输入条件的各种组合都可能出现,则应该针对 所有组合写出方法,而不能仅仅针对当前用到的组 合情况写方法。 例如,如果在当前应用中需要写一个方法,以获取 表中第一个元素,则至少还应该为获取表中最后一 个元素再写一个方法。 此外,一个方法不应该只能处理正常值,对空值、 极限值及界外值等异常情况也应该能够作出有意义 的响应。 6. 尽量不使用全局信息 尽量降低方法与外界的耦合程度,不使用全局信息 是降低耦合度的一项主要措施。
第12章 面向对象实现
把面向对象设计结果翻译成用某种程序语言书写的面向对象程序 +测试并调试面向对象的程序
12.1 12.2 12.3 12.4 12.5 习题
程序设计语言 程序设计风格 测试策略 设计测试用例 小结
1
12.1 程序设计语言 12.1.1 面向对象语言的优点
面向对象设计的结果可以用: 面向对象语言:编译程序可以自动把面向对象概念 映射到目标程序中。 非面向对象语言:由程序员自己把面向对象概念映 射到目标程序中。不支持一般-特殊结构的实现。 选择编程语言的关键因素,是语言的一致的表 达能力、可重用性及可维护性。
8
6. 类库 大多数面向对象语言都提供一个实用的类库。许多 软构件不必由程序员重头编写为实现软件重用带来 很大方便。 7. 效率 使用拥有完整类库的面向对象语言,有时能比使用 非面向对象语言得到运行更快的代码。
9
8. 持久保存对象 一些面向对象语言,没有提供直接存储对象的机 制。用户必须自己管理对象的输入输出,或者购买 面向对象的数据库管理系统。 另外一些面向对象语言(如Smalltalk),把当前的 执行状态完整地保存在磁盘上。 还有一些面向对象语言,提供了访问磁盘对象的 输入输出操作。 理想情况下,应该使程序设计语言语法与对象存储 管理语法实现无缝集成。
23
Leabharlann Baidu
12.2.2 提高可扩充性
上一小节所述的提高可重用性的准则,也能提高程 序的可扩充性。此外,下列的面向对象程序设计准 则也有助于提高可扩充性: 1. 封装实现策略 应该把类的实现策略(包括描述属性的数据结构、 修改属性的算法等)封装起来,对外只提供公有的 接口,否则将降低今后修改数据结构或算法的自由 度。 2. 不要用一个方法遍历多条关联链 一个方法应该只包含对象模型中的有限内容。违反 这条准则将导致方法过分复杂,既不易理解,也不 易修改扩充。 24
21
图2.2 通过因子分解实现代码重用
22
(3) 使用委托。 仅当确实存在一般-特殊关系时,使用继承才是恰 当的。当逻辑上不存在一般-特殊关系时,为重用 已有的代码,可以利用委托机制,见11.11.3小节。 (4) 把代码封装在类中。程序员往往希望重用用其 他方法编写的、解决同一类应用问题的程序代码。 重用这类代码的一个比较安全的途径,是把被重用 的代码封装在类中。 例如,在开发一个数学分析应用系统的过程中,已 知有现成的实现矩阵变换的商品软件包,程序员不 想用C++语言重写这个算法,于是他定义一个矩阵 类把这个商品软件包的功能封装在该类中。
27
12.3 测试策略
传统测试: 单元测试集成测试 确认测试系统测试。
测试面向对象软件的策略与上述策略基本相同, 但也有许多新特点。
28
12.3.1 面向对象的单元测试
最小的可测试单元是封装起来的类和对象。 一个类可以包含一组不同的操作,而一个特定的操 作也可能存在于一组不同的类中。测试面向对象软 件时,不能再孤立地测试单个操作,而应该把操作 作为类的一部分来测试。 例,假设有一个类层次,操作X在超类中定义并被 一组子类继承,每个子类都使用操作X,因此有必 要在每个子类的语境中测试操作X。
5
选择面向对象语言应该着重考察的技术特点:
1. 支持类与对象概念的机制 所有面向对象语言都允许用户动态创建对象,并 且可以用指针引用动态创建的对象。 2. 实现整体-部分(即聚集)结构的机制 两种实现方法: 指针:容易实现 独立的关联对象:(大多数现有的面向对象语言 并不显式支持独立的关联对象。
17
4. 把策略与实现分开 策略方法:负责做出决策,提供变元,并且管理全 局资源。 实现方法:负责完成具体的操作,但却并不做出是 否执行这个操作的决定,也不知道为什么执行这个 操作。 为提高可重用性,在编程时不要把策略和实现放在 同一个方法中,应该把算法的核心部分放在一个单 独的具体实现方法中。为此需要从策略方法中提取 出具体参数,作为调用实现方法的变元。
3. 避免使用多分支语句 一般说来,可以利用DO_CASE语句测试对象的内 部状态,而不要用来根据对象类型选择应有的行为, 否则在增添新类时将不得不修改原有的代码。 4. 精心确定公有方法 公有方法是向公众公布的接口。对这类方法的修改 往往会涉及许多其他类,因此,修改公有方法的代 价通常都比较高。为提高可修改性,降低维护成本, 必须精心选择和定义公有方法。 私有方法是仅在类内使用的方法,通常利用私有方 法来实现公有方法。删除、增加或修改私有方法所 涉及的面要窄得多,因此代价也比较低。
10
9. 参数化类 参数化类:使用一个或多个类型去参数化一个类的 机制。 程序员可以先定义一个参数化的类模板,然后把数 据类型作为参数传递进来,从而把这个类模板应用 在不同的应用程序中,或用在同一应用程序的不同 部分。 Eiffel语言中有参数化类,C++语言提供了类模板。
11
10. 开发环境 由于面向对象程序中继承关系和动态联编等引入的 特殊复杂性,面向对象语言所提供的软件工具或开 发环境显得尤其重要。 至少应该包括下列一些最基本的软件工具: 编辑 程序,编译程序或解释程序,浏览工具,调试器 (debugger)等。
12
12.1.3 选择面向对象语言
着重考虑以下实际因素: 1. 将来能否占主导地位 2. 可重用性 采用面向对象方法开发软件的基本目的和主要优 点,是通过重用提高软件生产率。因此,应该优先 选用能够最完整、最准确地表达问题域语义的面向 对象语言。
13
3. 类库和开发环境 语言、开发环境和类库这3个因素综合起来,共同 决定了可重用性。 不仅应该考虑是否提供了类库,还应该考虑类库 中提供了哪些有价值的类。 在开发环境中,除了提供前述的基本软件工具外, 还应该提供使用方便的类库编辑工具和浏览工具。 其中的类库浏览工具应该具有强大的联想功能。 4. 其他因素 对用户学习面向对象分析、设计和编码技术所能提 供的培训服务;在使用这个面向对象语言期间能提 供的技术支持;能提供给开发人员使用的开发工具、 开发平台、发行平台;对机器性能和内存的需求; 集成已有软件的容易程度等。 14
3. 可维护性 以ATM系统为例,假设在维护该系统时没有合适 的文档资料可供参阅,维护人员面对的只有源程序 时,维护人员人工浏览程序或使用软件工具扫描程 序,记下或打印出程序显式陈述的问题域语义,看 到“ATM”、“账户”、“现金兑换卡”等,对维 护人员理解所要维护的软件将有很大帮助。 尽量选用面向对象语言来实现面向对象分析、 设计的结果。
消息 消息
对象 属于该对象 的数据 处理数据的方法
29
12.3.2 面向对象的集成测试
在面向对象的软件中不存在层次的控制结构,传统 的自顶向下或自底向上及的集成策略及渐增式集成 方法就没有意义了。 面向对象软件的集成测试主要有下述两种策略: (1) 基于线程的测试:把响应系统的一个输入或 一个事件所需要的那些类集成起来。分别集成并测 试每个线程,同时应用回归测试以保证没有产生副 作用。 (2) 基于使用的测试:首先测试几乎不使用服务 器类的那些类(称为独立类),把独立类都测试完 之后,再测试使用独立类的下一个层次的类(称为 依赖类)。对依赖类的测试一个层次一个层次地持 续进行下去,直至把整个软件系统构造完为止。
6
3. 实现一般-特殊(即泛化)结构的机制 既包括实现继承的机制也包括解决名字冲突的机制, 即解决重名问题。 4. 实现属性和服务的机制 实现属性的机制着重考虑: 支持实例连接的机制; 属性的可见性控制;对属性值的约束。 对于服务主要考虑: 支持消息连接的机制;控制 服务可见性的机制;动态联编。
19
7. 利用继承机制 继承机制是实现共享和提高重用程度的主要途径。 (1) 调用子过程:如把公共的代码分离出来,构成 一个被其他方法调用的公用方法。
图12.1 通过调用公用方法实现代码重用
20
(2) 分解因子:从不同类的相似方法中分解出不同 的“因子”(即不同的代码),把余下的代码作为公 用方法中的公共代码,把分解出的因子作为名字相 同算法不同的方法,放在不同类中定义,并被这个 公用方法调用,如图12.2所示。使用这种途径通常 额外定义一个抽象基类,并在这个抽象基类中定义 公用方法。把这种途径与面向对象语言提供的多态 性机制结合起来,让派生类继承抽象基类中定义的 公用方法,可以明显降低为增添新子类而需付出的 工作量,因为只需在新子类中编写其特有的代码。
4
12.1.2 面向对象语言的技术特点
面向对象语言的形成借鉴了许多程序语言的特点: LISP(动态联编,交互式开发环境) SIMULA(类的概念,继承机制) Modula_2和Ada(数据抽象机制) 形成两大类面向对象语言: 纯面向对象语言:如Smalltalk和Eiffel等,着重支 持面向对象方法研究和快速原型的实现。 混合型面向对象语言:如C++等,在过程语言的基 础上增加面向对象机制。