首页 > 其他 > 详细

OO第一单元总结

时间:2021-03-28 21:49:14      阅读:28      评论:0      收藏:0      [点我收藏+]

目录

一、前言

二、基于度量的程序结构分析

三、个人程序出现的bug

四、互测策略

五、重构经历理总结

六、心得体会

一、前言

本单元作为OO作为面对对象思想的引入,目的在于初步利用面对对象设计实现多项式求导。由于第一周缺乏对于可扩展性的追求,引来了后期重构的巨大麻烦,以致于最后都没有完全实现递归下降分析处理。

二、基于度量的程序结构分析

1.第一次作业

  • 结构概览

技术分享图片

graph TD A[MainClass] A -->|生成| C[Polynomial] F[作业一类图]
  • 度量分析
代码行数 属性个数 方法个数
Polynomial 102.0 2.0 5.0
Mainclass 29.0 0.0 1.0
Total 131.0 2.0 6.0
Average 65.5 1.0 3.0
方法 代码行数 循环嵌套 条件嵌套 认知复杂 基本复杂 设计复杂 圈复杂
Polynomial.toTerm(BigInteger,BigInteger) 16.0 0.0 0.0 32.0 1.0 10.0 12.0
Polynomial.toString() 18.0 1.0 1.0 6.0 1.0 4.0 5.0
Polynomial.Polynomial(int) 4.0 0.0 0.0 0.0 1.0 1.0 1.0
Polynomial.parseStr(String) 39.0 1.0 2.0 72.0 1.0 23.0 23.0
Polynomial.isPos(String) 5.0 0.0 0.0 2.0 1.0 4.0 5.0
Polynomial.isNeg(String) 5.0 0.0 0.0 2.0 1.0 4.0 5.0
Polynomial.deriPoly() 11.0 1.0 1.0 3.0 1.0 3.0 3.0
Mainclass.main(String[]) 27.0 1.0 1.0 5.0 1.0 4.0 4.0
Total 125.0 122.0 8.0 53.0 58.0
Average 15.625 0.5 0.625 15.25 1.0 6.625 7.25
  • 分析

    由于输入比较简单,用正则分离各项后用HashMap存储系数和指数,以非常短的行数实现。没有着重考虑用面对对象和递归下降实现,将多项式分析、求导、输出耦合在一个方法中,可以说是面对该次作业的编程。这导致parseStr(分析、求导全部耦合)的复杂度和行数远超其他方法。现在来看可以说是百害无一利的设计……仅有的一些好处就是极简代码+第一次作业中性能、互测无懈可击。

  • 优化

    由于直接HashMap直接存储系数,故直接利用相同指数合并,基本达到了最大性能。

2.第二次作业

  • 结构概览

技术分享图片

graph TD A[MainClass] A -->|生成| B[AddExpression] B -->|生成| C[MultiplyTerm] B -->|实现| D(Differentiate) C -->|实现| D(Differentiate) B -->|生成| E[Factory] C -->|生成| E[Factory] E -->|生成| F[Cons] E -->|生成| G[TrigonSin] E -->|生成| H[TrigonCos] E -->|生成| I[Vari] F -->|继承| J[Factor] B -->|继承| J F -->|继承| J G -->|继承| J H -->|继承| J I -->|继承| J Z[作业二类图]
  • 度量分析
