OO前三次作业总结

一、多项式加减

1.程序结构

可以看到,程序的Cyclomatic Complexity过高,主要是因为我一些方法内部的分支过多,应该尽量使逻辑更简单,通过适当的分析减少判断的分支数目。

 

 类的设计完全依照讲义上的建议,还是比较清楚明白的。computepoly作为主类完成计算,其中要用到checkinput类检查输入,poly类构造一个一个的多项式来组成polylist,再调用poly类的运算方法完成计算。

2.BUG分析

第一次作业没有被找到BUG,倒是很快发现了别人有两处特别明显的错误,且都是关于输入检查的BUG。仔细一看发现原来他并没有使用课上建议的正则表达式来检出输入,而是使用了复杂繁琐的if, else判断语句。这样一来,在考虑各种错误的输入时就需要写很多的分支语句,很容易漏检。

 

3.心得体会

初次体会了面向对象的编程思想。和以前固化的过程式编程思维有很大的不同,但却更接近实际,重点在于对象的构造和对象间的交互,而不是像上帝一样从头到尾的控制整个流程,管理途中使用的每一个函数(方法)。

学习了正则表达式。在网上自己扒拉了一些说得还算详细的正则表达式教程,然后一边学习一边实践,仔细地写出了本次作业用的正则,主要分了三个层次。首先是用来匹配一个项的正则,也就是匹配一对小括号及其所包含的内容,记为regex1;然后以regex1为字表达式构造匹配一个完成多项式的regex2,即一对大括号及其所包含的内容;最后用regex2构造匹配整个输入的正则表达式regex3(其实这样只是为了让自己在构造表达式时有个清楚的逻辑,我觉得完全可以一次写完)。但是,后来发现自己没有考虑爆栈的问题。仔细思考后默默注释掉了regex3,改为使用regex2一个多项式一个多项式地匹配。当然,这样做的前提是先验证了一下当输入为一个包含最多项数的、每一项的数字长度都最大的多项式时,不会出现爆栈的问题,然后才是安心地进行分步匹配。

 

二、单部傻瓜电梯

1.程序结构

 除了出现和第一次相同的圈复杂度过高的情况之外,还出现了嵌套过深的情况。这主要是因为我在command方法中对电梯上一次状态和本次状态(STILL or UP/DOWN)、上一次动作完成时间和本次请求发出时间(中途是否出现了电梯空闲)等等因素做了十分复杂的讨论,不过还好思路是清晰的,只是还可以进一步优化。

 

 本次实现了指导书要求的几个大类:电梯类负责根据调度器类发出的命令生成一个本次调度的MoveRecord,所有的MoveRecord最后组成一个movelist以供输出;楼层类简单地记录楼层按钮的情况以供调度器类作为同质请求的判断依据(电梯类也有类似的记录);请求队列类将所有合法的请求按照输入顺序保存进一个队列供调度器进行调度;最后,调度器类依据指导书的要求完成核心的调度任务。

2.BUG分析

这次作业被人找了一个BUG,是因为前导零的问题。我的程序能够接受的前导零长度其实是在readme中有说明的,但是我这次git push完readme之后忘记去oj平台上再拉取一下新的commit了(真是zz),导致拿到我程序的同学只能看到我的一个裸程序,什么输入说明、要求都没有。于是,意料之中的,被找了前导零的BUG。

找到的他人的BUG是关于对超过一百行的请求的处理问题。他的readme中说明只处理前一百行的请求,但是当我输入一百多行的时候,他的程序对前一百行的处理出现了一点问题,没有得到正确的输出。应该是在考虑特殊情况时的逻辑出现了一点小问题。

 

3.心得体会

得到了巨大的教训,在push完后一定记得去oj上再拉取一下。

设计对象时尽可能抛弃固有的“把握全局”的上帝思想,只需要考虑这个对象要做什么、要提供什么、要存储什么就行了。一定要先想方法,再想完成这些方法需要记录的属性。比如电梯类,我一开始直接想的是有什么样的属性,于是就真的傻瓜式地耗费了很多空间来记录每一个按钮亮着的时间——每个按钮都有一个(由一个个闭区间组成的)亮着的时间区间数组,这些闭区间本身又是区间类的一个个实例,就很傻瓜。后来看到别人就记了一个按钮灭的时刻(一个简单的double数据类型),就搞定同质请求的判断时,我觉得自己之前先属性后方法的思考真的补星,受教了。

三、单部可捎带电梯

1.程序结构

 这次又出现了新的问题:参数的数目过多。原因是在重写新的调度方法时,发现有太多需要用到的东西:用电梯的状态判断是否可捎带,用电梯和楼层的按钮状态判断是否同质,从请求队列中生成主请求,根据当前主请求找出可捎带的请求等等,所以,这一个方法就传了一堆的参数,很是麻烦。

 

 总体结构和第二次作业没有区别,核心是继承了第一次的调度器类后重写的command方法,写得十分繁琐,但好歹也过了公测。

2.BUG分析

被别人找了两个BUG,都是让我心服口服、无可申诉的。首先,最致命且明显的错误,就是明明输入的时刻可以是很大的整数,我却在强制类型转化时神经地用了Integer.parseInt. (但是还好,只是在检测第一条请求的时候用了,其他的还是double)第二个BUG更揪心。是在提交要截止的时候,突然拿到一个样例,一跑,发现和标准输出不对。这下可够刺激了,开始火急火燎地debug。混乱中庆幸大脑没有发生故障,兴奋地找到了BUG:原来,问题出在对主请求的选择上。在看到指导书2.3中的最后一个例子时,原文轻描淡写地一句带过一个可能产生大BUG的关键点——“此时应选择队列中未执行的第一条请求(FR, 4, DOWN, 2)作为主请求”。于是,天真如我,在执行完一个主请求及其所有捎带请求(我的程序中,主请求本身也是其捎带请求,相当于没执行主请求,所有被执行的都是捎带请求,主请求只是作为分段执行各请求的标志)后,直接选择了当前未被执行的队列中的第一条请求为主请求,殊不知它很可能是一个同质的请求,应该被舍弃。(应该也有些同学犯了和我一样的错误吧,没有就当我没说,打扰各位大佬了)

找到的别人的BUG是一个由于粗心导致的错误:没有按指导书上的要求对首条指令进行判断。这样的错误实在不应该,提醒大家虽然指导书可能不那么readable,但还是要通读一下,尤其注意加粗的强制要求。

 

3.心得体会

一定要在写关键逻辑前想清楚这样写的合理性,不要理所当然不假思索地就写了。关键逻辑的漏洞是很致命的,因为你之后可能会构造各种进攻小细节的输入,但就是不会对自己的关键逻辑产生怀疑,觉得这都是大方向,应该不至于出错。

脑子浆糊时就先别写了。脑子清楚时一定不能在写某个复杂方法的内部逻辑时中途停下做其他的。否则,回过头来时已经断线的你是很难清楚地知道何从“续貂”的。

 

转载于:https://www.cnblogs.com/yuanjinglin/p/8711893.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值