Unit2-窝窝牌电梯
全文共2329字,推荐阅读时间10~15分钟。
文章共分四个部分:
作业分析
Unit2要求我们模拟现实生活中的电梯调度情景,迭代路径是单电梯->多电梯->特殊选层电梯。本单元的作业分析有独特的地方——因为三次作业都采用了一致的架构,因此以第三次作业的UML图为例即可了解整个单元迭代开发的过程。

从UML图可以很直接地看出来整个系统的模拟思路:通过分包策略,让输入(request)、分配(dispatcher)、调度(scheduler)、电梯本身(elevator)、时间控制单元(timeunit)之间实现“透明调度”。所谓“透明调度”和工厂模式有异曲同工之妙,只要保证包与包之间的调用接口不变,那么内部实现可以任意改变。也正是因为这个原因,三次作业的类图均遵循了上图的包模式。说完架构,下面分别分析三次作业的代码质量评估。
第一次作业
第一次作业要求我们实现一个可捎带的单电梯模拟系统。
UML图如下

- 代码结构
结构可以大致分为三层,输入->调度->电梯运转,之所以把电梯运转单独拆出来,是因为电梯只有上下的功能,其他的带有判断逻辑的“自主意识”都在调度器中实现。
- 复杂度分析


从反馈结果可以看出,由于把所有的判断逻辑都放进了调度器,造成了调度器的复杂度过高。在其他方法中,还是比较好的体现了“高内聚低耦合”的设计思想,均没有较高的复杂度。
第二次作业
第二次作业要求我们实现可稍带多电梯调度程序,并且能够自定义电梯数量。
UML图如下

- 代码结构
代码架构基本延续了第一次的设计风格,虽然更换了调度策略,但是可以发现UML图的三层结构几乎没有变化。
- 复杂度分析


从反馈结果可以看出,由于这一次的多电梯要求,我把请求的输入和分配都放在了输入层,导致复杂度相比于第一次有所上升。现在回看起来,输入逻辑和分配逻辑完全可以分开实现,这样就可以保证输入类的“单责性”。
第三次作业
第三次作业要求我们实现可稍带的特殊电梯调度,并且可以动态改变电梯的数量。
UML图如下

- 代码结构
代码架构基本延续了第一次的设计风格,在输入层增加了Dispatcher来实现分配逻辑。
- 复杂度分析


从反馈结果可以看到,由于Dispatcher的出现,原本复杂度很高的输入和调度层都有所改变,但是由于分配策略过于复杂,导致Dispatcher的复杂度变得很高,可以考虑再次切分分配策略:比如将一部分状态分析的方法放进调度器中直接实现一个反馈接口交给分派器。
SOLID Principle
S:单一功能原则O:开闭原则L:里氏替换原则I:接口隔离原则D:依赖反转原则
逐一分析,单一功能原则在每一次的迭代中都有不同程度的提升,比如Input和Dispatcher的分离;开闭原则体现得比较明显,因为更新调度器时除非采用不同的线程管理方式,其余部分都不用更改;里氏替换原则在本单元中不好展现,毕竟都没有继承关系。;接口隔离原则在一定程度上有助于实现前面提到的开闭原则;依赖反转原则是本单元让我体会最深刻的原则之一,因为先写上层架构,同时为下层留好待实现接口的方式,可以在开发过程中合并很多不必要的方法或者变量,同时更能够体现层次化思想。(感觉有点像先写评测机再做开发)
时序图(Sequence Diagram)

