一:基于度量分析自己的程序结构

第一次作业类图以及度量图:

 

 

类图分析:

  从类图分析,第一次作业虽然方法多,并且方法间只传递信息,但是只有一个类,可以看出第一次作业仅仅是面向过程含有了一些面向对象的思想。

复杂度分析:

  由于第一次作业是一个类干完了所有活,所以部分方法的Iv(G)高,意味着这些方法的耦合度高,这是面向过程思想的结果。部分方法的v(G)较高,即圈复杂度高,是因为这些方法中If-elsefor循环嵌套层数较多,这将使代码测试所需的最少路径条数剧增,且使程序产生错误的概率增加。

 

第二次作业类图以及度量图:

 

 

 

类图分析:

  从类图可以看出,第二次作业优点是:面向对象的思想比第一次好多了,第二次有三个类分别为:处理输入的类,多项式类(Poly),求导类。但是缺点也很明显:设计模式的欠缺,代码复用性差,没有因子类,且没有把所有因子抽象出一个公共的抽象因子类,这导致了第三次作业重构的悲剧。

复杂度分析:

  程序的ev(G)(除了个别方法稍高)基本不高,这表示程序模块化以及结构化方面做得还行。程序的iv(G)方面,大部分模块的iv(G)都比较低,有四个方法的iv(G)较高,分别是Poly类的jianhua()judge()方法,xn()xntwo()方法,这两对方法的耦合度高,且都在同一个类里,这体现了面向过程思想还未剔除干净,但是大部分的iv(G)都比较低,这是进步了了的。程序的v(G)方面,由度量图可看出很多模块的圈复杂度高,仔细分析这些模块的代码发现,他们都有一个共同特征:有较多的If-elsefor循环嵌套,且嵌套层数多,这和第一次一样,显然那时候我没有意识到这样做的坏处。

 

第三次作业作业类图以及度量图:

 

 

类图分析:

  从类图分析,第三次作业的类很多,并且具有层次性,高内聚,低耦合。每个类独立性强,各司其职。因为第二次作业代码复用性极差,因此第三次作业是重构了的,采用的抽象工厂模式,即所有因子有一个抽象公共类,所有复合项有一个抽象公共类,且每种因子和复合项都有自己的求导方法。第三次作业可以说完全摆脱了面向过程思想,并且在设计模式上也有了很大进步。

复杂度分析:

  模块的iv(G)基本都很低,模块耦合度低。模块的v(G)基本都很低,但也有两三个模块的圈复杂度稍高,还是If-elsefor循环嵌套的问题,这三次作业圈复杂度的问题都是If-else和for循环嵌套层数多的问题,这三次都没有意识到这个问题,经过这次的教训,以后都不会再出现这个问题了。

 

