2020春软件构造Lab4 Debugging, Exception Handling, and Defensi

1 实验目标概述

本次实验重点训练学生面向健壮性和正确性的编程技能,利用错误和异常处理、断言与防御式编程技术、日志/断点等调试技术、黑盒测试编程技术,使程序可在不同的健壮性/正确性需求下能恰当的处理各种例外与错误情况,在出错后可优雅的退出或继续执行,发现错误之后可有效的定位错误并做出修改。
实验针对 Lab 3 中写好的 ADT 代码和基于该 ADT 的三个应用的代码,使用以下技术进行改造,提高其健壮性和正确性:
⚫ 错误处理
⚫ 异常处理
⚫ Assertion 和防御式编程
⚫ 日志
⚫ 调试技术
⚫ 黑盒测试及代码覆盖度

2 实验环境配置

  1. 在Eclipse Market中搜索SpotBugs静态代码分析工具,完成下载,安装。
    在项目上面右键可以看到多出了一个选项卡:SpotBugs,即说明完成插件安装。
  2. Eclemma
    先在eclemma压缩包下载地址:http://sourceforge.net/projects/eclemma/ 下载压缩包,将eclemma压缩包下载下来后解压到Eclipse本地目录的dropins下,重启Eclipse即可。eclemma插件安装成功时,在Eclipse上会出现新的图标
  3. 在这里给出你的GitHub Lab4仓库的URL地址(Lab4-学号):

3 实验过程

3.1 Error and Exception Handling

3.1.1 处理输入文本中的三类错误

1~6不符合语法;7为元素相同;8为依赖关系不正确
通过ExceptionChain.java相连接
2020春软件构造Lab4 Debugging, Exception Handling, and Defensi
3.1.1.1 EntryNumberFormatException
原因:飞机编号不符合规则
抛出异常方法:检查飞机编号是否符合“前2个字符为大写字母,后4个字符为数字”
2020春软件构造Lab4 Debugging, Exception Handling, and Defensi
3.1.1.2 SerialNumberFormatException
原因:飞机型号不符合规则
抛出异常方法:检查飞机型号是否符合“3位由数字和大写字母组成”
2020春软件构造Lab4 Debugging, Exception Handling, and Defensi
3.1.1.3 SeatNumberException
原因:飞机座位数不符合规则
抛出异常方法:检查飞机座位数是否>0,<=506

2020春软件构造Lab4 Debugging, Exception Handling, and Defensi
3.1.1.4 PlaneAgeFormatException
原因:飞机机龄不符合规则
抛出异常方法:检查飞机机龄是否>0,<=10
同座位数

3.1.1.5 SameAirportException
原因:起飞和到达机场相同引起的错误。
抛出异常方法:对比两个机场字符串是否相等。

2020春软件构造Lab4 Debugging, Exception Handling, and Defensi
3.1.1.6 TimeConflictException
原因:起飞和到达机场时间冲突引起的错误。
抛出异常方法:判断抵达时间是否在起飞时间之前
2020春软件构造Lab4 Debugging, Exception Handling, and Defensi
3.1.1.7 SameEntryException
原因:两班相同航班冲突
抛出异常方法:判断抵达时间是否在起飞时间之前

2020春软件构造Lab4 Debugging, Exception Handling, and Defensi
3.1.1.8 HugeTimeGapException
原因:航班起飞抵达时间跨度太大(超过过一天)
抛出异常方法:判断抵达时间是否在起飞时间之后一天内

2020春软件构造Lab4 Debugging, Exception Handling, and Defensi

3.1.2 处理客户端操作时产生的异常

3.2 Assertion and Defensive Programming

3.2.1 checkRep()检查rep invariants

3.2.1.1 TimeSlot
查看TimeSlot的RI和AF
2020春软件构造Lab4 Debugging, Exception Handling, and Defensi
由此可以设置CheckRep()方法
2020春软件构造Lab4 Debugging, Exception Handling, and Defensi
3.2.1.2 Location
查看Location的RI和AF

