一、摘要

本文是BUAA OO课程Unit2在课程讲授、三次作业完成、自测和互测时发现的问题,以及倾听别人的思路分享所引起个人的一些思考的总结性博客。主要包含设计策略、代码度量、BUG测试和心得体会等内容。

二、设计策略分析

2.1 第一次作业

第一次作业较为简单,主要由Elevator线程和InputHandler线程互相合作完成,是消费者、生产者模式,InputHandler生产AllRequest类中的Request对象存在ArrayList中,电梯从中取出Request对象并完成送乘服务。该ArrayList即是共享资源,需要实现互斥。Elevator在内部有人的情况下先完成内部任务,当内部人员为空时去接Request中的乘客,若Request也为空,且输入未完成,则sleep。InputHandler每次增加Request对象都会唤醒电梯。若输入完成,则电梯下班。

2.2 第二次作业

本次作业与上次作业的区别并不大,可捎带的实现在电梯每次到达某一楼层时进行一次是否捎带的判断。如果符合捎带条件,开门后的处理流程和第一次基本是一致的,需要注意的线程安全问题基本没有改变。

2.3 第三次作业

本次作业中有多部电梯,并且电梯有各自运行的楼层,于是某些情况下乘客需要转乘来到达目标楼层。本人在设计中是通过对乘客类的修改实现,记录乘客的目标楼层,并先把目标楼层替换为中转楼层,在乘客出门后将增加一个请求。在电梯是否捎带的策略设计中,每部电梯只捎带从自己运行楼层出发,目的地也为自己运行楼层的请求,或者从自己运行的非换乘楼层出发的请求。设计中需要保证所有可能的请求都能顺利完成,不会出现无法到达的情况或者没有电梯响应请求的情况。也增加了新的线程安全问题,需要重新考虑电梯下班的条件,以及增加请求时也需要唤醒sleep的电梯线程。

2.4 对调度策略和实用性的思考

本次作业中,有很多指导书中的要求只是对实际情况的一种抽象,存在某些细节与实际不符合,也有考虑不周的情况。

例如对负重,现实中一定不会按人数,而会按照具体的重量来决定,那么在乘客输入请求时,电梯是无法预判是否会超载的。因此,基于超载预判的调度策略优化在现实中并不合理。

其次,作业中从未思考乘客的自主选择,除了反悔等,乘客可能提前下电梯、采用自己的换乘方案等。

最后,某些整体时间缩短的策略可能导致个别乘客等待时间的过长,可能会引起使用者的不满。

2.5 对优化的思考

本部分仅仅考虑在指导书规定中的优化,将有与上一节讨论(即与实际应用)矛盾或不合理的地方,仅可能带来性能上的提升。

首先,电梯在不载人的时候可以运行到某个特定楼层,例如中间楼层,或者换乘楼层,或者基于乘坐数据集的最可能接客地点。

其次,预判电梯将超载时,如果请求可以由其他电梯完成,同时调度其他电梯到该楼层。

还有基于当前所有请求的最优调度模拟。如果请求可以由不同电梯完成,或者楼层的访问顺序可以改变,可以预先计算所有调度方案所用时间,再选择最快的方法。但此方法对性能有较大影响。

三、程序规模统计

3.1 第一次作业

类图

代码度量

主线程UML时序图

Elevator UML时序图

3.2 第二次作业

类图

代码度量

主线程时序图

Elevator UML时序图

3.3 第三次作业

类图

代码度量

主线程时序图

Elevator UML时序图

3.4 分析

优点:设计中可扩展性强,后两次作业没有对之前的作业进行大规模的重构,类图具有一定相似性,设计中基本符合SOLID原则中的里氏替换原则、接口隔离原则、依赖倒置原则。

缺点:单一责任原则不是非常符合,Elevator的run、canTake、RunningCheck等方法复杂度过高,对Elevator类还可以进行拆分,可以将优化、调度策略等单独用一个类实现;第三次作业中不同的电梯设计不符合开放封闭原则,三部特殊电梯可以使用继承的方式实现。

四、测试中的bug分析

4.1 自我程序bug分析