二:分析自己程序的bug

  首先,总体分析发现,这三次作业中公测和互测的bug总数是呈递减趋势的,并且三次作业的bug中绝大多数都是粗心导致的小bug,稍加修改即可。只有一个不是粗心的bug是正则爆栈问题,后来很轻松的就解决了这个问题。下面来具体分析这三次作业的bug

  1. 第一次作业:出现的bug只有两种,第一种是对输入的字符串使用trim(),导致把开头输入的\f,\v等给去掉了,这样只要在字符串开头输入\f,\v,就不会被判断成WRONG FORMAT,第二种bug是正则爆栈问题。第一种bug所在的类是处理输入的类,第二种所在的类则是判断输入字符串合法性的类,两种bug特征均为用法的不熟悉。第一种bug产生原因是以为trim()只会去掉开头和结尾的空格,第二种bug产生原因是不了解正则的机制,过长的正则或者写的不好的正则会导致回溯过多导致爆栈,解决办法是优化正则或者使用独占模式。
  2. 第二次作业:出现的bug也是两种,第一种是纯属太粗心导致的,即:判断某个字符是不是数字时,把数字9的ascii码记错了,所以判断‘9’时不会被识别成数字,这确实很不应该。第二种是在提取因子的指数这一步,写正则时,忽略正负号了,导致只有正指数能被提取出来。第一种bug特征为纯属粗心,第二种为默认数据是某种格式。
  3. 第三次作业:只有一种bug,就是关于[+-]\\([+-]的符号处理问题,例如+(-x)这种,去括号前取出符号时,没有考虑这种情况。问题所在的类以及方法为各因子类的Fh方法(去括号前取出符号)。

  综合上述分析发现,这三次的bug和设计结构没什么关系,从分类树角度主要分为以下三类:(1):粗心大意。(2):语法以及用法的不熟悉。(3):处理数据时,数据形式分析不完整。

 

三:分析自己发现别人程序bug所采用的策略

第一次互测,所采取的策略为俩步:

  第一步,把自己总结的容易出现的bug以及自己已知自己和别人出现的bug记在记事本上,然后一个一个试。

  第二步,直接看代码找bug

第二次互测,所采取的策略很简单:

  写一个对拍器。直接把所有人的代码一起跑,将结果和对拍器中matlab的计算结果对比,不同则把错误信息输出到文件中,进行人工审核。

第三次互测,所采取的策略为策略二的改良版:

  不仅使用对拍器,并且根据每个人的代码设计结构手动设计测试用例。显然第三种策略最为有效,第一种策略真是不堪回首,工作量巨大,简直不要太蠢。第二种策略采用自动化方法,不用人为找bug了,节省了巨大的时间和空间,但是这种方法有两个弊端,第一:碰到bug很少很少的巨佬时,对拍器随机生成的数据显得乏力,漫无目的,效率低,且不容易找出bug。第二:不能锻炼自己找bug的能力。第三种策略在第二种策略的基础上,加上了根据每个人的代码设计结构手动设计测试用例,这就解决了上述两个弊端了。

 

四:Applying Creational Pattern

  三次作业在对象创建模式方面有了比较大的进步。

  第一次作业:刚接触面向对象思想,因此作业基本是面向过程加一些面向对象,没有设计模式可言。面向过程体现在我把代码只分为polymain两部分,poly承担了判断合法性以及求导,化简等功能,面向对象体现在我对要实现的每一种功能写了一个方法,并且每个方法间只传递信息,并不会出现参数传来传去。总的来说第一次作业基本是面向过程向面向对象的转变初期吧。

  第二次作业:我开始把poly,求导以及处理输入分别写了一个类,这便体现了面向对象的思想,遗憾的是,这种做法复用性不好,代价就是第三次作业重构。复用性不好的原因在于设计模式的缺陷,我并没有把几种类型的因子抽象出来,还是一个poly类。

  第三次作业:我重构后,采用的设计模式是工厂模式中的抽象工厂。现在具体说明一下怎么重构的。第三次作业我有一个专门处理输入的类(Judge),有一个主类(Main),有一个总的求导类(Dfx),有两个基本因子类(Sincos (三角函数)和XorInt(幂函数)),有三个复合表达式类(Qtao(嵌套复合项),Muitiple(乘复合项),Addsub(加减复合项)),这五个类分别都有自己的求导方法。抽象工厂模式体现在,我把三角函数因子和幂函数因子抽象成一个公共的基本因子,把加减复合项,乘复合项,嵌套复合项抽象成一个公共的复合项,但是这些子类里又分别有自己的求导方法。

 

五:总结与反思

  这三次作业有好也有坏吧,好体现在每次作业都比上次作业更加面向对象,且在设计模式的使用上越来越好,还有就是在找bug的能力越来越强。坏体现在每次都有粗心导致的bug并且掌握的设计模式也就那么几个,对面向对象的理解也不是那么深,因此作为菜鸡的自己要加油多学好的设计模式以及编程思想。

 

posted on 2019-03-27 17:18  bug2017  阅读(148)  评论(0)    收藏  举报