2020春软件构造Lab4 Debugging, Exception Handling, and Defensi
由此可以设置CheckRep()方法
2020春软件构造Lab4 Debugging, Exception Handling, and Defensi
3.2.1.3 Resource(Flight)
查看Flight的RI和AF
2020春软件构造Lab4 Debugging, Exception Handling, and Defensi
由此可以设置CheckRep()方法
2020春软件构造Lab4 Debugging, Exception Handling, and Defensi

3.2.2 Assertion/异常机制来保障pre-/post-condition

3.2.2.1 EntryState
判断状态改变前后的合法性,只允许高铁拥有“Blocked”状态
2020春软件构造Lab4 Debugging, Exception Handling, and Defensi
3.2.2.2 PlanningEntry
前置条件为:被分配的资源不能为空。以FlightSchedule为例

2020春软件构造Lab4 Debugging, Exception Handling, and Defensi
后置条件为:更改后的条件不为空
2020春软件构造Lab4 Debugging, Exception Handling, and Defensi

3.2.3 你的代码的防御式策略概述

在客户端到API、API到ADT之间这两种传递过程的起始和完成阶段,都应该进行防御。

3.2.3.1 Client–>API前置条件防御
客户端和API之间,需要基于用户输入参数进行功能控制,因此用户输入的内容正确性决定了API功能实现的正确性。
客户端的输入方法或API的方法起始阶段需要对用户输入进行检查。
例如FlightEntry中需要读入一段数据,为航班分配资源,在方法中对各项参数及逆行了检查,在EntryNumberFormatException中通过ExceptionChain的doBusiness进行抛出异常。
3.2.3.2 Client–>API后置条件防御
在API的操作会对ADT进行影响,若ADT为可变的,则要求Setter()参数正确。检查参数正确可以在API的方法中,也可以在ADT的方法中。
例如在改变计划项之后,会检查该计划项类型是否为可滞留(Blocked)的计划项对象类型。
3.2.3.3
在API的操作会对ADT进行影响,若ADT为可变的,则要求Setter()参数正确。检查参数正确可以在API的方法中,也可以在ADT的方法中。
例如例如API在读入某计划项的资源时,断言判断该ADT的资源是否为空。

3.3 Logging

日志功能的实现调用了 Java 的库 java.util.logging。
1.导入包log4j-1.2.17.jar,目录如下
2020春软件构造Lab4 Debugging, Exception Handling, and Defensi
2.src同级创建并设置log4j.properties
2020春软件构造Lab4 Debugging, Exception Handling, and Defensi
3.在应用类中,只需要加一个全局静态变量,调用已经创建的相关的 logger,再设置无需从控制台输出日志内容即可。以ActivityCalendarApp为例:
2020春软件构造Lab4 Debugging, Exception Handling, and Defensi

3.3.1 异常处理的日志功能

2020春软件构造Lab4 Debugging, Exception Handling, and Defensi

3.3.2 应用层操作的日志功能

2020春软件构造Lab4 Debugging, Exception Handling, and Defensi
应用中使用功能在应用中使用的任何功能,都应该在调用之后马上生成 INFO 调用信息,在功能成功结束后,生成 INFO 成功信息。

3.3.3 日志查询功能

导出日志到log文件
2020春软件构造Lab4 Debugging, Exception Handling, and Defensi

3.4 Testing for Robustness and Correctness

3.4.1 Testing strategy

位置冲突:添加条目使产生冲突;在添加方法时调用方法
资源冲突:添加条目使产生冲突;在添加方法时调用方法
状态冲突:Blocked

3.4.2 测试用例设计

2020春软件构造Lab4 Debugging, Exception Handling, and Defensi

3.4.3 测试运行结果与EclEmma覆盖度报告

ExceptionTest测试运行结果
2020春软件构造Lab4 Debugging, Exception Handling, and Defensi
EclEmma覆盖度测试,以EntryNumberFormatExceptionTest为例
2020春软件构造Lab4 Debugging, Exception Handling, and Defensi

