OO第一单元作业总结

 前言

  本学期第一次接触面向对象的思想和编程。在第一单元的作业中,专注于求导,并试着用面向对象的方法来解决求导问题。

  三次求导作业,第一次作业重点是多项式求导,死二次作业在多项式求导的基础上增加了三角函数求导,第三次作业增加了括号嵌套的层层求导。不同于以往的编程训练,面向对象的开发每次的作业更注重结构设计,以便往后的迭代开发,为自己减少推倒重构的风险,减少开发难度。

 

一 基于度量来分析自己的程序结构和缺陷

第一次作业分析

  第一次作业主要有三个类组成,分别为Main,Derivative,Item类,UML结构图如下所示:

 

  Main类主要用来键盘输入和屏幕输出操作,并调用Derivative类进行输入处理,Item用于处理Derivative传入的多项式的各项底数和指数。

  在Derivative类中,难点在于表达式的分割,再次,我采用正则式来进行表达式分割。但是我用正则式的缺点在于产生了一个正则打天下的naive想法,结果就是很容易在处理较长的表达式时候极易爆栈,而且考虑情况也不很完全,一些边边角角的WRONG FORMAT!情况就无法很好地处理。在互测中也因此比较惨淡。

  互测中,阅读其他同学的代码,分开匹配表达式是很好的一种办法,我所在房屋里我认为比较好的一些匹配做法是:1.尽可能让每一个项都标准化,即将‘++’‘--’‘+-’‘-+’全部换为单运算符,标准化的表达式简化正则式的匹配、、书写;2.匹配错误情况,匹配到了除了合法字符以外的字符就返回错误;判断正确就把合法的空格,水平制表符统统吃掉(replaceall),这样就可以带着简短的表达式进入下一阶段的判断。

  下面是对方法复杂度的分析,第一次作业的实现功能较为简单,复杂度爆红即复杂度高的方法略少;

 

