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次电梯作业中,后面的作业往往不能有效利用前面作业的代码,原因在于自己没有在一开始构造一个良好的设计,没有遵循设计原则。另一些原则是为了程序可读性,因为将来我们开发的程序只是一个大项目的一部分。不但要保证别人放心调用,而且最好在代码中清楚写出自己的逻辑。可能经过后面几次作业的训练,我能够更深入地理解设计原则。

原文地址:https://www.cnblogs.com/liqingyang/p/8981819.html

时间: 2024-10-10 17:53:08

OO博客作业2:第5-7周作业总结的相关文章

接着继续(OO博客第四弹)

.测试与JSF正确性论证 测试和JSF正确性论证是对一个程序进行检验的两种方式.测试是来的最直接的,输入合法的输入给出正确的提示,输入非法的输入给出错误信息反馈,直接就能很容易的了解程序的运行情况.但是,每次测试只是在程序涉及的整个问题空间取一个元素进行测试,一次测试只能确保程序对于测试中的样例和同类样例是正确的,并不能确保全局正确性.而为了追求全局覆盖性,就需要大规模的测试样例轰炸了,但是这时测试的最致命缺陷就出现了,一是如何构造如此大量且属于不同类别的测试样例,二是如何确保构造的测试样例能够

小菜鸡儿的第三次OO博客

规格化设计历史 规格化设计的历史目前网上的资料并不多,百度谷歌必应也表示无能为力...... 在这里结合现实情况讲一讲自己对程序规格化的理解,首先代码规格化对代码的影响是间接的,或许它不能让你代码里面的bug直接消失,或许它也不能让电梯之间不相互阻塞,但是它能让OO实验拿到更多分啊//笑.玩笑归玩笑,下面具体分析一下规格化设计(JSF为例)的作用: 在代码实现过程中,人们往往不能从一开始对整个项目的每个细节都面面俱到地思考一遍,规格化设计在开发初期可以将项目中的细节隐去,工程师只需要考虑类or包

oo博客2

一.从多线程的协同和同步控制方面,分析和总结自己三次作业来的设计策略及其变化 第五次:这次作业我的策略便是读入指令一个线程.调度器一个线程.电梯三个线程,通过调度器线程将读入指令线程读入的指令分配给三个电梯,而三个电梯则一直在运行,检测是否有指令产生.本次作业完全使用synchronized关键字进行同步控制. 第六次:这次作业因为指导书要求不太明确,我便放弃了读入指令线程这个设计以达到更好地同步控制.我的设计是将指令全部读入后,根据指令数量建立对应的监控线程,这样一来我只需做好监控线程的同步即

设计与实现分离——面向接口编程(OO博客第三弹)

如果说继承是面向对象程序设计中承前启后的特质,那么接口就是海纳百川的体现了.它们都是对数据和行为的抽象,都是对性质和关系的概括.只不过前者是纵向角度,而后者是横向角度罢了.今天呢,我想从设计+语法角度说一说我感受到的面向接口编程,从而初探设计与实现分离的模式. (本文所使用的面向对象语言为java,相关代码都是java代码) 设计--接口抽象设计 继承的思想很容易理解,提取几类相近数据中的公共部分为基类,各个独立部分在基类的基础上做自己专属的延伸.接口是抽象概括输入和输出,而具体的实现交由具体实

我的Android进阶之旅------&gt;经典的大牛博客推荐(排名不分先后)!!

本文来自:http://blog.csdn.net/ouyang_peng/article/details/11358405 今天看到一篇文章,收藏了很多大牛的博客,在这里分享一下 谦虚的天下 柳志超博客 Android中文Wiki AndroidStudio-NDK开发-移动开发团队谦虚的天下 - 博客园gundumw100博客 - android进阶分类文章列表 - ITeye技术网站CSDN博文精选:Android系列开发博客资源汇总 - CSDN.NET - CSDN资讯Android笔

Hexo 博客 之 腾讯云部署过程

写在前面 Hexo 博客搭好了有差不多两周时间了,这期间走了很多弯路,跳了很多坑.一些坑自己 bing 到了答案,找到了解决方法,一些坑则是自己摸索出来的解决方法.现在准备写几篇关于搭建流程.搭建过程中遇到的问题和解决方法.俗话说得好,好记性不如烂键盘嘛. 暂时准备写三篇关于 Hexo 博客搭建的博文: 关于 Hexo 博客 腾讯云部署过程 关于 Hexo 博客 NexT 主题的美化插件设置 点击这里 关于 Hexo 博客 添加域名映射和 https 点击这里 本文介绍 本博客是关于 Hexo

2019年7月-第一次写博客

总有一句话,万事开头难,一些东西往往是从0到1的过程是最艰难的.比如我再大二就想自己写博客,把自己做的一些东西记录下来. 此时此刻,我已经大四毕业了,离开学校半个多月之久.但是我的博客到此时此刻一直没有写.我给我自己找了几个理由, 第一,时间不够充足,整理这些东西会很浪费时间. 第二,能力不够,从小语文水平较差,害怕组织不出有品位的语言. 第三,专业技术能力不够,害怕弄错. 在快要毕业的时候,由于研究生入学考试的失败,我在年后就去朋友公司实习去了,阿木实验室(www.amovauto.com)实

软件工程_东师站_第十周作业

一.PSP Data Type Job start Int End Total 20160510 助教 团队作业二 20:00 5 21:00 55 20160511 助教 团队作业二.三 18:45 16 20:45 104 20160512 耐撕 站立会议 18:15   18:35 20 二.进度条   代码行数 博客字数 知识点 第一周 400 430 见我博客软件工程——师大站1 第二周 0 5200 见我博客软件工程_东师站_课堂笔记 第三周 0 63 站立会议.单元测试 第四周 1

软件工程_东师站_第八周作业

一.PSP Date Type Job Start Interrupt(min) End Total(min) 20160417 助教 黄金点 20:00 5 21:00 55 20160418 助教 黄金点 19:00 12 21:00 108 20160419 助教 黄金点 18:45 100 23:00 155 20160420 助教 团队作业 10:00 35 11:20 45 20160425 结对编程 四则运算 19:00 5 19:30 25 ? 二.进度条 ? 代码行数 博客字数