OO博客作业2:第5-7周作业总结
(1)从多线程的协同和同步控制方面,分析和总结自己三次作业来的设计策略及其变化。
第5次作业:多线程电梯
基本照搬了课件上“生产者-消费者”模型的设计策略,将InputHandler设计为生产者线程,将Scheduler设计为消费者线程,将RequestQueue设计为托盘。生产者与消费者的工作并发,提高效率。同时,每部电梯设计为一个线程,因为每部电梯的运行彼此不干扰。InputHandler, Scheduler由主线程创建,三部电梯由Scheduler负责创建,这样使得调度器可以获取电梯的状态。但这种策略并不是最优的。
第6次作业:文件监控
这大概是写得最失败的一次作业。
按课件方法构建了线程安全的SafeFile类。实现了同步化的访问文件状态、写文件方法。然而对于每个record型请求单独建一个文件写入,违背了训练初衷。
每个请求设计一个“监控器”线程,直接查看对应文件的状态,与指导书的设计思路差异较大。这使得程序难以应对path-changed等大规模变化。
总的来说,这次多线程之间没什么协同可言。同步控制也仅限于对文件状态的访问。
第7次作业:出租车调度
这次作业的设计策略基本照搬第5次作业。输入处理线程为生产者,调度器线程为消费者,请求队列为托盘。每辆出租车为一个线程,依然由调度器创建。
写了线程安全的SafeFile类用于输出文本文件。乘客请求、参与抢单的出租车信息由调度器负责写入,出租车运行情况由出租车线程负责写入,实现了线程协同。
(2)基于度量来分析自己的程序结构
1)OO程序代码度量
第5次作业:
类名 | 属性个数 | 方法个数 | 代码规模 | main / run方法规模 | 点评 |
Elevate_5 | 0 | 1 | 27 | 17 | |
Elevator | 14 | 7 | 176 | 40 | 电梯控制逻辑复杂。 |
Floors | 2 | 4 | 24 | ||
InputHandler | 10 | 6 | 158 | 15 | 写得太随意,很多属性更适合作为局部变量。 |
Request | 4 | 59 | |||
-CarryRequest | 1 | 3 | |||
-FloorRequest | 1 | 3 | |||
RequestQueue | 6 | 4 | 56 | ||
Scheduler | 7 | 8 | 209 | 40 | 保留了上次的调度器代码。 |
Tray | 3 | 4 | 76 |
第6次作业:
类名 | 属性个数 | 方法个数 | 代码规模 | main / run方法规模 | 点评 |
Detail | 4 | 3 | 64 | ||
FileState | 4 | 3 | 26 | ||
InputHandler | 9 | 6 | 107 | 相似的问题 | |
Monitor | 8 | 2 | 60 | 30 | |
SafeFile | 2 | 15 | 110 | 为测试者写了较多的方法 | |
Summary | 4 | 3 | 64 | ||
TestDrive | 0 | 1 | 15 | ||
TestThread | |||||
Trigger | 3 | 8 | 94 | 设计有问题 |
第7次作业:
类名 | 属性个数 | 方法个数 | 代码规模 | main / run方法规模 | 点评 |
_Point | 2 | 7 | 40 | ||
CHandler | 9 | 4 | 76 | 32 | |
CityMap | 4 | 4 | 114 | 算法代码比较长 | |
FHandler | 2 | 4 | 55 | ||
Queue | 3 | 3 | 49 | ||
Request | 3 | 3 | 24 | ||
SafeFile | 2 | 5 | 57 | ||
Schedule | 6 | 6 | 146 | 44 | 调度方法夹杂输出代码 |
Taxi | 16 | 9 | 204 | 40 | 运行方法夹杂大量输出代码 |
TestDrive | 0 | 1 | 18 | 12 |
3)各次作业的类图
第5次作业:由于指导书给出了上次电梯的参考类图,自己的设计基本遵循了指导书。但是Tray这个类没能发挥出应有的作用,只是单纯地缓存请求。更好的做法是同时缓存电梯状态,电梯运行时更新,调度器需要时读取。
第6次作业:写得很糟糕,有“面条代码”的嫌疑。对Monitor和Trigger两个类的职责没有明确,而且Summary和Detail的代码有大量重用。
第7次作业:很多地方参考借鉴了第5次作业(多线程电梯)。各个类的职责相对清晰。
4)UML的协作图(从上到下依次是第5,6,7次作业的图)
5)设计原则检查(仅针对第7次作业)
DIP (Dependency Inversion Principle):高层次不依赖低层次。
程序有两个渠道获取输入,一是通过文本文件获取城市地图,二是通过控制台获取叫车请求。我的程序没有将这两种途径进行抽象和归纳,导致程序对输入方式变化的适应性不好。
命名:
在为类、实例变量命名时我尽可能遵循“顾名思义”,但是走向了另一个极端。我将一个记录点信息的类命名为“Point”,结果后来发现有java.awt.Point这个类,使用GUI时很不方便。无奈之下我将自己写的类改名为“_Point”,花了一部分时间改名字。在顾名思义的同时,也尽量不要取过于简单、大众化的名字,否则容易与JAVA类库重名,造成麻烦。
另外,eclipse建议包名首字母小写,类名首字母大写,作为初学者还是遵守得好。
(3)分析自己程序的bug
第5次作业:
所有的“正确请求测试多线程功能”样例均有错(公测未发现或是被发现bug)。
问题所在的类是Scheduler。
被发现了一个CRASH是由于想向文件写入结果,但文件已经关闭导致的。这暴露出我对于多线程同步控制尚未掌握,且自己构造的测试样例太宽松,很容易露出破绽。
从设计结构角度分析,我把所有的电梯调度方法全写入一个调度器类。Scheduler类的代码规模更是破了200行,远远超过其它类。
在总结课上,我才了解到有更加均衡的实现方式。总调度器只负责将请求分配给不同的电梯,而每部电梯对应一个专门的调度器负责排请求的执行先后顺序。这种方式显然更合适,既是遵循均衡原则,又符合实际的应用场景。
第6次作业:
对方没有进行公测,且没有发现bug,故不作分析。
第7次作业:
被发现了一个bug,为新增节点“等待状态下出租车的运行不具备随机性”。
问题所在的类为Taxi,方法为run_edge
这个bug被发现在情理之中,因为我曾经尝试过实现出租车的随机运行,但是失败了(出租车发生了瞬移)。最终改成了一版确定性运行的方法。
(4)分析自己发现别人程序bug所采用的策略
很多学生(包括我)在编写多线程程序时遇到的一个技术难点就是如何让程序正常结束(在eclipse下是在控制台上方看到<terminated>)。尽管这不是指导书的硬性要求,但是能够正常结束的程序势必带来更好的用户体验和更强的鲁棒性。如果被测者没有在readme中对程序的结束进行说明,或是说明能结束但实际上没实现的,则可以报告bug。
边界条件是在编程过程中需要着重考虑的。一些在实际情况中完全有可能出现,但编程者很难考虑到的测试点上往往容易发现bug。第7次作业我通过构造“乘客请求起始坐标正好是出租车所在位置”的样例,成功发现了别人的bug。
后期的作业不但注重程序正确性,而且对程序设计原则也提出了要求。测试者可以阅读被测代码,发现其中不符合设计要求的部分,予以扣分。
(5)心得体会
1)线程安全
在线程安全方面,重点是把握课上重点讲过的“生产者-消费者”模型,学会将共享对象的存取方法设置为同步化的,以及方法内部具体的写法。拿到指导书之后,在分析程序需要哪些对象、对象之间关系时,必须额外考虑哪些对象需要被共享的问题。无论是自己写被共享类的代码,还是包装为线程安全类,都要想清楚哪些方法需要保证原子性,并使用synchronized关键字。
2)设计原则
从第7讲开始,课后作业将程序设计原则也纳入了作业要求和互评范围。设计原则与程序的正确性没有直接的关系,而是为了让程序具有较好的可读性、可扩展性。在软件开发行业,用户需求发生变更是经常遇到的事件。遵循课上讲过的一些设计原则可以增强程序的可扩展性。在需求变更时,只需要对原有程序进行有限的修改,而不是推倒重来。自己在3次电梯作业中,后面的作业往往不能有效利用前面作业的代码,原因在于自己没有在一开始构造一个良好的设计,没有遵循设计原则。另一些原则是为了程序可读性,因为将来我们开发的程序只是一个大项目的一部分。不但要保证别人放心调用,而且最好在代码中清楚写出自己的逻辑。可能经过后面几次作业的训练,我能够更深入地理解设计原则。
OO博客作业2:第5-7周作业总结的更多相关文章
- OO博客总结——OO落下帷幕
OO博客总结--OO落下帷幕 凡此过往,皆为序章. 不知不觉OO课程即将落下帷幕,一路坎坎坷坷磕磕绊绊,可算是要结束了,心里终于松了一口气,也有小小的不甘和遗憾.凡此过往,皆为序章.特殊的线上OO课程 ...
- OO博客作业-《JML之卷》
OO第三单元小结 一.JML语言理论基础以及应用工具链情况梳理 一句话来说,JML就是用于对JAVA程序设计逻辑的预先约定的一种语言,以便正确严格高效地完成程序以及展开测试,这在不能容忍细微错误的工程 ...
- OO博客作业1:第1-3周作业总结
(1)基于度量来分析自己的程序结构 注:UML图中每个划分了的圆角矩形代表一个类或接口,箭头可代表创建.访问数据等行为.类的图形内部分为3个部分,从上到下依次是类的名称.类包含的实例变量(属性).类实 ...
- 第二次oo博客作业--多线程电梯
这次的系列作业是写一个电梯调度,主要目的是让我们熟悉多线程. 第一次作业是一个傻瓜电梯的调度问题,要求也很简单,即每次接一个人就行了.我只用了两个线程,一个是输入线程,一个是电梯线程,输入线程负责从标 ...
- 小菜鸡儿的第三次OO博客
规格化设计历史 规格化设计的历史目前网上的资料并不多,百度谷歌必应也表示无能为力...... 在这里结合现实情况讲一讲自己对程序规格化的理解,首先代码规格化对代码的影响是间接的,或许它不能让你代码里面 ...
- 接着继续(OO博客第四弹)
.测试与JSF正确性论证 测试和JSF正确性论证是对一个程序进行检验的两种方式.测试是来的最直接的,输入合法的输入给出正确的提示,输入非法的输入给出错误信息反馈,直接就能很容易的了解程序的运行情况.但 ...
- OO博客作业3:第9-11周作业总结
一.总结介绍规格化设计的大致发展历史和为什么得到了人们的重视 1.规格化设计的大致发展历史 规格化设计,又称契约式设计,最早由Bertrand Meyer于1986年提出,出自于<面向对象软件构 ...
- OO博客作业4:第13-14周作业总结
一.论述测试与正确性论证的效果差异,比较其优缺点 测试是设计若干组测试用例,运行程序并检验其是否完成预期功能.测试是一种直接发现BUG的方法,可以准确断定什么样的BUG会发生,并通过辅助调试进一步确定 ...
- 第四次oo博客作业
(1)本单元是撰写UML数据分析器,架构大致如下,在指导书要求的函数外,对于UmlClass类,Umlinterface类,以及状态机,顺序图这四个类重现构造一个类,这个类里有他们所需要的全部信息,另 ...
随机推荐
- JSF中run项目时候Tomcat8启动不了的一种方法
把另一个博客内容迁移到这 我的问题是Tomcat是可以启动的 但是run那个jsp的时候 七月 10, 2016 3:14:54 下午 org.apache.tomcat.util.digester. ...
- MongoDB添加仲裁节点报错replica set IDs do not match办法
背景:由于历史原因,某个MongoDB副本集只有一主一从双节点,无法满足自动故障转移要求,需要配置一个仲裁节点. 原有节点192.168.10.20:27017,192.168.10.21:27017 ...
- ELF文件的加载过程(load_elf_binary函数详解)--Linux进程的管理与调度(十三)
加载和动态链接 从编译/链接和运行的角度看,应用程序和库程序的连接有两种方式. 一种是固定的.静态的连接,就是把需要用到的库函数的目标代码(二进制)代码从程序库中抽取出来,链接进应用软件的目标映像中: ...
- 9. svg学习笔记-裁剪和蒙版
裁剪 在svg中进行剪切,对整个svg元素而言,可以使用<svg>元素的viewbox属性,对于单个元素则可以使用<clipPath>元素.在单个图形元素上使用裁剪,可以在&l ...
- 挂载KVM Guest操作系统磁盘
使用虚拟机时, 发现想要修改虚拟机中的文件非常麻烦, 需要启动虚拟机, 然后再登录进去修改. 对于已经关闭的虚拟机, 为了修改一个文件而启动, 非常耽误时间. 对于一个无法启动的虚拟机(比如启动文件损 ...
- 一文读懂SpringCloud与Eureka,Feign,Ribbon,Hystrix,Zuul核心组件间的关系
概述 毫无疑问,Spring Cloud是目前微服务架构领域的翘楚,无数的书籍博客都在讲解这个技术.不过大多数讲解还停留在对Spring Cloud功能使用的层面,其底层的很多原理,很多人可能并不知晓 ...
- python 基础操作--数据类型
一.变量 1.定义:将运算的中间结果暂存到内存,以便后续程序调用. 2.命名规则 1.变量由字母.数字.下划线搭配组合而成: 2.不可以用数字开头,也不能全都是数字: 3.不能是python 关键字, ...
- Django-rest-framework 接口实现 了解 GenericAPIView
进化写法GenericAPIView 面向对象的封装 将同样的 方法以及对象 封装到一起 将 对数据库相关的 功能封装到一起 GenericAPIView 在 from rest_framework. ...
- C#深度学习の委托深度解析
一.我们在使用C#的过程中,不可避免的用到了委托. 委托的本质是什么呢? 从语法上看,委托是对方法的抽象封装,例如:public void print1(),public void print2(), ...
- PHP程序员的能力水平层次
PHP程序员的能力水平层次 之前看过很多篇关于服务端工程师和PHP开发者的能力模型介绍,每篇都对能力有侧重点. 下面我们来详细谈谈以开发能力为基准点的PHP程序员的能力水平层次. 层层递进 1.功能开 ...