OO第四单元博客作业

(1)总结本单元两次作业的架构设计

第一次作业
是要完成一个UML类图解析器,已知的是UmlElement信息,要求完成类图有关信息的查询指令。

设计思路的关键是对UmlElement进行处理,建立起自己的类图保存机制,而这些元素是相互关联的。

所以,我首先采用了NodeClass,NodeInf,代表类和接口,在对应的类保存自己的attribute(我建立了MyAttrib)和operation(我建立了MyOper)等,同时,采用单例模式,在UMLhelper对于全局使用的量进行保存(比如所有的NodeClass,NodeInf等用hashmap进行保存)。所以,我在MyUmlInteraction类里实例化一个helper便于查询使用全局变量。所以,这种分层对应关系正如下图:

1615418-20190624100731244-952018050.png

第二次作业

我保留了上一次的结构,同时增加了一些新的方法,我在要求的MyUmlGeneralInteraction里实例化了上一次作业的UMLHelper和MyUmlInteraction,所以类图查询指令没有变化。对于,新增的顺序图和状态图的信息,我在helper里增加了一定存储结构,保证了单例模式的实现。

同时,我新建了NodeState,NodeInter来代表状态图和顺序图。对于,新增的规则检查,我在NodeClass,NodeInf增加了一些方法。总体设计思路和上一次基本一样,具体关系,如下图:

1615418-20190624103023794-1384466918.png

(2)总结自己在四个单元中架构设计及OO方法理解的演进

1.第一单元作业:表达式求导

这个单元的作业主要是让我们熟悉了java语言,了解了类的使用、继承以及接口实现等基础知识,从面向过程走向面向对象。

第一单元的前两次作业,主要是面向过程的设计思想,尤其是第一次作业,属于只会java的一些语法之类,没有面向对象的思想,导致我的复用性较差(设置了两个类,只是输入判断的方法和map的结构在第二次能继续使用),所以基本每次都要重构。

而第二次作业的改进之处是,我根据老师的建议增加了Interpreter类对输入进行判断处理,提取出系数、x、sin(x)、cos(x)的指数等再存入map。

第三次作业中程序耦合度前两次有了明显的改善,主要是因为运用了面向对象的思想进行设计,还建立了接口,合理解耦,分类。我重新设计了类和方法,采取了ArrayList数据结构,将表达式解析为:Expression存Terms,Terms存Factors,使用Factor接口,使得不同类的因子存于同一list中,建立了嵌套联系,嵌套时的求导思路是递归,通过递归一层层下降求导。

2.第二单元作业:电梯

这个单元的作业主要是让我们了解了多线程的一些设计模式和方法并将其熟练使用,而在电梯的设计和使用过程中,了解了生产者与消费者模式、单例模式等设计策略,学会减少硬编码,并且能够灵活地使用工厂模式、抽象工厂模式等好的设计模式或方法。同时,在踩雷和写出bug的过程中,认识到了多线程中线程安全的重要性。我学会了采用notifyAll和wait的方式实现同步控制,用synchronized锁来保证线程之间互斥访问共享对象,而且设计中一定要避免轮询等问题。

而第一次作业,我在结构设计上采用的是“生产者-消费者模式”,有输入、调度器和电梯三个线程一起运行。把输入当成“生产者”,将请求队列当成“盘子”装运输请求,而电梯当作“消费者”取出请求加以实现。具体实现是由调度器Dispatcher每次从盘子里取出一个请求给电梯,电梯将其运送到指定的位置。

第一次作业没有bug,电梯运行逻辑比较简单,但是没有使用wait和notify,不太友好。

第二次作业,由于加带了ALS捎带策略,所以,我在第一次作业的基础上进行了改进,整体架构仍然为“生产者-消费者”模式。在调度器Dispatcher里直接将请求队列存起来,这样就判断是否捎带,以及是否开关门变得十分方便,不过对于调度器,我使用了单例模式,并采用notifyAll和wait的方式实现同步控制。

第二次作业并没有bug,电梯运行正常,只是捎带性能较差,主要是调度策略存在偶然性,如果用scan可能会好一些。

