北航BUAA面向对象OO第一单元--多项式求导作业总结

1. 第一次作业

1.1 任务与架构

+x - x**5*x**6*5-2

如上例,对含常数因子及幂函数因子的多项式求导

架构:

  • 如何管理对象:

    面向对象的三个关键类:输入处理,主控(MainClass),核心数据管理。

    输入处理+主控都放在MainClass中实现;核心数据管理的任务简单,我利用Map的数据结果Map(<指数值>, <Term>)管理多项式并进行求导derivation()、化简mergeFactor(Term NewTern),打印printTerm()的任务,这一部分的实现耦合在Main ClassTerm Class

  • 如何建立对象之间的层次:

    多项式与项的层次关系:项的线性组合是多项式。这种层次关系很简单,同时不可扩展到复杂多项式的情况。

  • 如何管理和利用层次关系:

    过程式管理

缺点:

  1. 构造多项式,利用大正则直接解析,相当于把构造的任务丢到MainClass处理,带来耦合的问题

  2. 封装不足:MainClass处理了大部分任务

  3. 方法复杂:面向过程思维带来的;利用大正则直接解析,轮子使用不熟练

  4. 不可迭代扩展:第二次作业要求一下来,代码根本“改不动”

String signIntPattern = "[+-]?[0-9]+";//有符号整数
String factorPattern = "[+-]?[0-9]+|x(\\*\\*[+-]?[0-9]+)?";//因子
String termPattern = "([+-]?x(\\*\\*[+-]?[0-9]+)?|[+-]?[0-9]+)(\\*([+-]?[0-9]+|x(\\*\\*[+-]?[0-9]+)?))*";//项
String expPattern = "[+-]?" + termPattern + "([+-]" + termPattern + ")*";//表达式

1.2 程序的metrics

  • design Code Smells:封装不足

  • implementation Code Smell:出现了3个method是complex method

    MainClass.getFirstTerm

    MainClass.getNextFactor

    Term.toString

  • method Metrics


附:

ev(G):基本复杂度,衡量程序非结构化程度,ev(G)高意味着非结构化程度高,难以模块化和维护。

iv(G):模块设计复杂度,衡量模块判定结构,即模块和其他模块的调用关系;iv(G)高意味模块耦合度高,这将导致模块难于隔离、维护和复用。

v(G):圈复杂度衡量一个模块判定结构的复杂程度,根据程序从开始到结束的线性独立路径数量计算得到,v(G)越高,代码越复杂越难维护。

1.3 程序的bug

二学位学生是在开学之后才通知pre预习和给账号,加上转专业第一周就直接实战,我的第一次作业仅仅做到“完成中测”,没有进入强测。

  • Matcher.find()Matcher.group()糊里糊涂的使用带来了很多bug。中测勉强通过了功能测试,但强测只过了3个点,也没有进入互测。第二次作业任务发下来后,我放弃了这个存在很多bug的思路,把时间花在pre预习和完成第二周作业。最后根据第二次作业的架构,重写了第一次作业,企图去修bug。但得知修改代码行数不能过多,遂放弃在原来的垃圾代码上修复bug。

2. 第二次作业

2.1 任务与架构

+x - x**5*x**6*5-2*sin(x)+(3*x**7)

如上例,对含常数因子、幂函数因子、三角函数因子及表达式因子的多项式求导

重写+重新设计架构后,我的后续作业架构一直沿用如下:

1 如何建立对象之间的层次

  • 有什么对象

    • 表达式Poly
    • Term
    • 因子Factor
  • 对象与对象之间的关系是什么

    • Term的加减组合构成表达式Poly(三次作业共有关系)
    • 因子Factor的乘法组合构成项Term(三次作业共有关系)
    • 表达式因子与表达式有递归关系(第二次作业新增)
    • 因子与因子有嵌套递归关系(第三次作业新增)
    • 每一个对象的求导结果之间有什么关系:\(项\stackrel{求导}{\longrightarrow}表达式\)\(因子\stackrel{求导}{\longrightarrow}因子\)