Methodev(G)iv(G)v(G)
Derivative.dealMyItem()1.04.04.0
Derivative.Derivative(String)1.07.07.0
Derivative.getMyItem()1.03.03.0
Derivative.getSize()1.01.01.0
Derivative.optimizeMyItem()5.05.05.0
Derivative.optimizeOutput(String)1.014.0`14.0
Derivative.print()1.07.07.0
Derivative.setMyItem(String)1.02.02.0
Item.compressItem()1.014.014.0
Item.getFactor()1.01.01.0
Item.getFactor_d()1.01.01.0
Item.getIndex()1.01.01.0
Item.getIndex_d()1.01.01.0
Item.getItem()1.01.01.0
Item.mergeMyItem(Item)1.01.01.0
Item.setFactor()1.03.03.0
Item.setFactor_d()1.01.01.0
Item.setIndex()1.02.03.0
Item.setIndex_d()1.01.01.0
Item.setItem(String)1.01.01.0
Main.main(String[])1.01.01.0
Total25.072.073.0
Average1.19047619047619053.42857142857142843.4761904761904763

第二次作业分析

  第二次作业收到之后,发现增加了三角函数求导和三角函数幂函数形式的求导,当时就估计很有可能在第三次作业中增加括号嵌套的求导,这就会使得正则式匹配不再好使,因此毅然决定推倒重写,在第二次作业中不再使用正则式进行匹配;先上UML结构图:

 

  可以发现本次作业结构十分复杂,当时咨询了一位软院大佬以后,按照他的建议,严格按照参考书,将匹配分为因子(Factor)项(Item)表达式(Expression)三级数据结构,最底层的因子又下辖幂函数,三角函数,常数的匹配方法,(据该大佬说我们的作业有点淡淡的编译原理文法分析的气息),在此不再赘述。对应三级数据结构的就是对应三级数据结构的三级分析方法类,首先将几个三级分析类都要使用的方法扔进最顶层的分析方法类,三级分析类就直接继承到了该顶层类,这也是我第一次在作业中应用继承的方法。其余如IO部分等和第一次作业保持一致。

  这一次作业给我的指导和启发就在于让我学到了这种数据结构类+分析方法类结合的编程方法,对于表达式的判断也就不再需要在最顶层判断,而是分散到各级的类当中处理,符合情况就返回匹配到的项,因子,否则就Null,这就使得表达式的匹配和分割可以比较愉快的进行下去。这样编程的整体构造方法就比第一次作业更加软工了一些。

  这一次作业几乎是完全推倒重来,因此bug众多也是难以避免的,指导书中对于表达式的表述对于第一项可以带一个正负号,包括第一因子为常数且值为1则可以省略该常数因子或表示为证号开头的形式,这些特殊情况我的处理做的不太好,问题集中在ExpressionAnalyser即表达式分析类中,特判第一项和正常匹配后续项数的方式导致行数和bug众多,在互测中也因为这个类的书写问题被打爆,值得庆幸的就是问题都是出在该类方法,就尝试修复该类,结果修复环节一改就超60行,只能在bug修复中将首项和后续项判断方法合并进行,终于一次性扫光了所有的互测中的bug。

  第二次作业的三级结构,就像摊大饼,很多方法就摊开了,因此复杂度尚可,当然,以后的书写中将会考虑使用Pakage将各级进行包装,否则目录中的众多类方法还真是令人吃不消。下面是方法复杂度的分析

 

Methodev(G)iv(G)v(G)
SinXAnalyser.analyse(String,int)5.08.09.0
SinX.toString()2.01.02.0
SinX.sinxD(SinX)3.03.03.0
SinX.SinX(BigInteger)1.01.01.0
SinX.SinX()1.01.01.0
SinX.getIndex()1.01.01.0
SinX.combine(SinX)1.01.01.0
PowerFunctionAnalyser.analyse(String,int)4.04.04.0
PowerFunction.toString()2.01.02.0
PowerFunction.PowerFunction(BigInteger)1.01.01.0
PowerFunction.powerD(PowerFunction)2.02.02.0
PowerFunction.combine(PowerFunction)1.01.01.0
Main.main(String[])1.04.04.0
ItemAnalyser.analyse(String,int)4.04.04.0
Item.toString()1.02.03.0
Item.numOfItem()1.01.01.0
Item.mult(Factor)10.010.010.0
Item.getFactor(int)1.01.01.0
IntegerAnalyser.analyse(String,int)4.04.014.0
FactorAnalyser.analyse(String,int)9.09.09.0
ExpressionAnalyser.analyse(String,int)9.06.012.0
Expression.printD()1.04.04.0
Expression.print()1.02.02.0
Expression.derivation()4.09.010.0
Expression.better()5.06.06.0
Expression.add(Item)1.01.01.0
CosXAnalyser.analyse(String,int)5.08.09.0
CosX.toString()2.01.02.0
CosX.cosxD(CosX)3.03.03.0
CosX.CosX(BigInteger)1.01.01.0
CosX.CosX()1.01.01.0
CosX.combine(CosX)1.01.01.0
ConstFactor.toString()1.01.01.0
ConstFactor.ConstFactor(BigInteger)1.01.01.0
ConstFactor.combine(ConstFactor)1.01.01.0
Analyser.skipSpace(String,int)1.02.03.0
Analyser.setIndex(int)1.01.01.0
Analyser.nextChar(String,int)1.02.02.0
Analyser.getIndex()1.01.01.0
Total96.0112.0136.0
Average2.46153846153846172.8717948717948723.4871794871794872

 

第三次作业分析

  第三次作业果然上了表达式的嵌套,有了第二次作业打下的结构基础和匹配基础储备,这就稍微容易,线上UML结构图:

 

  本次作业有了嵌套,嵌套主要是三角函数类型的嵌套,和幂函数底数的嵌套,因此同样采用三级结构的同时,因此在处理中专门针对这两个特点,遇到三角函数前括号,前括号就切割字符串,采用递归但不回溯的办法继续匹配括号内的内容。本次作业的处理思想和实现最后看起来也没那么难以进行,但是在实际作业中仍然花了很多时间不断尝试,以至于几乎是压周二晚的线提交作业,很大程度可能是我一直以来对于递归的不熟悉和畏惧,C语言时如此,汇编语言时也如此,这次大量的调试中,看着递归层层运行和不断debug对于递归的处理也是熟悉了很多。

  本次作业的缺陷是对于整个表达式的匹配识别中开了一些天窗,即使用if特判一些情况,并没有很好地将所有情况的判断分散到三级架构中进行,这在一二次作业中不涉及递归运行还良好,在本次作业中这些通过if特判开天窗判断的办法就带来了一些bug,这就使得我带着一些已知的bug进入了强测中。

  以下是方法复杂度分析:

Methodev(G)iv(G)v(G)
VarFactor.VarFactor(Base,BigInteger)1.01.01.0
VarFactor.VarFactor(Base)1.01.01.0
VarFactor.print()1.04.04.0
VarFactor.isIndexZero()1.01.01.0
VarFactor.derivation()1.01.01.0
SinXAnalyser.analyse(String,int)5.05.06.0
SinX.SinX(Expression)1.01.01.0
SinX.print()1.01.01.0
SinX.derivation()1.01.01.0
Main.main(String[])1.06.06.0
ItemAnalyser.analyse(String,int)5.05.010.0
Item.print()1.05.05.0
Item.mult(Factor)1.04.04.0
Item.mult(BigInteger)1.01.01.0
Item.isConst()1.01.01.0
Item.derivation()2.04.05.0
IntegerAnalyser.analyse(String,int)4.04.014.0
FactorAnalyser.analyse(String,int)7.08.08.0
Factor.print()1.01.01.0
Factor.derivation()1.01.01.0
ExpressionAnalyser.analyse(String,int)8.08.015.0
Expression.print()1.04.04.0
Expression.isConst()2.02.02.0
Expression.derivation()1.02.02.0
Expression.add(Item)1.01.01.0
Expression.add(Expression)1.01.01.0
CosXAnalyser.analyse(String,int)5.05.06.0
CosX.print()1.01.01.0
CosX.derivation()1.01.01.0
CosX.CosX(Expression)1.01.01.0
ConstFactor.print()1.01.01.0
ConstFactor.getVal()1.01.01.0
ConstFactor.ConstFactor(BigInteger)1.01.01.0
BaseAnalyser.analyse(String,int)10.010.010.0
Base.print()1.01.01.0
Base.derivation()1.01.01.0
Analyser.skipSpace(String,int)1.02.03.0
Analyser.skipExp(String,int)2.03.07.0
Analyser.setIndex(int)1.01.01.0
Analyser.nextChar(String,int)1.02.02.0
Analyser.getIndex()1.01.01.0
Total81.0106.0136.0
Average1.9756097560975612.58536585365853673.317073170731707

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

  下面附上基于CK标准度量分析程序结构:

  第一次作业

  第二次作业

  第三次作业

  

 

转载于:https://www.cnblogs.com/LtxBlogOfOo/p/10611177.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值