导航

第二次博客作业

Posted on 2018-05-02 13:34  VioletQ  阅读(213)  评论(0编辑  收藏  举报

OO作业总结二

 


第五次作业 多线程电梯

· 设计策略

  本次作业设计了管理请求的类,楼层类,电梯类和调度器类。其中每一个电梯一个线程,负责包括捎带功能在内的运行;管理请求为一个线程,负责将输入的请求存入总请求队列;调度器类为一个线程,负责将主请求队列里的请求按分配规则分配给电梯。这几个线程之间的关系是:管理请求与调度器线程共享主请求队列,而电梯类与调度器类共享每个电梯的请求队列。为了避免出现线程安全问题,对共享属性的操作方法加上了synchronized。

·度量分析

  类图

  

  协作图

  OO度量

 

  可以看出elevator类的复杂度过高,类之间的聚合度不够。捎带算法没有利用第三次作业的算法,当扩展电梯系统支持ALS调度时重写了算法,违背了OCP原则;电梯类不必要地承担了部分调度器的任务,输入的部分写在了Main类里,与SRP原则不符。类与类之间承担的任务量差距太大,可维护性和可读性都比较差。唯一比前几次有改进的是用了枚举类,而不是用数字代表各个对象的状态。

·分析自己的BUG

  这次作业由于时间仓促和对多线程,出现了很大问题。首先是一行输入多行指令时,我错误地将它们认为是不同时间输入的,所以公测错了2个,互测又被报了两个bug;另外,我对结束程序的判断有错误,虽然主请求队列和各个电梯的请求队列里没有请求但是电梯在执行这条请求时的情况没有考虑,导致程序总是不能执行最后一条指令,这样公测又错了2个,互测被报了3个。最后,由于第一个疏忽,我判断同质的时候时间的判断也不对,互测又被报了两个,理由是输出不稳定。

·测试策略

  测试自己的时候每次都是一次输入全部指令,导致没有发现以上bug。

  测试别人时先看正则,若符合要求则认为输入格式判断正确;再把分支树上合法请求的分支都测一遍;最后用比较大数据测试。

  这次拿到一个水平非常高的同学,类之间分工明确,代码简洁易懂,并没有找出bug。我还专门保留了他的代码供以后学习。

 

 


 

第六次作业 IFTTT(文件监控)

·设计策略

  这次作业的设计分两个部分,第一是测试部分,包括对文件的线程安全操作类和测试线程类;第二监控部分,包括管理请求类,触发器类和任务类,这三个类分别开了一个线程。管理请求类读入请求并将合法请求加入请求队列;触发器类监控文件变化;任务类负责写入触发summary和detail。由于监控与文件操作、触发和结果文件写入均涉及线程安全问题,我将触发器类和任务类的方法加上了synchronized。

·度量分析

  类图

    

  协作图

 

  OO度量

   可以看出 代码复杂度过高,基本上都是Trigger类贡献的,在代码规模上也有体现。具体看Trigger类,renamed触发和path-changed触发几乎完全一样,size-changed和modified触发基本相同,可以我依然每一个都用了两个方法实现,而且每一个方法都涉及递归,这大大增加了代码的复杂度,违背了重用原则。另外,每一次测试任务线程每隔一段时间向文件写入结果时是追加写入,导致文件中有大量重复内容。

·分析自己的BUG

  本次作业我吸取了上次的教训,把每个类的分工明确之后才动手。一开始没有理解指导书,程序不支持文件夹的renamed和path-changed监控,改了之后发现要求输出文件改变的所有信息,而我写的是改变了哪个输出哪个,可惜没有时间改了。果然,互测时,size-changed触发时我没有输出时间前后变化被找出了bug。另外,由于时间仓促我没有实现rename之后还能监控的功能,又被报了一个。最后,我自己发现我对test类和Trigger类不正确阻塞的解决方法不对,本来很害怕会被报很多,因为线程不安全,但是这个同学的关注点基本全在功能上,没有测线程安全,我侥幸逃过一劫。

·测试策略

  这次不检查格式问题,给大家省了不少时间。对分支树分支进行覆盖性测试后,我发现该同学对文件夹的size-changed监控不正确,具体是新增和删除文件时他的触发器不触发,估计和我一样,发现了但是没时间实现了。这个同学在控制台输出了很多信息,大大方便了我的测试。

 

 


第七次作业 出租车系统

·设计策略

  本次作业要求设计的是一个模拟出租车与乘客交互的系统,我们可以抽象出这样几个类:Map,Taxi,Request,分别表示地图,乘客请求和出租车。此外还需要一些辅助的类来调度整个系统,如请求队列类,输入类,调度器类。

  出租车类(Taxi)进行模拟出租车的运动、输入判断类(InputHandler)进行分析每一个请求是否合法并能够提取出请求的信息构成一个请求(Request)、请求队列类(RequestQ)把所有的请求放在数组里统一分配、调度器类(Scheduler)进行请求分配与安排出租车的运动、请求输入类(RequestInput)负责读入请求并把判断出合理的请求送到请求队列里。

  请求输入管理(RequestInput)为一个线程,每个出租车(Taxi)为一个线程,由调度器(Scheduler)线程进行把请求队列中的请求分配到出租车。为了保证线程的安全,在请求队列(RequestQ)和出租车(Taxi)类的部分方法加上了synchronized。

·度量分析

  类图

  协作图

  OO度量

   问题依然是类之间任务分配不均衡,Taxi类中的run()方法是一个巨大的有限状态机,其中还包含了计算最短路径和随机行驶的方法,规模过大,不符合责任均衡分配原则;

  Taxi类中对时间的补偿重复写了6次,没有层次化抽象;

  这次由于使用了gui包,没有用枚举类,导致代码可读性差,debug时也十分费劲。

·分析自己的BUG

  这次作业要求的抢单时间是3秒,但是由于我用的是系统的真时间,若保证了抢单时间是3秒,那么从请求发出到出租车出发的时间并不是3秒,因为程序分配出租车时消耗了时间,我没有处理这个bug。

  由于我的程序没有符合重用原则,还被报了一个设计缺陷,目前我已改正

 · 测试策略

  这次的测试无比麻烦,出租车的初始位置是随机的,等待状态的运动方向也是随机的。我结合gui和文件输出判断代码的功能正确性。唯一发现的一个小bug是这位同学的出租车在等待状态随机行驶时道路的选择并不是随机的。但是,他的需求分析写的很好,也基本符合设计要求。

 

 


心得体会

  第一次接触多线程,基本知识没有掌握好就贸然动手做作业,必然是失败的。我的多线程电梯就是个例子:类之间分工不明确,指导书明确的要求被忽视,最后被测出来了才知道自己为啥错,这也是一个宝贵的教训;IFTTT工作量加大,但是我花时间看了课件,查了资料,研究了指导书,所以虽然感觉累,但是我知道这么写是一定正确的,最后的bug也是自己发现了没时间改造成的。出租车稍微容易一些,而且我动手较早,所以比前两次感觉稍好一点。单单从这三次作业我被扣的分看,我确实有进步,但是离代码风格好、设计没有缺陷还是差很多。