2 如何管理对象

  • 构造

    • 通过递归下降的解析输入字符串的方法,构造不同的对象
    • 考虑到Factor的多种类型,使用简单工厂模式构造Factor
  • 存储(借助容器)

    • Class Poly的主体是ArrayList<Term>Class Term的主体是ArrayList<Factor>
  • 使用

    • 我考虑了对象与对象之间的共性使用:求导、输出打印(有余力时的优化)

    • 求导需要跨类协同:比如说对项Term求导,内部需要完成对Factor的求导,

      Factor间乘法求导法则的组合,产生Poly类的求导结果

3 如何管理和利用层次关系(具体实现)

  • 递归下降以解析输入
  • 简单工厂模式处理<因子>类
  • 求导法则,derivation()方法的实现

整体UML图

Factor的简单工厂结构

2.2 程序的metrics



2.3 程序的bug

重构后作业质量有了很大提高,在强测和互测中都没有bug,但也没有参与hack别人。

别人测bug的方法:

  • 利用特殊用例:如-++-1,0等等
  • 利用评测机自动生成测试用例(但后来我发现:能不能hack到别人,不在于用例有多复杂,而在于有没有关注到一些边界的测试情况。而这些边界情况,一个是关注自测时积累test case,另一个是读别人的程序,关注if else这种情况)

3. 第三次作业

3.1 任务

+x - x**5*x**6*5-2*sin((cos(x)))+(3*x**7)

如上例,对含常数因子、幂函数因子、(带因子嵌套的)三角函数因子及表达式因子的多项式求导

架构

同第二次作业

整体UML图

Factor简单工厂模式

3.2 程序的metrics

  • 由于新增了判断WF的需求,我的parse method复杂了很多


3.3 程序的bug

第三次作业,增加了判断WF的需求。我在写代码的时候,关于WF的处理,我想了几种方法来判断WF

  • 递归下降法的错误处理

  • 在字符串尾部多加一个无关字符%,以示结束

  • 解析了多长的字符串 对比 input的字符串长度(这是研讨课提出的方法)

  • 提前的格式检查

  • 异常处理:throw exception : rte的时候直接throw exception / try catch

由于文法的复杂(还有空格的干扰处理),递归下降处理能应对尽可能多的WF输入,因此我选择了递归下降法。但太过自信于自己的递归下降,没有加入额外的保险,比如上述的第3和第5种方法,最终强测+自己再自测,还是发现了2个bug。

“80% 的软件缺陷常常生存在软件20%的空间里” -- 在自测和中测环节,我的bug在WF判断中频发:因递归下降造成的数组越界、解析提前结束、解析本应结束但继续读字符。后来的强测和自测,我确实也是在WF判断中翻车

bug分析

  • 强测中有一个测试点不通过

cos( cos(x**+7))**+7*(sin((cos((sin((cos(((x**+3)))**+6))))))

对于如(((sin(x))的WF输入,我的源程序无法判断缺失表达式因子右括号的情况,在parseExpfactor()的时候数组越界。

我的修改:加入try...catch结构捕捉StringIndexOutOfBoundsException

try{
	//mycode
} catch (StringIndexOutOfBoundsException e) {
            throw new MyException();
}
  • 在修bug的过程中,我还发现了一个强测也没有测出来的bug。

对于如(sin(x)))))这种WF的输入,我当成valid input。原因在于:我在ExpFactor 归约到 Term 归约到Poly时,解析Poly结束的标志有bug。举例来说,我解析到蓝色右括号时,就return poly,此时字符串解析结束,得到poly = (sin(x))

我的应对很简单,在MainClass中,在parsePoly()后,我对已解析的字符个数与原字符串的长度进行对比,如果长度不等则说明存在WF的情况。

Poly polynomial = Poly.parsePoly(testOrigin);//解析输入字符串
if (polynomial.getIndex() != testOrigin.length()) { //判断字符串解析是否提前结束
throw new MyException();
}

新bug

反思:

  • 没有额外地“冗余”地添加一些判断WF的方法。如果加了这两道判断WF的保险,能规避掉很多错误。

  • 不能轻易相信中测及自己的代码。但心理上,还是会在中测通过后懈怠。

4. 对以后作业的期盼

  • 提高阅读别人代码的能力,在架构上多向别人学习。
  • 测试能力有待提高。这一次作业只做到了“完成作业”,但测试,还没有做。
  • 心态稳定,不要太双极化了
  • 有不懂的及时问+沟通。
posted @ 2021-03-30 17:43  糯米鸡呀呀呀呀  阅读(51)  评论(0编辑  收藏  举报