第三次作业,保留了不少之前作业的设计,比如单例模式等设计模式并没有改变。但由于不同电梯有不同的到达层数,所以一定存在换乘,所以,我制定了调度策略:设置mid,每次输入,如果必须换乘则mid不为零,而是根据一定策略,制定换乘中转站。

但是,第三次作业,我出现了致命的错误,cpu时间超时:在elevator的run方法里出现了轮询问题,因为如果该方法执行时间很短,则会出现抢占CPU的问题,所以需要sleep操作。这导致我的多个测试点超时,而且这样的线程是不安全的。

3.第三单元:地铁线路查询

这个单元的作业让我们了解了JML语言,并学会了熟练使用相关设计思路和工具。正如老师的PPT所说的,引入JML规格和复杂的中间数据模型,让我们在图数据结构和图模型之间建立层次,根据功能需要设计适应性能要求的中间数据模型和协同架构 (比如,以空间换时间成本,解决时间性能问题)。

正如第一次作业,我在结构设计上采用的是多容器来解决时间性能问题,比如,map与list存的东西一样,但是map便于查找:

private ArrayList nodesList;
private HashMap<Integer, Integer> nodeMap;

第二次作业,由于加了图结构,所以,我在第一次作业的基础上进行了改进,将图结构存起来,而图的数据结构,我选择的是hashmap嵌套hashmap,而由于图没有权值,所以可以使用bfs来解决最短路径问题。

第三次作业,保留了不少上一次作业的设计思路,正如,数据结构,hashmap嵌套hashmap,仍然与第二次相同。但由于图结构有不同权值,而且存在换乘,所以放弃了bfs,改用dij来计算最短路径。我的设计是,每次加入的path,都构造成完全图,每次换一条边,相当于增加一次换乘。

4.第四单元:UML图解析

具体架构之前已经阐述,这个单元逐步引入了UML模型的理解和解析,给我最深的体会应该是这种层次化的模型构建,正如老师上课时提到的,本单元的核心设计目标是针对诸多不同类型的对象构造层次和关系,在构造UML模型的过程中动态维护相关的查询数据。

(3)总结自己在四个单元中测试理解与实践的演进

经过四个单元,我对测试有了更深的理解,测试能力也也有所提高。

第一单元的时候,我自己测试能力还比较弱,测试并不算充分,甚至每次都有bug,比如,第一次bug较多,原因主要在于我的匆忙优化,没有多去测试,display时没有打印0前面的+号,语句漏写了“=“号,导致不会输出”+“。

而第二单元的时候,多线程下,电梯运行可能出现的问题有很多,比如:线程无法正常停止;有乘客未被接上就结束了线程;“吃人”电梯(有乘客滞留电梯); 数组下标越界;线程停止时开关门操作异常等。

所以,可以加入自动化评测手段, 因为自己手动在控制台输入,是不可能定点投放请求的。所以必须有自动化评测手段,比如用jar打包+命令行的方式来实现。

同时,我也学会在互测时分析他人的程序:比如,在互测阶段,寻找别人的bug时,我首先使用自己在强测前即中测阶段,对自己的project所使用的测试样例来对别人的程序进行测试,会仔细看指导书的要求来构造,对指导书的边界样例进行总结,构造相关测试点,正如:第一次作业的格式问题。

之后,我会仔细阅读room里其他人的代码,先理解别人的代码和设计思路,看能否直接找到错误,构造相应测试点,寻找潜在bug。另外,如果逻辑上没有找到问题,可以自己构造一些临界或易错的测试点,或者可以编写自动化测试,以及构建脚本文件等使测试更加全面。

而第三单元,前两次作业,从设计思路上来说,没有任何问题,强测和互测都是满分,原因是自己先用 JUnit 测试了程序的一定正确性,并用随机数据生成器,与他人进行对拍,充分的进行了测试,保证了正确性。而且前两次优化了容器的使用,使得设计本身不会导致超时等问题。

