OO第二单元总结
第五次作业
作业设计结构
本次作业结构不算复杂,因此我只构建了5个类来处理本次问题。Main类作为总控制类,它启动了input和process线程。input类用于获取输入并将请求放入队列中。process类则用于调用队列的get方法,通过get方法中对scheduler类的调用实现对请求的响应。严格来说我这次做的结构还是有问题的,队列的get方法尽管会返回请求,但是在方法中就已经完成了请求,这与queue的设计需求不吻合,而且我的scheduler方法本来是为了做调度器的,但是我在写的过程中把电梯的功能也加进去了,这样使得我这次的结构有些不伦不类。
多线程之间信息的沟通使用了wait,notify,但是通过一些判断使得即使notify早于wait也可以使程序成功停止。
第五次作业的类图
第五次作业的流程图
作业度量分析
本次作业中我的EleQueue类中的get方法在设计上出现了漏洞,使用了大量的if else语句和while语句用来防止死锁,易于出现BUG,同时难以修复。
第五次作业的度量图
作业BUG分析
本次作业我的程序没有被找到BUG。
发现他人BUG策略
由于本次作业代码量小,大家的作业结构也很好,因此我主要选择利用之前我对自己程序的测试数据来发现别人BUG。最终成功hack他人1次。
第六次作业
作业设计结构
本次作业结构比上一次要复杂不少,但是我们所需要做的只是增加一个调度算法,通过这一算法让调度器按照一定的方案从队列中取出请求并进行执行。我主要采用的是look算法,同时我在每到新的一层时就会尝试从队列中读取请求。主要利用Main类创建process线程,Main向queue加入请求,process周期性调用elevator,elevator通过其设置的look算法的规则访问queue读取请求,并进行执行。同时我还使用了SortByDist类来对queue中的请求排序。
多线程之间主要通过sleep的延时以及while的轮询来处理信息的传递,这是为了防止wait,notify可能会出现的notify在wait之前的情况。
第六次作业的类图
第六次作业的流程图
作业度量分析
本次作业中我的整体结构还算完美,没有什么代码编写上的问题。
第六次作业的度量图
作业BUG分析
我的程序并没有出现错误,但是可能会发生在同一楼层两次开关门的问题。这是因为我在判断是否有人需要进出时忘记对要出去的人增加需要在电梯内的限制了,所以有可能会在确实有人需要下电梯,但是这个人还没上电梯时开关电梯门。
if ((next.getPersonRequest().getFromFloor() == elePosition
&& !next.isHasGetIn()) ||
(next.getPersonRequest().getToFloor() == elePosition
&& next.isHasGetIn())) {//bug after fixed
sign = true;
break;
}
发现他人BUG策略
由于本次作业代码量明显增大,同时大家的程序也编写的相当好,因此我没能找到BUG。
第七次作业
作业设计结构
本次作业结构相当复杂,我借助五个类完成了这一次作业。我主要通过Main类创建3个电梯的进程,并创建一个Review的进程,同时自己接受输入的请求并发给queue。在queue中设置三个队列为三个电梯所需处理的请求,读入的请求通过一定的处理得到它应当如何处理,如果只需要一个电梯的运行,则直接将其放入该电梯的请求队列,否则将请求分为两个请求,先将第一个请求放入对应电梯的请求队列。利用Review线程访问各电梯得到之前的被分开的请求的上半部分是否已经被处理完毕,如果是则将下半部分放入电梯中。
这个结构在我现在看来是一个愚蠢的结构,首先我可以通过电梯对请求的抢夺来实现请求的分配,这样做还会减少电梯的空闲率,再者我也可以采用让电梯向queue发送消息的方法进行前半部分与后半部分的衔接,单独采用一个Review类进行操作需要修改太多原本的结构,导致我的程序结构相当糟糕。
多线程之间主要通过sleep的延时以及while的轮询来处理信息的传递,这是为了防止wait,notify可能会出现的notify在wait之前的情况。
第七次作业的类图
第七次作业的流程图
作业度量分析
本次作业中我由于工程的结构有些问题,很多代码写的不够漂亮,Elevator类、EleQueue类写得结构很错乱,循环和条件语句多,在Elevator类的personInOut方法中使用了大量的while语句和if语句对多个Array List进行了处理,在EleQueue类的addOrder方法中,我采用了C语言的写法,对数组进行了很多循环、分支操作,写了很多层嵌套,这些都使得我的ev(G)、iv(G)、v(G)相当之高。
第七次作业的度量图
作业BUG分析
本次作业我的程序存在HashMap和ArrayList的线程不安全的BUG。比如下面是我修复BUG后对一个ArrayList的操作。
Iterator<PersonRequest> iterator = getReq.iterator(); synchronized (synObj) {//bug after fixed while (iterator.hasNext()) { PersonRequest next = iterator.next(); subReq.add(next); eleMap.put(next.getPersonId(), 0); iterator.remove();
} }
发现他人BUG策略
由于本次作业代码量相当大,同时我还有操作系统期中考试的压力,所以我没能完全仔细的读完别人的代码,只对一些我自己之前在编写代码时找到的BUG进行了测试,最后也没能找到别人的BUG。
SOLID原则
SRP 单一责任原则
我的第五次作业的queue类并没有做到这一点,多了处理请求这一功能,但是第六次作业就很好的做到了,第七次作业本身任务繁重,但我仍只分了五个类,所以queue类的功能太过复杂,包括了队列、请求的分解等功能,应当被分成多个类。
OCP 开放封闭原则
我在第五次作业与第六次作业之间的拓展对代码进行了大量的重构,但是第六次与第七次作业之间对电梯的调度算法以及输入部分的修改就几乎没有。
LSP 里氏替换原则
三次作业都没有用到继承
DIP 依赖倒置原则
第五次作业很好的做到了这一点,各个类结构和调用层次比较分明,第六次也是这样,但是第七次我的queue类、review类、elevator类相互调用,互相之间次序杂乱无章,没有很好的实现这一原则。
ISP 接口分离原则
三次作业的接口设计都比较合理,只有一点在于Main类传递的exit参数在其他类中的大量方法中被作为参数引用,但是exit只在某些方法中有用处,所以会有些繁琐。
设计原则分析以及心得体会
第五次作业我觉得写出的程序不够面向对象,没有完全按照每个对象所应当能执行的功能来编写代码,这需要我对一些代码的结构进行优化。
第六次作业我认为我的架构还算比较完整,代码风格也很漂亮,算是我这几次作业以来写的最漂亮的代码了。
第七次作业我认为我在面对大量问题时没有事先找到一个完整的解决思路,只想了个大概就开始了写代码,写了大半以后就开始对自己之前没有想清楚的部分犯难,不断增加新的东西,把原来很完善的部分也搞得很糟糕,最终给出的代码很差劲,失去了一个面向对象程序的样貌。对多线程的控制也不够清楚,多个线程间相互调用,有可能会由于锁的不够彻底出现除了ArrayList,HashMap以外的其他BUG。