OO第一单元总结
第一单元很艰难地度过了。经历了一次彻底的重构。
第一次作业
做完三次作业返回来看第一次作业感觉很简单。只涉及简单的幂函数,求导方法也很简单。
根据作业要求我只设计了三个类:Main,Expression, Term,形式上大多还是仿照第一次上机实验课的代码来完成的。Expression用来分解各项的系数和指数,Term用来处理每一项的输出方法,并实现略微的简化。
我的第一次作业在架构上基本完全仿照第一次上机实验,可拓展性极差,注定在下次作业要重构。
下面是各类的度量。
Main:
Expression:
Expression下的各个方法耦合度较高,你中有我我中有你,思维较为混乱,复杂度也普遍很高。
Term:
Term下toString方法的重写中,对于各种可以化简的情况进行了if分支处理,导致复杂度很高。
每个类之间分工还算明确,但是类之内的方法写的比较混乱(但是均没有超过六十行的),最后也没有进行进一步的化简。
第二次作业
第二次作业表达式因子的加入,让我基本全盘重构,只保留了去空格的部分。
第一次作业我采用利用项与项之间的加号来进行分割,因子与因子之间的乘号进行分割处理,在第二次作业就很难行得通。根据作业指导书的提示,我在重构后设计出九个类,一个接口。九个类分别是Main,Expression,WhichType,Constant,Cos,Sine,Power,MulKnot,Plus.接口为Derivable。特别指出的是乘法和加法节点。这是打造出表达式树的关键点。二者其实就是求导法则的类,在其中实现他们的求导方法和输出。其余的如Constant之类的顾名思义的项就是为各种因子做出一种类,在类里实现求导和输出方法。
以下为这次作业的类图
这一次改进第一次作业在Expression中才修整加减号的问题,在Main类中和去空格同级处理多个加减号的问题。
Expression下关于分析系数的值有一些冗余,四个方法的代码重合度较高,有很大的改进空间。
对于每一种因子均设立一种类实现derivable的求导方法,从而利用出多态的特性。在每一种类中也给出各自的toString方法,用于输出。
这次在进行大的分类后,我认为每个类之间的耦合性已经较小,也为第三次作业打造出了较好的架构。
Main:
Expression:
在打造最终的表达式树的方法里用了多次for,if的语句,复杂度很高。
WhichType:
判断因子种类用了多个if,复杂度较高,且这种判断并没能在Expression里使用这个工具类时减少if的使用,现在想来是失败的。
Constant:
Power:
Sine:
Cos:
MulKnot:
在toString中对于一些可以化简输出的特殊情况进行了判断,利用了一些if语句,导致复杂度较高。
Plus:
这次作业用在架构上的时间非常长,完成的也非常仓促,第一次做完的时候并没有化简和认真debug,导致强测分数感人。
第三次作业
第三次作业相较于第二次作业,增加了格式判断。这个是重点内容,至于sin的嵌套,思想和第二次作业非常一致,因此这一点基本毫无难点。对于格式判断,由于我之前沿用的分割、预处理法无法实现这一功能,因此专门增加一个判断格式的类JudgeFormat来实现这个功能,并且使用的是递归下降分析法。下面是类图。
Expression中略微改变了求系数的方法,减少了数量,合并了比较相似的方法。此外,对sin和cos类增加了一个属性,就是sin、cos后跟的因子。但是大体的方法基本不变。
Main:
JudgeFormat:
较多的if、 while的使用,使得复杂度较高。
Expression:
跟第二次作业相比,打造节点的方法的复杂度已经减少了很多,但是还是偏高。
Sine:
可以看到增加内容对复杂度基本无影响。
Cos:
其他的类没有变化,在此就不再列出。
Bug分析
第二次作业强测出现较大问题,bug出现在分割判断少了一种情况以及结果长度过长。互测也因为这两个问题被反反复复hack多次。分割判断上,出现bug与修复后的差异只有一个字符,就是正则表达式的差异,因此代码行和圈复杂度都不变。在修复代码长度过长的问题上,代码行和圈复杂度都有显著提升,这是因为在化简时对一些特殊系数进行了if判断,导致复杂度上升。
第三次作业强测在格式判断上出现问题。该问题的根源是对可能出现的情况考虑不周到,指数超过50时用long也不一定装得下。针对此bug,我只是修改了数据类型,因此代码行和圈复杂度也没有大的差异。
对于别人的代码,我只是用一些自己看到的或者想到的可能的边缘情况进行了大概的测试,没有结合被测程序的代码设计结构来设计测试用例。
重构经历总结
第二次作业相对于第一次作业完全重构。
第一次作业没有认真的思考可拓展性,只是投机取巧地套用了第一次上机的代码结构。对于常数、幂函数等因子并没有分类意识,也导致后面无法沿用这种结构。
第二次作业在重构后类数多了非常多。表达式因子的出现使得我必须构建表达式树,因此对于各种因子以及求导规则都要进行类的建立。重构后的结构是比较好的,也便于后期第三次作业的拓展。
心得体会
-
pre对第一单元的作业很有帮助,但是我寒假贪玩,没有珍惜这个学习机会,除了可惜无能为力。
-
学习继承、多态的知识是我所感觉到的层次化设计所需的比较重要的知识。
-