1.设计策略
第一次作业,这是第一次接触多线程的问题,就按照自己对电梯的直观理解来进行设计。请求的输入是一个线程,同时专门为请求写了一个Person类,然后调度器和电梯分别是两个线程。 请求由输入的线程产生,传输给调度器,调度器用轮询+Sleep的方式来判断当前是否有请求输入,然后再把输入传送给电梯,电梯会在完成原先主请求后轮询等待新的请求。第二次作业,发现上一次的作业当中,调度器没有必要专门写成一个线程,会多许多麻烦,其次,存在许多线程与线程之间的交互,导致代码的耦合度不好。就只有两个线程,一个用户的输入线程,一个电梯的线程,他们中间有一个请求队列,输入线程会将请求放入队列,电梯每到一层都会访问请求队列,然后顺便完成捎带请求。第三次作业就增加了许多难度,与第二次作业的结构相类似,采用的是电梯自由抢夺乘客的策略,每当有请求出现,若请求需要换成,会先将请求拆分,然后3个电梯都会去扫描队列中是否有能去完成的请求,若存在就去执行。
2.程序结构的分析
第一次作业
类图
时序图
度量分析
存在的问题:
- 从类图和时序图中可以发现,我的设计是线程与线程之间的直接交互(PLUS:这个应该避免),这就导致了当其中某一个线程需要修改的时候,与它交互的线程有很大可能也会进行修改。
- 从度量的分析中可以看到我的Elevator类的run方法设计复杂多过高,与代码对照发现确实有这种情况,内容过于复杂,存在着大量的判断语句和本应该分离的操作。
第二次作业
类图
时序图
度量分析
进步
- 设计的架构更加合理,修正了线程与线程之间的交互问题。
- 同时将上一次中没有实际作用的控制器线程换成了一个实例,用来实现输入线程与电梯线程的之间的请求池(类名忘记更改了,也主要因为一开始想对请求加入一些调度的算法)
- 将Elevator的Run方法的许多操作分离出去了。
存在的问题
- 控制器中的getInPerson方法过于复杂,这是由于设计时的思路不清晰导致的,将判断电梯门是否开的操作也加入了进去。合理的做法应是:电梯到达楼层,1.判断是否需要开门(有人需要出或需要进?),2.出人,3.等待0.4秒,进人(优化的小trick),总共3个方法来完成。
- Elevator类的run方法的分支判断仍然有些复杂,经过后面的思考,发现不需要将电梯的移动操作与等待操作分离,从而使电梯的移动操作在一个循环里。
第三次作业
类图
时序图
度量分析
存在问题
- 与第二次设计相同Elevator的run方法循环内不需要嵌套循环。
- 与上一次作业相同,PickUp方法太过复杂,应该将能否接人的判断进行分离。
- getMainRequest的两个方法写的过于复杂,这是由于希望改变获取主请求的算法来进行性能的提升,结果由于复杂遗漏了一些特殊情况,电梯会在某些楼层间来回运动,不断更新主请求,从而爆炸。
设计原则分析
可以说在设计原则这方面,我这单元的作业十分糟糕。如果设计原则能够更早的在课堂上提出就好了,前面的作业会有更多的时间让我们投入到关于设计方法的思考。
- SRP:这一原则比较好的体现在Person和PersonInput类吧。关于电梯类,我认为它的许多行为是变化的,我们应该将这些变化的行为进行分离,写一个接口,这样会在以后的拓展更好。
- OCP:在三次作业,我有经常修改Elevator的PickUp,PutDown和getMainRequest方法,这三个行为是经常会变化的,所以我认为应该将它们分离,写到行为的接口里,Elevator对修改关闭。
- LSP:这次没有运用继承,而是使用了Elevator线程与ElevatorType类的组合,这样不用进行大量的重复工作。
- LD:这三次作业,后两次作业中在这方面做的还是可以的。
- ISP:额,这次没有使用接口是比较遗憾的,没有在这方面得到锻炼。其次,经过思考,如果有更多的接口的话代码的结构会更加清晰,类中变化的和不变的将分离,而我们对代码的扩展,即变化,只需要在接口里写就可以了。
- DIP:
3.分析程序的bug
第一次和第二次作业由于算法比较稳妥,都没有在公测和互测中找到bug。但是在第三次作业中,由于希望提高电梯的性能,更改了电梯获取主请求的算法,通过扫描楼层希望选取最合适的请求,但是没有过多的去思考该算法的情况,且课下的自行测试没有做足。
4.分析自己发现别人程序bug所采用的策略
第一次和第二次由于指导书给的方向比较固定,分在同组的人也都是按照指导书的方法进行编写的,只发现了一个bug,但还是线程不安全的bug,也没有测出来。与第一单元相同,先通过自己的测试样例进行轰炸,关于代码,着重会去看有锁的部分是否会出现死锁的情况或其他线程不安全,如果有就编写针对性测试数据。
5.心得体会
首先是了解并去应用了多线程编程的方法,发现了许多新的编程方式,以及多线程程序与单线程程序相比,需要考虑到线程的安全性,尤其是多个线程对共享资源的访问时互斥性以及线程间的死锁问题,这一点往往难以发现。其次是设计原则,可以说,在本单元的作业当中,没有在这方面投入什么功夫,有很多设计如果应用到原则,会避免很多问题,尤其是对最后一次的作业来说,前面的作业合理应用设计原则就会更加的舒服。最后就是最心痛的一点,不要面向课下测试编程!!!要合理安排好作业的时间,最好能够提前,留出一些时间用来做更多的代码测试。