无可奈何的毫无进步的重构之旅——BUAAOO第一单元作业总结
(一)程序结构分析
1.第一次作业
由于第一次上机实验与第一次作业相关性较高,本人第一次作业是由第一次上机代码迭代而来。
1.1代码规模度量
类 | 属性个数 | 方法个数 | 类总代码规模 |
---|---|---|---|
Term | 2 | 4 | 90 |
Expression | 1 | 4 | 86 |
Main | 0 | 1 | 19 |
1.2经典OO度量
只记录超标方法与类
method | CogC | ev(G) | iv(G) | v(G) |
---|---|---|---|---|
Term.toString() |
9 | 7 | 8 | 9 |
纵观第一次作业,爆红较少,总体的各项数值也没有过高,尽管是第一次写面向对象程序,但是由于要求简单,各模块耦合较为正常。
1.3类图
Expression
用一个容器来存储元素Term
,以便合并和计算,整体结构较为清晰
2.第二次作业
第二次作业加入了三角函数的求导与括号的嵌套,第一次作业的结构不再适用,于是采取了类似于表达式树的结构
2.1代码规模度量
类 | 属性个数 | 方法个数 | 总代码规模 |
---|---|---|---|
Expression |
2 | 13 | 127 |
XExpression |
0 | 3 | 24 |
CosExpression |
0 | 4 | 37 |
AddSubExpression |
3 | 5 | 89 |
NumExpression |
1 | 5 | 48 |
MultiExpression |
3 | 4 | 82 |
PowerExpression |
2 | 4 | 66 |
SinExpression |
0 | 4 | 37 |
PreTreatExpression |
1 | 2 | 44 |
MainClass |
0 | 4 | 39 |
2.2经典OO度量
只记录超标方法与类
在第二次作业中,由于加入了三角函数,对于数据的处理由第一次作业基于同类项构建,为了表达式树的结构,但是由于一开始没有较好的规划使的内容过于耦合,致使发现BUG后再修改过程中产生了更多的BUG。
2.3类图
由于第二次作业没有工厂方法,致使类与类之间关联较为紧密,而且这一特性延续到了第三次作业。
关于各类的功能,为抽象类Expression
通过一个静态方法来递归构建整体的表达式树,然后通过各个部分的多态来完成递归的求导。为了去除括号,采取了预处理的手段。将括号内内容先处理并存入静态容器内,然后将其内容替换,接着循环处理最高层,直至没有括号。当读到替换内容时,仅需要将静态容器的内容加入表达式树即可。
3.第三次作业
3.1代码规模度量
相较前两次作业,第三次作业单个类的代码更加均匀,对于不同功能的划分更加细致。也使第三次作业debug变得更加容易。
3.2经典OO度量
第三次作业有较多的方法有较高的圈复杂度,更容易产生BUG,而事实也确实如此,有不少因为考虑不周而带来的BUG,导致强测较低的分数和互测中被hack次数较多。
3.3类图
和第二次方法一样,由于没有工厂方法,第三次作业里在求导方法于简单化简方法中有很多相互调用构造方法的操作,致使彼此之间联系较为紧密。第三次作业与第二次作业思路相同,只是减少了附加属性,避免单个类承担过多功能,使表达式树内功能冲突。不过,有些抽象类内无属性,只有一个静态方法,如FunctionBase
、BasicFactorExpression
等可以用单独的类承载他们的功能,用接口来帮助实现区别子类功能。
(二)BUG分析
在第一次未发现BUG,在第二次作业中虽然过了中测,但是有非常多的BUG,最后采取了重构。而在第三次作业,主要产生了3个BUG,分别是:
-
在优化
0 - 表达式A
时直接将该表达式优化为表达式A
导致正负号错误 -
在处理指数时采用了
parseLong
的方法,但是没有catch
错误输入带来的异常,导致会产生异常中断 -
在处理表达式与项前的正负号时遇到正号选择了直接忽略,导致将项识别为因子,致使无法正确区别
Wrong Format
(三)分析自己与别人程序BUG
在本项目的三次作业里,本人一直没有找到合适的构造测试策略,这也导致了后两次需求稍微复杂后就很难发现自己的BUG,进而导致了强测和互测表现感人。关于本人BUG分析通常会通过拆解出错样例。
(四)心得体会&重构经历总结
三次作业下来,感觉自己的面向对象思想并没有什么提高。尽管后面两次本应是迭代的作业都采取了重构,但是并没能使自己的OO度量数据有什么改变。而且,在测试样例构造时感到无力。而构造测试样例是通过强测的先决条件,下一步需要增加自己构造数据的能力。