简要写一下lab4的思路。(如果不对的话欢迎各位的建议)

3.1. Error and Exception Handling

哈工大2020软件构造Lab4_设计模式

首先看到注释2可知,我们检查所读入的文件,如果发现文件中的信息和指导书描述的信息不符合的话,那么==我们不仅要抛出异常、而且要捕获异常并进行异常处理。==参考Piazza老师的回答,当我们发现文件中有异常时,应该立即退出,并提示用户选择其他的的文件进行读取。

哈工大2020软件构造Lab4_软件构造_02

3.1.1 文件中的格式错误

我检查了所有可能出现的错误,检查的思路是:一行一行的读取,判断每一行的格式是否均符合lab3给的格式要求。

思路:由lab3可知,去除空行后,文件中每13行表示一个航班计划项,每一行都要符合lab3给出的格式要求。我使用13个正则表达式进行匹配,第一个正则表达式匹配第一行,如果第一行格式错误,直接抛出异常和提示信息,提醒用户换另一个文件进行读取。如果第一行格式正确,则使用第二个正则表达式匹配第一行和第二行,如果不匹配,那么肯定是第二行格式错误,因为我们已经知道第一行格式正确。依次类推,那么就需要13个正则表达式进行匹配。

为啥匹配的时候不是一次匹配一行呢:因为一次匹配一行,可能会出现这样的情况:13行的每一行的信息都是符合格式要求的,但是每一行的顺序不是正确的,这种情况下每次匹配一行也能匹配到相应的信息,但是这显然不符合格式要求。

所有的错误:

①格式不符合Flight:xxx,xxx  ②航班日期格式不符合xxxx-xx-xx  ③ 航班号不符合格式要求,不是由两位大写字母和 2-4 位数字构成 

第二行:

