软件构造Lab4实验总结
1 实验目标概述
本次实验重点训练面向健壮性和正确性的编程技能,利用错误和异常处理、断言与防御式编程技术、日志/断点等调试技术、黑盒测试编程技术,使程序 可在不同的健壮性/正确性需求下能恰当的处理各种例外与错误情况,在出错后可优雅的退出或继续执行,发现错误之后可有效的定位错误并做出修改。 实验针对 Lab 3 中写好的 ADT 代码和基于该 ADT 的三个应用的代码,使用以下技术进行改造,提高其健壮性和正确性:
⚫ 错误处理
⚫ 异常处理
⚫ Assertion 和防御式编程
⚫ 日志
⚫ 调试技术
⚫ 黑盒测试及代码覆盖度
2 实验环境配置
需要下载spotBugs寻找错误,下载完成后会出现以下界面:
3 实验过程
3.1 Error and Exception Handling
考虑到文件内容较多,为了加快读文件以及建立轨道的速度,采用读一行匹配一行的策略,对于多数异常的处理一边匹配一边进行,对于某些特定异常需要在匹配完成之后再进行处理
种类1. 输入文件中存在不符合语法规则的语句
对于田径比赛轨道系统,异常情况以及处理代码如下:
1.运动员国籍不是由三位字母构成
2运动员.国籍中出现小写字母
3.运动员年龄为负数
4.运动员号码为负数
5.运动员成绩为负数
6.运动员成绩小数位不足两个
7.运动员成绩整数位超过两个
以上7个异常在匹配运动员变量的时候统一检查,此时也检查了种类2中出现相同元素的情况:
try
{
// 先判断是否有重复元素
Iterator<trackE1> iterator = athlete.iterator();
while (iterator.hasNext())
{
try
{
if (iterator.next().getName().equals(w ord1))
{
throw new Exception(
"same elements:the athlete " + word1 + " appears more than once.");
}
}
catch (Exception e)
{
log.info(
"trackGame:exception happens in class functionTrackGame,method creatingTrackFromFiles:"
+ e.getMessage()
+ " handling:return false,and exception message is printed on console");
System.out.println(e.getMessage());
return false;
// TODO: handle exception
}
}
// 国籍长度为3
if (!(word2.length() == 3))
{
throw new Exception("statements do not conform to syntax rules: the athlete " + word1 + "'s nationality is not made up by three letters:" + word2);
}
// 国籍由大写字母构成
for (int i = 0; i < 3; i++)
{
if (!((word2.charAt(i) <= 90) && (word2.charAt(i) >= 65)))
{
throw new Exception("statements do not conform to syntax rules: the athlete " + word1 + "'s nationality's first letter is not capital " + word2);
}
}
// 编号为正
if (Integer.parseInt(int1) < 0)
{
throw new Exception("statements do not conform to syntax rules: the number of athlete " + word1 + " is negative " + Integer.parseInt(int1));
}
// 年龄为正
if (Integer.parseInt(int2) < 0)
{
throw new Exception("statements do not conform to syntax rules: the age of athlete " + word1
+ " is not negative " + Integer.parseInt(int2));
}
// 成绩必须为正
if (Float.parseFloat(float1) < 0)
{
throw new Exception("statements do not conform to syntax rules: the result of athlete "
+ word1 + " is negative:" + Float.parseFloat(float1));
}
// 最好成绩必须有两位小数
if (float1.charAt(float1.length() - 1 - 2) != ".".charAt(0))// 必须有两位小数
{
throw new Exception("statements do not conform to syntax rules: the athlete " + word1 + " 's result's fractional part's length isn't 2");
}
// 已经确保有两位小数了,现在需要确保有不超过两位整数
if (float1.length() > 5)// 在此之前已经判断小数点的位数是有两位的,现在需要判断整数位数
{
throw new Exception("statements do not conform to syntax rules: the athlete " + word1 + " 's result's Integral part's length is larger than 2");
}
}
catch (Exception e)
{
log.warning("trackGame:exception happens in class functionTrackGame,method creatingTrackFromFiles:"
+ e.getMessage()
+ " handling:return false,and exception message is printed on console");
System.out.println(e.getMessage());
return false;
// TODO: handle exception
}
8.轨道数目不在[4,10]区间内:
// 比赛种类不符合要求
try
{
if (!(Integer.parseInt(int11) == 100 || Integer.parseInt(int11) == 200
|| Integer.parseInt(int11) == 400))
{
throw new Exception("statements do not conform to syntax rules: " + "the game type " Integer.parseInt(int11) + " is illegal");
}
}
catch (Exception e)
{
log.warning("trackGame:exception happens in class functionTrackGame,method creatingTrackFromFiles:"
+ e.getMessage()handling:return false,and exception message is printed on console");
System.out.println(e.getMessage());
return false;
// TODO: handle exception
}
9.比赛种类不在100|200|400的比赛范围内:
if (!((Integer.parseInt(int12) <= 10) && (Integer.parseInt(int12) >= 4)))
{
try
{
throw new Exception("statements do not conform to syntax rules: " + "the number of track " + Integer.parseInt(int12) + " is out of bound");
}
catch (Exception e)
{
log.warning( "trackGame:exception happens in class functionTrackGame,method creatingTrackFromFiles:" + e.getMessage()+ " handling:return false,and exception message is printed on console");
System.out.println(e.getMessage());
return false;
// TODO: handle exception
}
}
对于原子轨道系统,异常情况以及处理代码如下:
1.原子名称第一位字母小写
2.原子名称第二位字母(若有)大写
3.原子名称超过两位字母
以上三种情况在匹配原子名称时进行判断:
try
{
// 原子名称最多两位字母
if (!((temp.length() > 1) && (temp.length() < 3)))
{
throw new Exception(
"statements do not conform to syntax rules:the name " + temp + " is out of bound ");
}
// 第一位必须大写
if (!((temp.charAt(0) <= 90) && (temp.charAt(0) >= 65)))
{
throw new Exception("statements do not conform to syntax rules:the first letter \""+ temp.charAt(0) + "\" is not capital");
}
// 再保证只有两位的情况下,判断第二个字母是否是小写
if (temp.length() > 1)
{
if (!((temp.charAt(1) <= 122) && (temp.charAt(1) >= 97)))
{
throw new Exception("statements do not conform to syntax rules:the second letter \""+ temp.charAt(1) + "\" is not lowercase");
}
}
}
catch (Exception e)
{
log.warning( "atomStructure:exception happens in class atomStructure,method creatingTrackFromFiles:" + e.getMessage()
+ " handling:return false and exception message is printed on console");
System.out.println(e.getMessage());
return false;
// TODO: handle exception
}
4.轨道数目不是正整数:
// 轨道数应该是正整数
try
{
if (trackNumber2 <= 0)
{
throw new Exception("statements do not conform to syntax rules: the tracknumber "+ trackNumber2 + " is non-positive");
}
}
catch (Exception e)
{
log.warning(
"atomStructure:exception happens in class atomStructure,method creatingTrackFromFiles:"+ e.getMessage()+ " handling:return false and exception message is printed on console");
System.out.println(e.getMessage());
return false;
// TODO: handle exception
5.电子数量为负数
6.轨道编号为负数
以上两种情况在匹配电子时进行处理
try
{
// 轨道编号必须大于等于零
if (Integer.parseInt(a1) < 0)
{
throw new Exception(
"statements do not conform to syntax rules:the numebr of track is negative: "
+ Integer.parseInt(a1));
}
// 轨道上的电子数目必须大于零
if (Integer.parseInt(a2