第三次我的设计思路比较迟缓,虽然进行了一定随机化测试,留给自己测试时间太短了,没有进行充分的测试,导致bug的产生,所以,测试手段也很关键,随机数据生成器也不能依赖,应该仔细分析程序的各种可能结果,自己精心构造好测试样例,而构造好测试样例,不仅是在动手前,也是在动手后的仔细检查中。

不过这一单元让我学会了Junit、JunitNG等工具的使用,帮助我对于每个局部方法都进行充分测试,保证正确性。

第四单元,没有学新的测试方法,但是把之前的测试手段,比如,Junit,再次熟悉使用了一下。
我相信,经过这几个单元,我逐渐学会了如何面对较为大型程序的精准、全面测试。

(4)总结自己的课程收获

1.编程能力的提高

我从什么都不会的java菜鸟到可以独立完成上千行的代码满足需求,编程能力确实进步不少。纸上得来终觉浅,编程能力的提高,一定是日积月累的训练得来的,而OO课程帮助我做到了这一点。

2.测试能力提高,意识到了测试的重要性

所谓 “完成作业一时爽,强测互测火葬场”,说的就是测试不充分的情况吧。

从过了中测后自信满满地开始养老到过了中测后还提心吊胆地多方位测试,我对于测试的态度产生了很大的改善。

另外,正如之前提到的,我还掌握了不同的测试手段,提高了测试能力。

同时,还提高了自己的心理素质(比如,在ddl截止前两小时内还发现了bug......)。

3.面向对象的思想方法与技巧

通过上课听讲和阅读相关的书籍,我们学到了一些思想方法。而实践操作,才让我们融会贯通,真正理解并掌握了面向对象的思想方法与技巧。从简单的类的继承以及接口的实现,到尝试不同的设计模式,有效地对程序进行测试,我们确实进步不少。比如,在第四单元作业中,很自然地就会想到单例模式的使用来改善程序,我想,这也是面向对象给我们的思想上的提升吧。

4.代码风格好转,这也得益于Checkstyle的使用,虽然有时候这些规定看起来比较折磨人,比如,每行的字符长度不得超过80个字符,但是,正是这些要求使得我不再像以前一样,一个函数莽到底,而是注意:方法长度不超过50行等。所以,我以后在写代码时,也会注意到这些问题,养成好的习惯,提高代码的可读性。

(5)立足于自己的体会给课程提三个具体改进建议

a.第一个建议是:

合理安排课程难度和时间。

可以较小难度阶梯或者在作业难度比较大时,给同学们一些具体可行的思路;

另外,有些作业难度比较高,应该适当延期,合理调整作业期限,而不是突然延期之类,例如,每个单元第一次作业简单一些,最后一个难一些,前者可以缩短,后者可以延长,这个事先可以定下来。

b.第二个建议是:

关注上机实验的时间和难度。

比如,我们这学期的理论课在周五上午,上机在周五下午,有时候难度偏大,理论课的东西还没有理解消化完全。

另外,前三次难度较大,出现了没时间完成的情况,所以,上机实验的难度梯度也值得关注。当然,在前几次后,上机体验得到了改善。

c.第三个建议是:

给每个单元每次作业架构及时的反馈信息(现有反馈主要是正确性)。

虽然每次作业会有强测以及互测屋,但是不代表你看到的代码就是优秀的吧,你这次作业的代码架构是好是坏难以得到评价(即使强测互测通过,也不一定是好的架构)。所以,不好的架构仍然可能进入下一次作业。

比如,我在电梯这一单元的架构就不是很友好,直到结束后很久,再看到一些优秀的架构,才明白如何加以改进。

所以及时的反馈一些优秀的设计方法与架构,可以让大家更好地学习同学们的优秀代码,改进自己的设计。不过,这样的话,助教的工作量比较大。所以,可以先只看一些大佬的作业,再给同学们反馈一些优秀的架构。

可以暂时不需要源码,我觉得讲解一些具体实现方法与思路已经足够(虽然这学期老师有时候也会给些提示,但讲的有点少,可能同学们也没理解),等这一单元结束再公布源码也不迟。

转载于:https://www.cnblogs.com/Puzzled-Bubbles/p/11075607.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值