①第二行不是‘{’ 

第三行:

①格式不符合DepartureAirport:xxx,比如DepartureAirport拼写错误 

第四行:

①格式不符合ArrivalAirport:xxx,比如DepartureAirport拼写错误 

第五行:

①格式不符合DepatureTime:xxxx,比如DepatureTime 拼写错误  ②出发时间格式不符合xxxx-xx-xx yy:yy 

第六行:

①格式不符合ArrivalTime:xxx,比如ArrivalTime拼写错误

②到达时间格式不符合xxxx-xx-xx yy:yy

第七行:

①不符合Plane:xxx格式,比如Plane拼写错误  ②飞机编号格式不符合要求,不符合第一位为 N 或 B,后面是四位数字 

第八行:

①第八行不是‘{’ 

第九行:

①第九行格式不符合Type:xxx,比如Type拼写错误  ②机型格式错误,不符合大小写字母或数字构成,不含有空格和其他符号 

第十行:

 ①第十行不符合Seats:xxx,比如Seats拼写错误  ②座位数不是整数  ③座位数不在[50,600] 

第十一行:

①第十一行格式不符合Age:xxx,比如Age拼写错误  ②机龄不符合要求,比如范围不在[0,30],小数位数超过1位  

第十二行:

①第十二行不是‘{’ 

第十三行:

①第十三行不是‘{’ 

注释:我判断文件是否合法均是按照以上的标号顺序进行判断。(详细见代码)

给所有可能发生的异常实现一个自己的异常类,实现方法就是简单的继承Exception类,然后可以声明一个带参数的构造器方法。考虑到,文件中语法错误的异常很多,所有我将这些异常类统一看为文件格式不合法的异常。

哈工大2020软件构造Lab4_软件构造_03哈工大2020软件构造Lab4_软件构造_04

如果文件语句格式不合法,立即抛出异常,像老师所说,出现异常应该终止文件的读取,那么在catch语句中,我也是直接抛出一个异常,在App类里面捕获这个异常就可以使用日志记录这个异常信息,并且提示用户重新选择文件进行读取。

哈工大2020软件构造Lab4_哈工大软件构造_05

这是App类捕获异常的处理信息。哈工大2020软件构造Lab4_哈工大软件构造_06

3.1.2 输入文件中存在标签完全一样的元素

比如:存在多个航班计划项的“日期,航班号”信息完全一样。

思路:读取一个航班项之后,遍历之前已经读取到的航班集,判断是否存在和这个航班项完全相同的航班即可。

详细见代码

自定义的异常类:sameLabelException

哈工大2020软件构造Lab4_设计模式_07

哈工大2020软件构造Lab4_软件构造_08

3.1.3 输入文件中各元素之间的依赖关系不正确

哈工大2020软件构造Lab4_设计模式_09

思路:每次读取了一个航班项之后,就遍历已经读取的航班项,判断是否存在上述依赖关系不正确。详细见代码

自定义的异常类:wrongDependenceException类

哈工大2020软件构造Lab4_java_10

部分代码示例

哈工大2020软件构造Lab4_java_11

3.1.2 自定义的异常类

哈工大2020软件构造Lab4_哈工大软件构造_12

以cancelPlanningEntryException异常为例,主要就是继承Exception类就行

哈工大2020软件构造Lab4_软件构造Lab4_13

具体思路:客户端收到用户指令之后,然后调用相应的方法,如果出现异常,则相应的方法直接抛出相应的异常,客户端直接捕获异常之后就可以返回给用户提示信息。

哈工大2020软件构造Lab4_软件构造_14

3.2 Assertion and Defensive Programming

断言和防御式编程:主要是写 rep invariants (RI)、Abstraction Function (AF),以及它们的每个方法的
spec(pre-condition 和 post-condition)。以及checkRep方法。

checkRep方法: Location类:name != null  Timeslot类:time1 晚于time2 且不为空 Resource类:resource != null  FlightEntry:起飞时间必须要早于降落时间,起飞和降落的机场不相同 CourseEntry:上课时间晚于下课时间。位置不为空。 TrainEntry:所有的中途站不重复,所有的时间对按照时间增序,使用的车厢编号均不相同(将高铁 车次使用的 所有车厢编号放进set类里面,如果set集合的大小等于车厢的数量的大小,则车厢编号均不相同, 否则有重复)。 

哈工大2020软件构造Lab4_java_15

3.3. Logging

日志记录的信息有:

哈工大2020软件构造Lab4_哈工大软件构造_16

思路:

** 自己声明一个日志类logRecord,每一个日志类对象表示一条日志信息,日志类的属性有:异常发生的类名、方法名、时间、具体信息、日志等级、异常类型。**

然后声明一个日志管理类logKeeper,管理所有的日志信息,比如可以按照时间或者异常类型等等进行日志的查询。我们把App的日志信息输出到一个文件中,日志管理类logKeeper就可以读取文件信息创建多个日志类对象当客户端需要查询日志时,可以按照自己的格式来反馈给用户。

当出现异常时,需要记录异常的出现的类名、方法名、时间、提示信息、异常类、日志等级。

我设定了两种日志查询的功能,一个是根据时间范围进行日志查询,另一个是根据日志类型来进行日志查询

哈工大2020软件构造Lab4_java_17

哈工大2020软件构造Lab4_软件构造Lab4_18

哈工大2020软件构造Lab4_软件构造_19

3.4. Testing for Robustness and Correctness

即测试所有的类。要考虑语句覆盖度、分支覆盖度和路径覆盖度。

分支覆盖度

哈工大2020软件构造Lab4_哈工大软件构造_20

路径覆盖度

哈工大2020软件构造Lab4_设计模式_21

语句覆盖度

哈工大2020软件构造Lab4_设计模式_22

3.5. Using SpotBugs tool

① 一开始粘贴3.6节老师给的debug代码的时候, 出现的bug是判断相等用的是==,而不是equals方法

哈工大2020软件构造Lab4_软件构造_23

哈工大2020软件构造Lab4_软件构造_24

3.6. Debugging

3.6.1 EventManager程序

功能:给定许多个事件的起止时间,需要找出某一时刻同时进行的事件的最大数量。

思路:属性是类型为TreeMap的变量temp,temp的键存储的是事件在时间轴上的时间,值对应的是在该时间点上面同时发生的时间数量的最大值。所以只需要循环temp的所有的值,找出最大的值即可。

使用TreeMap的好处:TreeMap已经是按照键的大小排序,所以可以直接遍历temp,表示从时间轴向后遍历所有的事件,而不需要对键重新进行排序。**

3.6.2 LowestPrice程序

程序功能:给定一组优惠,并且给出我们所需要的各个物品的数量,找出需要购买这些物品的最低价格。

程序思想:首先求出按照商品的单价直接购买商品所需要的价格res。然后,遍历所有的优惠,如果这个优惠的需要的商品的数量不超过我们需要的数量,则递归的求出使用优惠所需要的价格。最低价格就是res和使用优惠的最小值。

3.6.3 FlightClient/Flight/Plane程序

功能:给定一组航班和一组飞机,问能否在飞机不冲突的情况下给每个航班都安排一架飞机。

思路:首先,对航班按照出发时间进行排序,然后随机选取一架飞机,判断如果给这个航班安排飞机是否存在冲突,如果存在冲突选取别的飞机,遍历所有的飞机如果仍然不能安排飞机,则返回false。