本单元三次作业中,本人自己的bug仅仅只有第三次作业有1个bug,具体如下。

         } else if (name == 'C' && !el.isInC(toFloor)) {
this.toNewFloor = toFloor;
if (el.isInA(toFloor)) {
this.toFloor = 1;
} else {
if (floor <= toFloor) {
this.toFloor -= 1;
} else {
this.toFloor += 1;
}
}
this.special = true;
}

含BUG的代码

         } else if (name == 'C' && !el.isInC(toFloor)) {
this.toNewFloor = toFloor;
if (el.isInA(toFloor)) {
this.toFloor = 1;
} else {
if ((floor <= toFloor && floor != 3) || (toFloor == 2)) {
this.toFloor -= 1;
} else {
this.toFloor += 1;
}
}
this.special = true;
}

修复后代码

此为设计上的考虑不周。BUG位于People类的构造器中,即在分析特殊乘客的转乘路线时,设计出现了错误,导致乘客不能正确地转乘,从而无法到达目标楼层。

在本单元我的程序中,并没有出现有关线程安全问题的bug。

4.2 互测其他人bug分析

本单元中互测时遇到的bug也比较少,例如请求完成电梯线程sleep后唤醒时出现的重复到达楼层的问题,和第三次作业中特殊楼层请求不能被正确完成的bug。基本都为设计上的小问题,没有遇到线程安全的问题。

五、Hack策略分析

5.1 Hack策略

Hack分别基于代码和统一共性问题进行测试。统一的问题如

线程安全问题的测试主要通过阅读代码来进行判断,这次互测时也没有发现线程安全方面的问题,因此没有特意设计基于某个线程安全bug的针对性数据输入。

5.2 与第一单元的差异

第一单元中,学生主要出现bug的地方都是关于输入输出格式方面的问题,Hack主要基于指导书要求中容易被忽视或者设计上易出现错误的数据,而程序功能性问题比较少。本单元中使用统一接口后,bug只剩下功能性问题和线程安全问题。

六、心得体会

6.1 线程安全

本单元中开始了多线程的设计,在以前简单地学习JAVA中我对多线程有一点点了解,但之前从未考虑过安全问题。通过理论课程的学习和三次作业的练习,大概了解了保证线程安全的重要性和方法。本单元的练习中,主要是输入结束和电梯暂时无任务、电梯下班等需要仔细考虑,输入完成后不意味着电梯就已经完成任务,电梯内仍然可能有人,而第三次作业中,输入完成、电梯内无人后仍然可能有人还没到达目标楼层,这些都是要考虑的地方。而且有关线程安全的测试也更加困难,不一定会引起错误而且具有不可再现性,需要在设计中考虑周全并进行多次测试。

6.2 设计原则

本单元的设计方面现实性比较强,易从实际角度分析电梯的调度要求,可能出现的各种情况等,功能的设计方面思考起来比较容易。在设计原则方面,由于功能的复杂总体较低,有些原则没有顾全,例如单一责任原则,本身电梯需要完成的调度还算比较简单,所以没有分离设计,对更复杂功能的程序实现是存在问题的。而基本上没有使用继承、抽象等,无法体现里氏替换原则。本单元只是对多线程设计的简单初探,之后的更多要求更加复杂的设计中需要更加考虑到SOLID原则才能使程序具有更好的健壮性和扩展性,符合工业化的要求。

