前三次作业总结——分析与反思

一、写在最前

OO课程,时至现在,完成了三次作业。回头看这三次作业,对于我个人来说,每次可以说都是有新的挑战的。第一次作业多项式的计算的难点是从java零基础与编程全忘光的小白速成为一个能够使用有限状态机和简陋到不能再简陋的面向对象思想的新手村战士;第二次作业傻瓜电梯,发现自己居然要从0开始完成五个类的庞大工程——“建立框架一整天,核心算法俩小时”便是第二次作业的真实写照。第三次作业开始前,本以为自己可以舒舒服服地写核心算法了。但是ALS智能电梯真的比自己这个可怜的小脑瓜是要“little smart”一些的。

如下是两次作业在作业完成时所做的总结,第一次作业当时仅作bug分析,便不再单独贴出来。
第二次作业总结
第三次作业总结
接下来呢,我们先度量分析下三次作业的程序结构,体会其中的面向对象的思想的发展变化(可能在我的代码里并没有,嘤嘤嘤)。



二、度量分析代码程序结构

(一)Metrics插件使用

首先,我们按照网络上的各种教程安装好Metrics插件,打开某个工程的Metrics View。我们会看到这个界面:

望着这满屏的数据,我们又该如何分析自己的代码呢?这么多的数据,哪些数据对我们有用呢?经过我的简单分析,我觉得以下几个指标可能对我们的代码结构有指导意义。

1.

这个指标分析了每个类的方法所占有的权重。从该指标可以看出自己各个类的侧重。

2.

这个指标可以一目了然地看到每个类中所含有的非静态方法数。

3.

该指标下可以看到每个类中含有的静态方法的个数。

4.

类的代码长度与方法的代码长度可以最直接地反映出来自己的代码结构。

(二)三次作业的度量

第一次作业

类图

第二次作业

类图

第三次作业

类图

以上为三次作业中各次的类图。从上述的图中中我们可以发现三次作业的一个发展变化:
三次作业越写越丑了!

(三)度量分析

经过同学提点,我了解到在进行度量分析时首先要关注自己的红色指标。我发现三次作业的共性问题是圈复杂度高。

圈复杂度“用来衡量一个模块判定结构的复杂程度,数量上表现为独立现行路径条数,即合理的预防错误所需测试的最少路径条数.

我三次作业的圈复杂度都很高,这说明三次作业的程序代码质量低且难以维护,程序出错误的概率很高。可能的原因是很多地方仍采用面向过程的写法,导致圈复杂度过高。除此之外,第三次作业还存在嵌套块过深的问题。问题如下:

这是由于在进行ALS调度以及电梯运行模拟都是在command方法中完成,其间会出现各个类之间的调用,例如由command->elevator->Req_queue->Request。这样的写法导致了方法调用过深。或许可以这样表达,类的职能不够清晰,类与类之间的关系扁平化不足



三、程序bug分析

第一次作业

自己的bug

【main类,main方法,逻辑考虑不周】
在第一次作业中,被发现了一次crash。Bug出现的原因是这样的:输入部分的过滤本来采用一次匹配检查,但由于在测试中发现正则表达式可能存在栈溢出的问题,因此对于超长正则表达式进行单独判断。而错误也正是出现在所打补丁的代码中。为解决正则表达式匹配超长字符串问题,将超长字符串按多项式右括号进行切分,再对子串增添右括号,套用正则表达式判断。然而,由于拆分后未对项数个数进行判断,即使超出20项也会加入多项式数组,又因为多项式数组只开了25,因此一旦超过25便会数组溢出,发生crash错误。
除去被抓的bug,在上述打补丁模块,还存在另一个bug。由于pattern书写格式如下所写:
pattern="[+-]?"+Bracket+"("+"[+-]"+Bracket+"){0,19}";
致使分割字符串s左花括号外不具有正负符号,仍可进入到计算模块,导致ERROR表达式误判为正确。

第二次作业

自己的bug

公测部分未发现bug,互测者也未发现bug。

被测者bug

【main类,main方法,函数理解存在歧义】
在使用正则表达式时,使用Pattern-Matcher,然后使用m.find(),同时只要求匹配字符串结尾的下标m.end()与原字符串结尾下标相同。由于开发者的逻辑错误,导致只要在正确格式前加入任何字符都认为是合法字符。

第三次作业

自己的bug

1.对t=0,10层UP与1层DOWN无法给出错误报告(公测8的错误)【floor类,get_signal方法,逻辑思考存在漏洞】
由于请求的发送均在floor和elevator中完成,因此格式符合要求便会发送至这两类中。因此10UP1DOWN在floor类中进行判断,引起错误响应。然而由于与主函数的错误响应的兼容问题,写下当t=0时不发送错误的bug。

2.判断是否捎带时判断错误【Subscheduler类,command方法,逻辑思考存在漏洞】
由st10||st20||st21改为(st10||store==10)(公测28,time out),导致某些非捎带请求进入请求队列,且由于其非目标楼层致使电梯进入死循环。

3.队列添加问题【Req_queue类,req_add方法,继承第二次作业错误】
原来为保证入队为顺序队列,虽在请求发送之前就已判断,但在队列方法中仍额外判断当添加时间大于队尾时间时才入队。在ALS中因为双队列方式存在问题。删去即可(公测26,公测30)。

被测者bug

被测者在捎带请求判断中存在问题。如电梯在主请求(FR,9,UP,2)前往9层时,此时(FR,9,DOWN,2)与电梯运动方向不同,不应被捎带,然而被测者却视其为捎带,在电梯到达9层时同时输出。



四、发现被测者bug所采用的策略

使用自己构造的测试样例进行测试,针对测试结果进行代码关键部位分析,发现bug

对代码进行通读,从形式角度对代码逻辑进行分析。发现其中的漏洞,构造合适的数据进行分析

在前两次作业中,在将自己课下构造的测试样例测试结束发现bug后便会去通读代码,除发现bug外,还可以学习别人代码中优秀的地方。但到第三次作业时,第二种策略便显得较为困难了。由于代码逻辑复杂性指数级上升,很难通过自己的认知获取代码较为清晰的理解,即便是花费大量时间也有些云里雾里。这其中既有代码本身逻辑复杂性的上升,同时也因为大家readme并没有真正起到帮助别人理解自己代码的作用。Readme的作用更多体现在扣分与防扣分上。细想起来,与其“readme”的本身含义颇有些格格不入。



五、心得体会

之前的两个总结是在完成作业时便写就的。当时的心境对于那次作业来说可能更为真实一些。当然,当我现在回头看这三次也会有些新的感触。

1、什么样的态度就有什么样的结果。第三次作业心态放松后期果然扑街。每次作业都应有狮子搏兔,亦用全力的心态。

2、readme不应仅局限于说明输入输出。它首先应当起到的作用是让测试者快速理解自己的代码。具体的写法方式还有待探究,但我觉得这样的思路是没错的。



My Buddies,let‘s Fighting For Freedom!!!

posted @ 2018-04-03 23:30  BrandonPan  阅读(203)  评论(0编辑  收藏  举报