评测相关
详情见这里(https://www.cnblogs.com/silencejiang/p/12701979.html)
重难点聚焦
从三次开发和互测的过程来看,问题主要都在CPU时间上。这个问题之所以能够获得如此“殊荣”,主要是以下两个原因:
- 本地测试CPU时间(啥玩意儿?)
- 不只polling会导致过高的CPU时间,就算用
wait-notify,要是没操作好,结果是一样的。
对于第一点,在和大家的交流以及经过了学长的指点后,发现这个问题对win用户确实很不友好——在linux下使用time系统调用可以轻松地实现上述操作。但是,我们有万能的python——在time库中有一个神奇的函数process_time(),根据官方文档是可以实现和前者一样的功能的。但是,由于这个函数的subprocess的兼容性并不好,最后还是选择了前者。(I am so into Linux)
对于第二点,因为最开始设计的结束方式是在程序结尾统一notifyAll(),这样会导致程序和polling无异,CPU时间过高也就出现了。
Hack所用的策略
主要有两种方式:
- 使用完成作业时有意义的样例进行测试
- 利用评测机自己生成数据
评测机简要介绍
这是评测机的working directory

center:存放评测的核心控制代码,用于组织编译->运行->反馈功能data:存放自动生成的数据download_data:存放测试中出现问题的数据,可以用于回归测试。factory:存放数据生成代码output:存放各个测试代码的输出result:存放各个测试代码的结果ruler:存放标程src:存放源码filter.py:用于格式化数据以提交
本单元的评测机延续了上一单元的架构,但是加入了多线程评测和JAR包评测机制。原因很简单,多线程可以提高评测的速度,JAR包评测可以提高对不同架构程序评测的兼容性。
值得一提的是,本次加入了运行结果的可视化分析,分别是:
运行时间走势

在所有数据里取得最优解的次数

平均调度时间及其方差和标准差(标准差在该情境下和方差等价)

通过可视化分析,我逐渐明白一个道理:生活中的最优解用大数据的思想来探寻,比起挠头冥想会不会更轻松一点呢?
重构策略
在三次作业的完成过程中,我都是先确定好架构再开始完成的,所以没有遇到需要从头开始重构的情况。
但是值得一提的是,由于优化需求,每次都利用了上文提到的可视化思路进行策略的选择,因此调度策略在三次作业中都有或多或少的改变。同时,接口一致性保证了除了调度器之外的部分不需要进行逻辑上、架构上的修改。
课程体验感受
这一单元的迭代开发让我初步接触了现代软件开发的基本功:多线程。
总的来说体验良好,这种让计算机硬件发挥它最大作用的感觉非常棒。同时,也让我开始重新审视那些我自以为已经拿在手上的工具,比如Python.以前从来没有使用过Python的多线程模块,这次为了开发评测机就小有涉及;之前和matplotlib只是点头之交,现在逐渐觉得自己还要领会的东西真是数不胜数,期待未来的路上还会出现的小确幸吧。
最后一定要说的是:谢谢讨论区里的老师、助教、同学,是大家让我真正领会了一句很久以前看见的话:
一个人可以走得很快,但一群人才能走得更远。
Unit2-窝窝牌电梯的更多相关文章
- OO_Unit2 多线程电梯总结
OO_Unit2 多线程电梯总结 相比于Unit1的表达式求导,Unit2的多线程电梯听上去似乎显得更加"高大上".但在完成了3个task的迭代后再回过头去比较这两个单元,我发现其 ...
- BUAA_OO_第四单元
一.UML解析器设计 先看下题目:第四单元实现一个基于JDK 8带有效性检查的UML(Unified Modeling Language)类图,顺序图,状态图分析器 MyUmlInteractio ...
- OO Unit2多线程电梯总结博客
OO Unit2多线程电梯总结博客 传说中的电梯居然就这样写完了-撒花
- 电梯系列——OO Unit2分析和总结
一.摘要 本文是BUAA OO课程Unit2在课程讲授.三次作业完成.自测和互测时发现的问题,以及倾听别人的思路分享所引起个人的一些思考的总结性博客.主要包含设计策略.代码度量.BUG测试和心得体会等 ...
- OO Unit 2 电梯调度
目录 OO Unit2 博客作业 基于度量来分析⾃己的程序结构 复杂度分析 架构分析 改进和重构 发现过的BUG 简化问题 多线程初探 OO Unit2 博客作业 基于度量来分析⾃己的程序结构 自认为 ...
- 面试题:电梯/雨伞/杯子/笔/A4纸/纸杯… 怎么测试?
目的 面试的时候,面试官出题可能会出其不意: 比如随意指定生活当中的一件物品,问你如何测试,见下 作为测试人员,电梯/雨伞/杯子/笔/A4纸/纸杯… 怎么测试? 面试官的考察点 1.在没有需求文档或者 ...
- OO Unit2 总结
OO Unit2 总结 OO课Unit2电梯仿真项目技术回顾 BUAA.1823.邓新宇 2020/4/17 Part1 设计策略 从多线程的协同和同步控制方面,分析和总结自己三次作业的设计策略 第一 ...
- OO unit2 summary
Unit2 一.第一次作业 1.UML 2.Sequence Diagram 3.同步块设置与锁处理 采用了生产者-消费者模式,用共享对象来连接不同的线程. 第一次作业中,我有三个线程:Receive ...
- c 算牌器代码
int main() { // 算牌器 ]; ; do { printf("请输入牌名: \n"); scanf("%2s",char_name); ; ]) ...
随机推荐
- 必须使用角色管理工具 安装或配置microsoft.net framework 3.5
windows server 2008安装sql server 2012后报错,要求安装microsoft.net framework 3.5 sp1 但安装时提示,必须使用角色管理工具 安装或配置m ...
- Java内存虚拟机理解
对于Java程序员,在虚拟机自动内存管理机制的帮助下,不需要再为每一个操作写配对的释放资源操作,不容易出现内存泄露和内存溢出问题.加深对Java虚拟机的理解,有助于在发现问题时精准定位问题,排 ...
- Java基础以及变量和运算符、包机制、javadoc生成
目录 注释.标识符.关键字 注释 标识符 关键字 标识符注意点 数据类型 强类型语言 弱类型语言 Java的数据类型 基本类型(primitive type) 数值类型 boolean类型 什么是字节 ...
- 【原创】CentOS 7搭建多实例MySQL8(想要几个搞几个)
起因 最近项目上开始重构,可能会用到主从加读写分离的情况,就想先在本地搭一个出来试试效果,结果百度一搜出来一大堆,然而自己去踩坑的没几个,绝大多数都是去抄的别人的内容,关键是实际应用中还会出错,浏览器 ...
- Nginx判断客户端实现301跳转
set $a 0; #第一个条件 if ($uri !~* /(.*).php(.*)){ set $a 1; } #第二个条件 if ($http_user_agent ~* (up.UCBrows ...
- java后端解决跨域
1 package com.zys.boot_jeep.config; import org.springframework.context.annotation.Bean; import org.s ...
- 【JAVA习题七】输入一行字符,分别统计出其中英文字母、空格、数字和其它字符的个数。
package erase; import java.util.Scanner; public class 字符串分类 { public static void main(String[] args) ...
- MVC案例
MVC案例分析: - 没有业务层,直接Servlet调用Dao,所以也没有业务操作.所有在DAO直接获取Connection对象 -采用MVCDs设计模式 -使用到的技术: mvc设计模式:JSP ...
- 设计MyTime类 代码参考
#include <iostream> #include <cstdio> using namespace std; class MyTime { private: int h ...
- DNS域传输漏洞利用总结
操作基本的步骤是: 1) 输入nslookup命令进入交互式shell 2) Server 命令参数设定查询将要使用的DNS服务器 3) Ls命令列出某个域中的所有域名 4) Exit命令退出程序 攻 ...