电梯系列——OO Unit2分析和总结的更多相关文章

  1. UML系列——OO Unit4分析和学期总结

    一.本单元的架构设计 1.类图 第一次 第二次 2.关键方法和架构简述 总体而言是读取图的时候就完成大部分计算(完成缓存),调用查询方法时只是展示计算的结果,少部分直接计算.主要是设计了各种自己定义的 ...

  2. 多项式求导系列——OO Unit1分析和总结

    一.摘要 本文是BUAA OO课程Unit1在课程讲授.三次作业完成.自测和互测时发现的问题,以及倾听别人的思路分享所引起个人的一些思考的总结性博客.本文第二部分介绍三次作业的设计思路,主要以类图的形 ...

  3. JML规格编程系列——OO Unit3分析和总结

    本文是BUAA OO课程Unit3在课程讲授.三次作业完成.自测和互测时发现的问题,以及倾听别人的思路分享所引起个人的一些思考的总结性博客.主要包含JML相关梳理.SMT Solver验证.JML单元 ...

  4. OO Unit2多线程电梯总结博客

    OO Unit2多线程电梯总结博客 传说中的电梯居然就这样写完了-撒花

  5. OO Unit2 总结

    OO Unit2 总结 OO课Unit2电梯仿真项目技术回顾 BUAA.1823.邓新宇 2020/4/17 Part1 设计策略 从多线程的协同和同步控制方面,分析和总结自己三次作业的设计策略 第一 ...

  6. SonarQube系列二、分析dotnet core/C#代码

    [前言] 本系列主要讲述sonarqube的安装部署以及如何集成jenkins自动化分析.netcore项目.目录如下: SonarQube系列一.Linux安装与部署 SonarQube系列二.分析 ...

  7. 【HANA系列】SAP HANA跟我学HANA系列之创建分析视图一

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[HANA系列]SAP HANA跟我学HANA系 ...

  8. OO电梯系列总结与反思

    目录 前言 HW5 度量分析 UML类图与协作图 bug分析 HW6 度量分析 UML类图与协作图 bug分析 HW7 度量分析 UML类图与协作图 bug分析 SOLID原则 感想 前言 紧张刺激的 ...

  9. OO电梯系列优化分享

    目录 前言 HW5 HW6 第二次作业uml协作图 HW7 第三次作业uml协作图 前言 本单元作业在优化方面确实有一些想法值得分享,故单开一篇博客分享一下三次作业的优化以及架构. 三次作业的共同之处 ...

随机推荐

  1. asp.net动态添加控件学习

    看了老师的教程后,自己一点感悟记录下来: 1.在页面提交后,动态生成的控件会丢失, 但如果生成控件的代码在pageload中,就可以,原理是每次生成页面都执行生成. 2.动态按件或页面原来控件, 在页 ...

  2. 我的第一个python web开发框架(40)——后台日志与异常处理

    后台权限和底层框架的改造终于完成了,小白也终于可以放下紧悬着的心,可以轻松一下了.这不他为了感谢老菜,又找老菜聊了起来. 小白:多谢老大的帮忙,系统终于改造完成了,可以好好放松一下了. 老菜:呵呵,对 ...

  3. 【spring源码分析】IOC容器初始化(十)

    前言:前文[spring源码分析]IOC容器初始化(九)中分析了AbstractAutowireCapableBeanFactory#createBeanInstance方法中通过工厂方法创建bean ...

  4. Django ORM 使用原生 SQL

    使用原生sql的 方法 : raw # row方法:(掺杂着原生sql和orm来执行的操作) res = CookBook.objects.raw('select id as nid from epo ...

  5. 如何在本地编译Fabric Code

    之前的博客都是拿官方现成的Docker镜像来用,但是并没有自己动手做镜像,也没有说到如何去开发和测试Fabric的代码.这一篇博客就从入门的角度讲解如何编译.测试和开发Fabric. 一.环境准备 要 ...

  6. 特殊需求:EF 6.x如何比较TimeSpan格式的字符串?EF Core实现方式是否和EF 6.x等同?

    前言 我们知道C#中的TimeSpan对应SQL Server数据库中的Time类型,但是如果因为特殊需求数据库存储的不是Time类型,而是作为字符串,那么我们如何在查询数据时对数据库所存储的字符串类 ...

  7. windows配置nginx实现负载均衡集群 -请求分流

    windows配置nginx实现负载均衡集群 一.windows上安装nginx 1.下载nginx的windows版本http://nginx.org/en/download.html 2.把压缩文 ...

  8. Docker 核心技术之容器与镜像

    Docker容器与镜像的关系 容器提交 – docker commit docker commit -h 作用: 根据容器生成一个新的镜像 命令格式: docker commit [OPTIONS] ...

  9. JS中让新手倍感震惊、违反直觉、出乎意料、的一些知识点汇总记录

    本文记录在自己学习js过程中,违反直觉,出乎意料,倍感震惊的知识点.当然,不了解这个知识点,很容易出错,因为毕竟违反直觉,出乎意料,倍感震惊嘛! 1. 两个内容一样的数组竟然不相等? var a = ...

  10. this.$router.push、replace、go的区别

    1.this.$router.push() 描述:跳转到不同的url,但这个方法会向history栈添加一个记录,点击后退会返回到上一个页面. 用法: 2.this.$router.replace() ...