代码行数 属性个数 方法个数
AddExpression 106.0 2.0 0.0
Cons 13.0 0.0 0.0
Factor 96.0 4.0 12.0
Factory 15.0 0.0 1.0
MainClass 11.0 0.0 1.0
MultiplyTerm 62.0 2.0 2.0
TrigonCos 77.0 1.0 0.0
TrigonSin 76.0 0.0 0.0
Vari 76.0 0.0 0.0
Total 532.0 9.0 16.0
Average 59.111111111111114 1.0 1.7777777777777777
方法 代码行数 循环嵌套 条件嵌套 认知复杂 基本复杂 设计复杂 圈复杂
Vari.Vari(String) 3.0 0.0 0.0 0.0 1.0 1.0 1.0
Vari.toString() 36.0 0.0 0.0 2.0 1.0 1.0 8.0
Vari.todifferString() 35.0 0.0 0.0 2.0 1.0 1.0 8.0
TrigonSin.TrigonSin(String) 3.0 0.0 0.0 0.0 1.0 1.0 1.0
TrigonSin.toString() 36.0 0.0 0.0 2.0 1.0 1.0 8.0
TrigonSin.todifferString() 35.0 0.0 0.0 2.0 1.0 1.0 8.0
TrigonCos.TrigonCos(String) 3.0 0.0 0.0 0.0 1.0 1.0 1.0
TrigonCos.toString() 36.0 0.0 0.0 2.0 1.0 1.0 8.0
TrigonCos.todifferString() 35.0 0.0 0.0 2.0 1.0 1.0 8.0
MultiplyTerm.toString() 11.0 1.0 1.0 3.0 3.0 2.0 3.0
MultiplyTerm.todifferString() 24.0 2.0 1.0 12.0 4.0 6.0 7.0
MultiplyTerm.MultiplyTerm(String) 18.0 1.0 2.0 12.0 1.0 8.0 8.0
MultiplyTerm.differentiate() 5.0 1.0 0.0 1.0 1.0 2.0 2.0
MainClass.main(String[]) 9.0 0.0 0.0 0.0 1.0 1.0 1.0
Factory.getFactor(String) 13.0 0.0 1.0 5.0 5.0 4.0 5.0
Factor.todifferString() 3.0 0.0 0.0 0.0 1.0 1.0 1.0
Factor.setIndex(BigInteger) 3.0 0.0 0.0 0.0 1.0 1.0 1.0
Factor.setDerindex(BigInteger) 3.0 0.0 0.0 0.0 1.0 1.0 1.0
Factor.setDericoef(BigInteger) 3.0 0.0 0.0 0.0 1.0 1.0 1.0
Factor.setCoef(BigInteger) 3.0 0.0 0.0 0.0 1.0 1.0 1.0
Factor.optimizationIndex(BigInteger) 9.0 0.0 1.0 3.0 3.0 2.0 3.0
Factor.optimizationCoef(BigInteger) 11.0 0.0 1.0 4.0 4.0 3.0 4.0
Factor.hashCode() 4.0 0.0 0.0 0.0 1.0 1.0 1.0
Factor.getIndex() 3.0 0.0 0.0 0.0 1.0 1.0 1.0
Factor.getDerindex() 3.0 0.0 0.0 0.0 1.0 1.0 1.0
Factor.getDericoef() 3.0 0.0 0.0 0.0 1.0 1.0 1.0
Factor.getCoef() 3.0 0.0 0.0 0.0 1.0 1.0 1.0
Factor.Factor(String) 16.0 0.0 2.0 9.0 1.0 4.0 5.0
Factor.equals(Object) 14.0 0.0 1.0 4.0 3.0 5.0 7.0
Factor.differentiate() 9.0 0.0 1.0 2.0 1.0 2.0 2.0
Cons.toString() 3.0 0.0 0.0 0.0 1.0 1.0 1.0
Cons.todifferString() 3.0 0.0 0.0 0.0 1.0 1.0 1.0
Cons.Cons(String) 5.0 0.0 0.0 0.0 1.0 1.0 1.0
AddExpression.toString() 14.0 1.0 1.0 4.0 1.0 3.0 3.0
AddExpression.todifferString() 14.0 1.0 1.0 4.0 1.0 3.0 3.0
AddExpression.hashCode() 4.0 0.0 0.0 0.0 1.0 1.0 1.0
AddExpression.equals(Object) 14.0 0.0 1.0 4.0 4.0 2.0 5.0
AddExpression.differentiate() 8.0 1.0 0.0 1.0 1.0 2.0 2.0
AddExpression.AddExpression(String) 48.0 1.0 3.0 32.0 5.0 18.0 20.0
Total 505.0 112.0 62.0 90.0 145.0
Average 12.948717948717949 0.23076923076923078 0.4358974358974359 2.871794871794872 1.5897435897435896 2.3076923076923075 3.717948717948718
  • 分析

    针对第二次作业的括号嵌套问题,作业一中的正则方法已经行不通了,只能重构。嵌套的分析使用了栈,并且嵌套调用表达式类和项类(因子可以是表达式,因子可以生成表达式对象)。使用工厂模式创建各种因子,编写toDiffString输出求导后表达式。代码量增长了4倍,其中因子类中创建了大量的set-get方法,复杂度集中在分析表达式输入AddExpression和求导输出toDiffString上。分离了求导、输出降低耦合度,这是第二次作业的优点。缺点是这种嵌套调用的方法使得求导比较复杂,这也是复杂度集中在求导输出上的原因。

  • 优化

    只做了系数为0、-1、1,指数为0、1特殊情况的输出处理。

