• oo前三次作业总结


    OO作业总结(1-3)


    前言

    这三次作业,是我第一次,真正的系统性接触和学习Java,在这三次作业中,我对Java的理解也逐渐加深,也逐渐领悟到了从C语言入门的我在应对工程代码方面的不足,这一次学习到的度量分析又为我打开了新的大门。


    (一)代码的度量分析

    (1)第一次作业

    第一次作业,内容是多项式计算,其中并没有涉及到复杂的计算原理和程序逻辑,而是在输入和输出的处理上略有难度。对于当时不懂正则表达式的我来说,我的第一次作业使用了状态自动机。

    在第一次作业中,分为3个类,Input类处理输入,Polynomial作为主类,Term类表示单个多项式。之前我一直觉得这份代码写得还算不错,直到我最近学习了Java代码的度量分析,才惊觉之前的代码有着诸多缺点。

    接下来贴上分析结果截图

    显然,我的循环复杂度Cyclomatic complexity)在Input类里过高了,也就是说我的Input类功能不够单一,做不到功能内聚,需要再划分为更小的模块,才能减小程序的漏洞数。

    这次由于将状态机封装进了Input类,导致的Input类复杂度过高,以后的状态机或许可以分成多个简单类的交互。

    (2)第二次作业

    第二次作业,内容是傻瓜电梯的调度。虽然指导书刻意复杂化了代码逻辑,但其实代码非常之简单,只需要每次处理当前请求时,将请求队列之中的同质请求消除就可以了。

    在这一次作业当中,我也意识到了try,catch的重要性,在面临可能数组越界或是访问空指针的危险情况时,try and catch变得尤为重要,这样可以快速帮助锁定错误所在,希望以后我也能像各位大牛一样将try catch运用熟练。

    下面贴上类图和度量分析结果

    本次代码设计上的主要问题从度量分析看来主要来自于Request类的SelfCheck方法,但是本人点进去仔细查看SelfCheck函数后却并不认为其有什么问题,代码如下:

    1 boolean SelfCheck(double LastTime)
    2 {
    3     if(Time<LastTime)return false;
    4     if(Type==0 && (Aim==0 || Aim>10))return false;
    5     if(Type==1 && (Dep<=1 || Dep>10))return false;
    6     if(Type==2 && (Dep==0 || Dep>9))return false;
    7     if(Time>(1L<<32)-1)return false;
    8     return true;
    9 }

    这个功能仅仅用来判断Request类是否合法,而由于限制条件的众多,代码内的众多if语句也难以避免,况且该功能十分明确且简单,个人不认为这段代码有不妥的地方。

    以上就是这次分析的结果,个人认为这次的情况正好对应了维基百科上所说的对于特殊情况,代码的循环复杂度可以酌情放宽

    (3)第三次作业

    关于第三次作业,我需要提前申明的是,本次作业我一开始的想法就错了,导致后面回天乏术。具体原因会在第二部分的bug互查说明,这里仅仅分析代码的性能。

    下面贴上度量分析结果:

    下面贴上Watcher中的FindDir作为示例:

     1     Request FindDir(double time)
     2     {
     3         if(time==L.GetLast()+1 && L.IsOpen())
     4         {
     5             //System.out.println("LastTime="+L.GetLast()+"  time="+time);
     6             L.Change(time);
     7             //System.out.println(L);
     8             if(Temp.GetFor()==0)
     9             {
    10                 if(L.GetCnt(L.GetPos())>0 && L.GetReq(L.GetPos(), 1).GetAim()==L.GetPos())
    11                 {
    12                     OUT.Add("VALID", 0, L.GetReq(L.GetPos(), 1), L.GetPos(), time);
    13                     L.pop(L.GetPos());
    14                 }
    15                 if(F[L.GetPos()].GetQn()>0 && F[L.GetPos()].GUP(1).GetDep()==L.GetPos())
    16                 {
    17                     //System.out.print("First:");F[L.GetPos()].GUP(1).Print();
    18                     OUT.Add("VALID", 0, F[L.GetPos()].GUP(1), L.GetPos(), time);
    19                     F[L.GetPos()].PopQ();
    20                 }
    21                 if(F[L.GetPos()].GetDn()>0 && F[L.GetPos()].GDN(1).GetDep()==L.GetPos())
    22                 {
    23                     OUT.Add("VALID", 0, F[L.GetPos()].GDN(1), L.GetPos(), time);
    24                     F[L.GetPos()].PopD();
    25                 }
    26                 while(L.GetCnt(L.GetPos())>0 && L.GetReq(L.GetPos(), 1).GetAim()==L.GetPos())
    27                 {
    28                     OUT.Add("#SAME", 0, L.GetReq(L.GetPos(), 1), L.GetPos(), time);
    29                     L.pop(L.GetPos());
    30                 }
    31                 while(F[L.GetPos()].GetQn()>0 && F[L.GetPos()].GUP(1).GetDep()==L.GetPos())
    32                 {
    33                     OUT.Add("#SAME", 0, F[L.GetPos()].GUP(1), L.GetPos(), time);
    34                     F[L.GetPos()].PopQ();
    35                 }
    36                 while(F[L.GetPos()].GetDn()>0 && F[L.GetPos()].GDN(1).GetDep()==L.GetPos())
    37                 {
    38                     OUT.Add("#SAME", 0, F[L.GetPos()].GDN(1), L.GetPos(), time);
    39                     F[L.GetPos()].PopD();
    40                 }
    41             }
    42         }
    43         //System.out.println("haha="+L.GetAim()+" "+L.GetPos()+" "+L.IsOpen()+" time="+time+" last="+L.GetLast());
    44         //L.Print(time);
    45         if(L.GetAim()==L.GetPos() && !L.IsOpen())
    46         {
    47             //System.out.println("hahahahahahahhahaha");
    48             //L.Print(time);
    49 
    50             //L.Print(time);
    51             int aim1=0, aim2=0, aim3=0;
    52             if(time==L.GetLast())
    53             {
    54                 int finish = L.Finish();
    55                 if(finish!=0)
    56                 {
    57                     L.Direct(L.GetAim()-L.GetPos()==0 ? 0 : L.GetAim()-L.GetPos()==1 ? 1 : -1);
    58                     return new Request(-1);
    59                 }
    60             }
    61             //L.Print(time);
    62             for(int i=1;i<=10;++i)
    63             {
    64                 if(L.GetCnt(i)>0 && (aim1==0 || L.GetFront(i).GetSeq()<L.GetFront(aim1).GetSeq()))
    65                     aim1 = i;
    66                 if(F[i].GetQn()>0 && (aim2==0 || F[i].GUP(1).GetSeq()<F[aim2].GUP(1).GetSeq()))
    67                     aim2 = i;
    68                 if(F[i].GetDn()>0 && (aim3==0 || F[i].GDN(1).GetSeq()<F[aim3].GUP(1).GetSeq()))
    69                     aim3 = i;
    70             }
    71             if(aim1>0 && 
    72                     (aim2==0 || (F[aim2].GetQn()>0 && L.GetFront(aim1).GetSeq()<F[aim2].GUP(1).GetSeq())) && 
    73                     (aim3==0 || (F[aim3].GetDn()>0 && L.GetFront(aim1).GetSeq()<F[aim3].GDN(1).GetSeq()))) return L.GetFront(aim1);
    74             if(aim2>0 && 
    75                     (aim3==0 || (F[aim3].GetDn()>0 && F[aim2].GUP(1).GetSeq()<F[aim3].GDN(1).GetSeq())) && 
    76                     (aim1==0 || (L.GetCnt(aim1)>0 && L.GetFront(aim1).GetSeq()>F[aim2].GUP(1).GetSeq()))) return F[aim2].GUP(1);
    77             if(aim3>0 && 
    78                     (aim2==0 || (F[aim2].GetQn()>0 && F[aim2].GUP(1).GetSeq()>F[aim3].GDN(1).GetSeq())) && 
    79                     (aim1==0 || (L.GetCnt(aim1)>0 && L.GetFront(aim1).GetSeq()>F[aim3].GDN(1).GetSeq()))) return F[aim3].GDN(1);
    80             return new Request(-1);
    81         }
    82         //L.Print(time);
    83         return new Request();
    84     }

    可见由于之前的逻辑分析失误,导致了if-else语句的滥用,由此可见,在写代码之前,有一个清晰,简单的框架是写好程序之必备,而本人在这一方面则反了经验不足的错误,以为简单按照描述来写就行,结果表明不成熟的程序框架会导致大量的冗余代码和复杂的·逻辑判断,今后必须引以为戒。


    (二)bug分析

    (1)第一次作业

    第一次作业本人存在一个bug,那就是没有判断程序最开始是空格的情况。因为本人的最初版本程序要求程序第一个左括号,所以空格会导致判断为ERROR。

    由此可见两个问题:

    1.对内置函数不熟练,本来可以用string.replace来解决

    2.逻辑思维不够严密

    (2)第二次作业

    第二次作业本人由于对助教意思的误解,对于同质请求没有输出#SAME,这是一个incomplete

    (3)第三次作业

    而第三次作业,本人为了完全再现电梯接受请求的反应,决定按照时间的运行来模拟,而这时由于一开始得考虑不周,本人犯了一些严重的错误:

    1.电梯请求放在了电梯类,楼层请求放在了楼层类,导致交互时的代码非常繁琐

    2.由于一开始的考虑不周,放弃了请求队列的想法,本意是想每次接受请求时只与当前请求比较,结果发现请求有可能排成队列

    3.对于时间和请求的交互请求关系考虑不周,导致出现电梯没有及时改变方向,出现runtime error

    综上所述,本人的第三次作业并没有达到理想要求,并非是修补bug可以解决的问题需要推倒重来。

    以后也要吸取教训,对待程序一定要思考清楚后开始写,否则仅是浪费时间而已。

  • 相关阅读:
    2018年4月22日笔记
    2018年4月19日笔记
    2018年4月17日笔记
    2018年4月14日笔记
    2018年4月12日笔记
    课堂练习找水王
    评价软件
    第十一周进度条
    典型用户场景、用户场景描述
    构建之法阅读笔记04
  • 原文地址:https://www.cnblogs.com/xuyibo1/p/8716813.html
Copyright © 2020-2023  润新知