3.5 SpotBugs tool

发现了哪些错误,每种错误代表什么不良的编程习惯
1.
2020春软件构造Lab4 Debugging, Exception Handling, and Defensi
可以创建不同的实例,它们相同,但不以==进行比较,因为它们是不同的对象。通常不应该通过引用进行比较的类的例子有java.lang,Integer,long,float等。
2.
2020春软件构造Lab4 Debugging, Exception Handling, and Defensi
对readLine()的结果值没有进行判空操作就去重新赋值,这样的操作可以会抛出空指针异常。
对代码修改,消除这些错误。
1)
2020春软件构造Lab4 Debugging, Exception Handling, and Defensi
2)判断readLine的结果是否为空

3.6 Debugging

3.6.1 EventManager程序

理解待调试程序的代码思想
该程序要求若干时间区间交集数量的最大值。算法是标记+搜索。将区间的每一个整数点进行标记(用Map),查询是查找Map.values()最大值。
发现并定位错误的过程
键值匹配不恰当,循环条件有问题
你如何修正错误
2020春软件构造Lab4 Debugging, Exception Handling, and Defensi
以最小的键值与所有键值对进行比较,如果最小键值大于其他键值对的键,小于其他键值对的值,active++,最终取最大的active输出
修复之后的测试结果
2020春软件构造Lab4 Debugging, Exception Handling, and Defensi

3.6.2 LowestPrice程序

理解待调试程序的代码思想
该程序想要求在有special offer的情况下最优价格,是贪心算法的一种。首先假设最低代价为所有商品均为零售,然后每次将一个special offer加入“购物车”,更新需求,再用新需求迭代求解,直至求得最低价格
发现并定位错误的过程
测试用例运行后发现错误原因是死循环
你如何修正错误

  1. 2020春软件构造Lab4 Debugging, Exception Handling, and Defensi
  2. 2020春软件构造Lab4 Debugging, Exception Handling, and Defensi j-1改为j
    修复之后的测试结果
    2020春软件构造Lab4 Debugging, Exception Handling, and Defensi

3.6.3 FlightClient/Flight/Plane程序

理解待调试程序的代码思想
该程序通过枚举每个航班,尝试安排飞机,确保没有与其他已经分配的航班冲突,最后确认是否能所有同时分配成功。
发现并定位错误的过程
1.While死循环
2. boolean bFeasible一直返回true
3.fStart获取时间进行比较的方法错误
你如何修正错误

  1. 2020春软件构造Lab4 Debugging, Exception Handling, and Defensi
  2. 2020春软件构造Lab4 Debugging, Exception Handling, and Defensi
  3. 2020春软件构造Lab4 Debugging, Exception Handling, and Defensi
    修复之后的测试结果
    Test中无冲突的两架飞机返回true
    2020春软件构造Lab4 Debugging, Exception Handling, and Defensi
    三架飞机存在冲突返回false

4 实验进度记录

日期 时间段 计划任务 实际完成情况
6.3 12:30~18:00 3.1~3.3 3.1完成;3.2开始
6.4 9:00~11:00;
14:00~18:00 3.2~3.3 3.2完成;3.4完成;3.3没懂暂时跳过
6.5 20:00~ 3.3+3.5~3.6 3.5完成;3.6未完成;3.3不完全
6.7 13:00~ 完善3.3 完成

5 实验过程中遇到的困难与解决途径

  1. 原Lab3存在较多构造方法的问题,之前写程序也没有标注Testing strategy,省略一些Test,导致Lab4难度加大

    请教同学老师,重新编写了Lab3的一些接口

  2. log4j的配置和使用

    ****寻找教程

  3. EclEmma覆盖度不高

    覆盖率数据只能代表你测试过哪些代码,不能代表是否测试好这些代码,应该设计更多更好的Test

  4. 使用SpotBugs发现一些bug无法找到解决方法
    回顾课程,网上查询,使用JDK API