3.第三次作业

技术分享图片

graph TD A[MainClass] A -->|生成| B[AddExpression] B -->|生成| C[MultiplyTerm] B -->|实现| D(Differentiate) C -->|实现| D(Differentiate) B -->|生成| E[Factory] C -->|生成| E[Factory] E -->|生成| F[Cons] E -->|生成| G[TrigonSin] E -->|生成| H[TrigonCos] E -->|生成| I[Vari] F -->|继承| J[Factor] B -->|继承| J F -->|继承| J G -->|继承| J H -->|继承| J I -->|继承| J A -->|生成| K[CheckFormat] Z[作业二类图]
  • 度量分析
代码行数 属性个数 方法个数
AddExpression 104.0 2.0 0.0
CheckFormat 137.0 1.0 3.0
Cons 13.0 0.0 0.0
Factor 119.0 5.0 12.0
Factory 15.0 0.0 1.0
MainClass 37.0 0.0 1.0
MultiplyTerm 77.0 3.0 2.0
TrigonCos 110.0 2.0 1.0
TrigonSin 111.0 2.0 1.0
Vari 76.0 0.0 0.0
Total 799.0 15.0 21.0
Average 79.9 1.5 2.1
方法 代码行数 循环嵌套 条件嵌套 认知复杂 基本复杂 设计复杂 圈复杂
AddExpression.AddExpression(String) 46.0 2.0 3.0 36.0 7.0 14.0 17.0
AddExpression.differentiate() 8.0 1.0 0.0 1.0 1.0 2.0 2.0
AddExpression.equals(Object) 14.0 0.0 1.0 4.0 4.0 2.0 5.0
AddExpression.hashCode() 4.0 0.0 0.0 0.0 1.0 1.0 1.0
AddExpression.todifferString() 14.0 1.0 1.0 4.0 1.0 3.0 3.0
AddExpression.toString() 14.0 1.0 1.0 4.0 1.0 3.0 3.0
CheckFormat.checkFormat(String) 48.0 3.0 3.0 48.0 8.0 18.0 18.0
CheckFormat.checkFormatOpt(String) 26.0 2.0 5.0 46.0 9.0 14.0 16.0
CheckFormat.checkOpt2(String) 60.0 2.0 3.0 78.0 14.0 31.0 34.0
Cons.Cons(String) 5.0 0.0 0.0 0.0 1.0 1.0 1.0
Cons.todifferString() 3.0 0.0 0.0 0.0 1.0 1.0 1.0
Cons.toString() 3.0 0.0 0.0 0.0 1.0 1.0 1.0
Factor.differentiate() 16.0 0.0 1.0 4.0 1.0 4.0 4.0
Factor.equals(Object) 15.0 0.0 1.0 4.0 3.0 6.0 8.0
Factor.Factor(String) 30.0 1.0 4.0 27.0 6.0 14.0 14.0
Factor.getCoef() 3.0 0.0 0.0 0.0 1.0 1.0 1.0
Factor.getDericoef() 3.0 0.0 0.0 0.0 1.0 1.0 1.0
Factor.getDerindex() 3.0 0.0 0.0 0.0 1.0 1.0 1.0
Factor.getIndex() 3.0 0.0 0.0 0.0 1.0 1.0 1.0
Factor.hashCode() 4.0 0.0 0.0 0.0 1.0 1.0 1.0
Factor.optimizationCoef(BigInteger) 11.0 0.0 1.0 4.0 4.0 3.0 4.0
Factor.optimizationIndex(BigInteger) 9.0 0.0 1.0 3.0 3.0 2.0 3.0
Factor.setCoef(BigInteger) 3.0 0.0 0.0 0.0 1.0 1.0 1.0
Factor.setDericoef(BigInteger) 3.0 0.0 0.0 0.0 1.0 1.0 1.0
Factor.setDerindex(BigInteger) 3.0 0.0 0.0 0.0 1.0 1.0 1.0
Factor.setIndex(BigInteger) 3.0 0.0 0.0 0.0 1.0 1.0 1.0
Factor.todifferString() 3.0 0.0 0.0 0.0 1.0 1.0 1.0
Factory.getFactor(String) 13.0 0.0 1.0 5.0 5.0 4.0 5.0
MainClass.main(String[]) 35.0 1.0 5.0 28.0 1.0 12.0 12.0
MultiplyTerm.differentiate() 5.0 1.0 0.0 1.0 1.0 2.0 2.0
MultiplyTerm.MultiplyTerm(String) 36.0 1.0 2.0 18.0 3.0 10.0 12.0
MultiplyTerm.todifferString() 19.0 2.0 1.0 10.0 1.0 6.0 8.0
MultiplyTerm.toString() 12.0 1.0 1.0 3.0 3.0 2.0 3.0
TrigonCos.getFactor() 3.0 0.0 0.0 0.0 1.0 1.0 1.0
TrigonCos.todifferString() 39.0 0.0 0.0 2.0 1.0 1.0 8.0
TrigonCos.toString() 37.0 0.0 0.0 2.0 1.0 1.0 8.0
TrigonCos.TrigonCos(String) 27.0 1.0 1.0 11.0 3.0 9.0 13.0
TrigonSin.getFactor() 3.0 0.0 0.0 0.0 1.0 1.0 1.0
TrigonSin.todifferString() 40.0 0.0 0.0 2.0 1.0 1.0 8.0
TrigonSin.toString() 37.0 0.0 0.0 2.0 1.0 1.0 8.0
TrigonSin.TrigonSin(String) 27.0 1.0 1.0 11.0 3.0 9.0 13.0
Vari.todifferString() 35.0 0.0 0.0 2.0 1.0 1.0 8.0
Vari.toString() 36.0 0.0 0.0 2.0 1.0 1.0 8.0
Vari.Vari(String) 3.0 0.0 0.0 0.0 1.0 1.0 1.0
Total 764.0 362.0 105.0 193.0 264.0
Average 17.363636363636363 0.4772727272727273 0.8409090909090909 8.227272727272727 2.3863636363636362 4.386363636363637 6.0
  • 分析

    由于作业二未实现完备的递归下降分析,导致作业三检查WF必须新增一个CheckFormat类重新对输入进行检查,纯if-else结构使得类中方法条件嵌套、复杂度喜提所有方法第一。所幸嵌套结构依然可以实现复合求导,对三角函数因子类嵌套生成表达式因子。最后果然因为WF而非正确性错了两个强测点。这再次证明了在作业一时就注重可扩展性是多么重要。

