使用了masteruml插件来生成类图和metrics插件分析代码
第一次作业
1、UML类图
>在第一次作业中,使用了两个类,代码中有没有使用的变量与函数,为平衡两个类的内容,我将输出函数放在了多项式类中,但是仍然不够平衡。
2、量化分析:
>处理字符串输入的过程,按照面向过程的思路来写,嵌套的判断条件过多,时间空间复杂度都比较高,写的并不简洁。
3、程序中的bug:
公测bug:压力测试,在数据量较大的情乱下,我对计算结果进行了取模运算,导致了公测出错。错误来源处于多项式计算的过程中,在最终获得运算结果并存入结果数组中,为了保持与输入相同的最多六位数的要求,我对结果进行了取模运算,这与程序中类的设计没有太多关联。
被发现的bug:对于一种特殊情况(指导书没有说明)没有在Readme中说明的incomplete错误。这次bug提示我,一定要好好写readme,尽可能的覆盖程序的所有边界情况,防止出错。
自己的程序还是存在问题,在输入时没有限制输入的最多数目,将数组开成了100大小,且数组的操作并没有包括在trycatch代码块中,如果多项式个数非常多,程序会出现crash
4、分析别人bug的方法:
分析别人bug的方法,首先,我将我自己的测试用例都尝试了一遍,结合其指导书上 的要求,找到了其未处理指数为负数的bug(同时也说明公测并没有涉及到这个问题);其次,我阅读了TA的代码,在代码中,负责处理输入的模块并不是由正则表达式来完成的,在抱着感兴趣的态度阅读了与正则表达式不同的有限状态机的实现过程中,画出了流程图,并找到了在有限状态机过程中存在的一个计数错误问题(多项式超过50项仍能计算)和一个输出错误问题。我的测试过程是,首先测试了几个压力测试,然后将我在编写程序时用到的测试样例,可能出错的点进行了测试,最后看代码中会不会出现问题。
5、心得体会:
在第一次作业之前,只使用java编写过一个简单的商店管理系统,但是第一次作业写的仍然不够OO。主要的代码都在Computeploy类中,两个类并不均衡。输入部分,采用正则表达式进行判断是否满足要求,为了防止爆栈,将正则表达式进行了两次拆分;计算部分,我参考了C语言,写的比较面向过程,采用比较传统的字符串处理来处理数据,然后进行计算,对result多项式进行输出。
优点是,对数组进行存储的时候比较方便,可以直接使用;正则表达式分成了两个;在ploy类中实现的打印方法,相对来说更加均衡
缺点是,空间利用率不高,数组开的比较大;没有考虑到超过最大限制数目多项式的存储问题;计算过程偏向于面向对象;正则表达式容易出现爆栈现象。
第二次作业:
1、uml类图:
>将电梯与楼层抽象出来,用request和requestarray来分析请求,最终串在调度器类中;但是有个失误,就是电梯的运行过程比较简单,所以将调度方法写在了电梯类中,这也直接导致了第三次作业无法使用第二次代码。
2、量化分析:
>这此作业还是在处理字符串的方法上篇幅过重,查了一下Mccabe Cyclomatic Complexity的含义,用无向图的方式来分析结构复杂度,然后看到了自己的三分代码都爆了红,道阻且长。
3、bug:
公测bug:由于处理输入时采用的先读取进队列,再进行判断的方法,导致与要求的直接判断方式不符,导致了四个点错误;另外两个点的错误都是在0时刻同质请求的忽略,在判断同质请求时的判断语句没有写好,将所有0时刻的请求都判断为了不同质。
被发现的bug:还是Readme的问题(emmm),由于对OJ期望输入的不了解,我在写Readme时,#后面输出了详细的错误信息;但是在OJ输入样例错误之后,我在代码中将#输出代码注释了(emmmm)但是没有同步进行Readme的修改,然后被报了错误,还是Readme的问题。
4、心得体会:
这一次的作业,从指导书来看,面向对象的思想还是有的。但是在实际的代码编写过程中,还是有很多编写面向过程的思维想法。在整体的编写过程中,我将其中的request和requestlist类用读取输入时请求队列的生成,在这两个类的实现过程中,我忽视了在请求未进入队列就进行判断正误的操作,使得在公测时部分点因为ERROR的输出顺序有误出现了错误;在Lift类,我构建了电梯常见的10层停靠按键和run方法,虽然这个调度方法应该在Scheduler类中进行编写,这里也是一个没有设计好的典例。在我的设计中,我类比真正的电梯,模拟电梯和实际楼层,我觉得这是实际设计时比较好的设计模式。但是,对于调度器这个抽象出来的行为,我并没有设计好。其次,在测试的时候,我遗漏了初始值为0时的同质请求的判断。
其次就是对OO课程时间安排上的反思,由于周末事情比较多,我开始写电梯的时间比较晚,导致最后的Readme还是存在部分空缺,不够完整。于此同时,需要吸取的教训是,在git上不同版本对应的文件需要实时更新才行。
第三次作业:
1、uml类图:
>沿用了第二次作业的基本架构,但是简化了电梯的功能模块,主要的调度器功能都写在了调度器类中,并且分了好几个方法来防止单一方法过长,这种做法在进行debug的时候省了比较多的功夫,简单的一行sysout输出就可以判断是那个模块出了问题;但是在debug的时候,没有想着调增代码结构,只是在原基础上增加,导致代码过长。甚至出现了低级错误.....
2、量化分析:
>如前面所说,调度方法在设计的时候没有考虑到很多的代码,也没有重构,这两个指标表现的还是很差。然而现在并没有什么代码重构的经验,还是要在接下来的coding中多积累。
3、bug:
公测bug:由于一个很蠢的错误导致的公测没有过一个点,想来也是有趣(呸),在看到每次输入的多行请求只能以(1,FR,1,0)开始,我很快将其单拎出来处理,然后少输出了一个/符号,导致公测全部没有通过。
4、心得体会:
首先,这次作业将我的毛病表现的很明显。最重要的问题,粗心大意,在吸取了第二次作业没有看讨论区的教训,对讨论区中出现的详细描述都进行了排查和debug,但是每次都遗漏了第一行的输出信息,导致了悲剧的产生。其实,仔细想想,细心这个问题一直很困扰我,在计组课程中,也因为一个非常微笑的bug导致了一次测试没有通过。这是我这次作业无效收获的最大的教训和经验。
其次,在debud的过程中,我也意识到了一次只解决一个bug的弊端(或者说,痛苦)。在debug的过程中,感觉就像是在一个修补一个破烂不堪的花瓶,这里需要打洞去填补,之后会导致其他的地方需要重新修补,反复进行。这从侧面表现出了一个好的设计从一开始就提供的优势。最近,我在读《重构》这本书,虽然我只看了前三章,但是第一章的案例开始看的时候,我觉得写的挺好的(捂脸),但是作者从变量名到类的结构再到每个类之间方法与代码量的平衡,提出了很多很多的意见。移除暂时性的变量,改变每个类中的方法的具体位置。在这次代码中遇到的debug难度与大工程大项目的debug难度完全不能比,如此多人共同协作的大项目也应该更难吧。在本次代码中,Scheduler类的长度明显过长,按照重构的要求来看,还需要很大的工作量。
再其次,这次的测试程序做得并不够,测试程序应该覆盖的越全面越好,但是这次连最基本的错误都没有发现,需要反思。
再再其次,由于第二次作业将调度器写在了电梯类中,导致了第三次作业无法按照要求按照继承机制重写调度器方法,接口类与toString在设计的时候也并没有发挥本质的作用。
总之,这次作业写的十分失败,十分失败。熬夜并没有换来好的结果。
接下来的展望
多线程的挑战也已经到来了,现在还领略不到面向对象思想的精髓。找时间看完《重构》,结合几个小例子,争取在后面的作业中进行一些实践,或者课程结束后,把自己写的这些杂乱不堪的代码给重构一下。细心,比什么都重要。