OO第二阶段总结

一、多线程电梯

1. 结构分析

(1)度量

程序的Cyclomatic Complexity过高,原因在于我在电梯类里实现ChangeState方法时,没有简化逻辑,就把各种能想到的情况都列出来了,一一进行响应,导致各种分支过多,以后可以尽量合并一些差不多的情况。

 

参数数目过多,主要原因还是在于延续了之前的调度器类,为了不费脑子往方法里传入了很多的参数。

 

代码嵌套过深,因为在电梯线程中对电梯的移动做了很多繁琐复杂的判断,上行、下行,同层、异层,中途有空闲、中途无空闲等等,而且嵌套逻辑不够清晰,导致嵌套过深。

 

(2)类图

主要的类就是几部电梯,一个调度器。调度器负责把输入的请求分配给电梯,电梯访问被分配到的请求,根据自身状态和这些请求改变更新状态。

其中,被共享的信息只要有:电梯的状态、请求队列和楼层的状态。

(3)时序图

2. BUG分析

对输出的时间没有按照指导书的标准进行整理导致输出格式错误;没有及时地更新电梯的运动量。

3. 找BUG策略

首先是看对输入的检查,没有发现BUG。然后,是对输出的检查,发现了两个BUG,第一个BUG是输出格式有点问题,与指导书要求不符,第二个是输出的时候所有的运动量都为0,即没有处理电梯的运动量。然后是对一些捎带条件的检查,看看调度器是否能正确地分配楼层请求,没有发现BUG。

4. 心得体会

这是第一次做多线程的作业,所以有些细节方面还没有考虑周全,对多线程也还存有许多的疑虑,导致在编程的过程中脑子经常转不过弯来。到最后都是赶着DDL写完的,结果还是写得不清不楚,自己都看不下去。以后写多线程时,一定要先确定好有哪些对象,哪些线程,以及哪些线程之间需要同步,哪些共享状态需要被保护。

二、IFTTT

1. 结构分析

(1)度量

在InputHandler中,生成线程这一方法的圈复杂度过高,主要原因在于把输入格式的检查,请求的生成和监视线程的生成全部都写在了这一个方法里。其实可以更加细化,每一个部分封装成一个方法,然后在一个新的方法里顺序调这些方法,这样思路也比全写在一起清楚很多。

 

在快照类中,比较两快照异同的方法出现了嵌套过深的问题。主要还是因为方法写得太散,一个方法调一个方法,方法里又调一个方法,如此嵌套下去,深度太大。可以尝试把一些简单方法合并起来,不用在已经很深的方法里再调一个方法。

(2)类图

主要的类就是监控线程和快照,监控线程每隔一定的时间获取新的快照,然后与旧快照进行比较,根据自己对应的监控作业,输出重命名、路径移动、修改时间变动、大小变化等等改变。

(3)时序图

2. BUG分析

这次测我程序的人没有给我找BUG,但我自己在看了一些讨论过后,知道自己应该还是存在一个BUG,就是多个文件的重命名映射问题。

3. 找BUG策略

对方在判断重命名时,没有注意到的一个条件是:“新增”。即他的程序会把原来就存在的,其他属性相同但是名字与消失文件不同的文件认为是重命名后的文件。还有就是没有处理多个重命名文件的映射问题。

4. 心得体会

这次的作业思路比较清楚,就是建立快照,然后比较信息,所以上手比较容易。但是,实际实现过程中会遇到不少的细节问题。比如,对目录的监控应该如何处理,这就应该使用一个递归来进行快照的比较,而不是像文件一样简单的同级目录比较。还有就是应该如何开监视线程,是一种触发器对应一个监视线程,还是一个监控对象对应一个监视线程,还是一个监控对象和一个触发器唯一确定一个监视线程,还是一个监控任务确定一个监视线程,不同的处理方式会带来不一样的处理细节问题,需要仔细思考。

三、出租车

1. 结构分析

(1)度量

租出车类的move方法出现了圈复杂度过高的问题,原因在于进行移动时,需要对当前状态进行判断(4种),还要判断是否需要进行一次的随机移动到停止的转化,在服务状态和接单状态还需要判断是不是刚刚转变成服务或接单状态等等,这些条件成立与否都会对后续的处理带来不同,目前还没有找到合适的解决方法。

(2)类图

主要的类就是请求窗口线程和出租车。每个请求窗口线程每隔一段时间将查询各个出租车的状态,从中挑选出可以响应的出租车。然后在窗口关闭的时候,从所有candidates中按照指导书的要求选择最合适的一辆租出车来接单,改变其状态为接单状态。

(3)时序图

2. BUG分析

本次作业的BUG主要出现在多线程访问共享资源的问题上。因为在请求窗口结束的时候,需要访问各个候选车的状态,然后改变最终被选车的状态。这时,如果两个请求几乎同时发出,都将一辆车纳入候选列表中,如果两个窗口几乎同时访问该车状态,都将认为该车可以接单,就都选择了这辆车来响应,实际当然是不可能的。这就需要把访问状态和修改状态绑在一起执行,中途不许其他线程做该动作。

3. 找BUG策略

被测者没有好好处理输入。(80,80)的点程序不会报错,(5,5)到(5,5)的请求程序也不会忽略。

4. 心得体会

这次的出租车调度主要需要清楚有哪些线程,这些线程要做什么,他们共享了哪个对象。我的想法是:请求窗口是一个3s的线程,出租车移动是一个200ms执行一次move的线程,他们都将访问共享对象出租车的一些状态。

posted @ 2018-05-01 22:37  inevitable  阅读(120)  评论(0编辑  收藏  举报