三、个人程序出现的bug

  1. 第一次作业
    • toString判断空串用了==而没用equals()
  2. 第二次作业
    • 无bug
  3. 第三次作业
    • 没有判断幂的幂(连续**
    • 对于空串+括号(())判断循环写错(重新开始时计数器是否需要增加)

总结:最后一次明显是因为没有在分析多项式自动排除WF,用if-else特判会出现很多考虑不出来的情况。

四、互测策略

  1. 第一次作业
    • 根据形式化表达,利用函数递归构造多项式数据,可以设置深度和随机数范围来设置嵌套数和生成因子的几率。只写了生成器没写自动测评机。
  2. 第二次作业
    • 写评测机。输入主类名字,自动寻找文件夹中主类,分别编译所有.java向主类输入in.txt数据。获得数据再和标准答案(sympy.diff())对比(simplify())。根据题目特别加大了嵌套深度,确实提高了hack出bug的几率。
  3. 第三次作业
    • 研究了一下打包JAR但是发现无法输入遂放弃,沿用第二次作业评测机。

五、重构经历总结

大规模重构是在第二次作业时,类图在上面已经放出就不再复制过来了。第一周过于粗暴地面对作业编程显然第二周将不可避免地推翻重构。针对面对对象的工厂模式、编写toDiffString()求导和输出分离解耦均是在第二周实现的。然而第三周依然经历了15h的痛苦编写检查WF类,归根到底是第二周的设计模式还不够彻底地递归下降。应该一个字符一个字符地生成检查而不是直接判断整个因子、项,传一个子串处理。后者再在检查WF时没法很好处理单个字符间的问题。

六、心得体会

本单元在第一周的偷懒使得后面付出了成倍的代价,在下一单元应该提前设计好整个单元的程序结构,避免后面迭代带来的种种麻烦。同时希望之后在此基础上能多考虑一些性能的提升,因为后面的重构使得没多少时间去提升性能。

OO第一单元总结

原文:https://www.cnblogs.com/NatsusakiYomi/p/14589404.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!