OO__Unit1__多项式求导

OO__Unit1__多项式求导

前言

经过三周的痛苦挣扎,小菜鸡深深感受到了自己面向的这个“对象”所具有的威力。整体看来,第一、二次作业虽然还有不少bug,但是还是可以勉强胜任。第三次作业在代码量和设计难度上明显提升,由于我前两次作业的代码可扩展性不强,这三周可以说是一路重构、历经九九八十一难。虽然说万里长征才刚刚开始,但是在受折磨后终于完成项目带来的成就感也是很令人回味的。

1.程序结构分析

hw1

设计思路:

通过Expression类对表达式进行解析,对+-进行分析,切分出常数因子和幂函数因子。对于幂函数因子创建Powerfunc类,进行求导操作。讲求导后的结构以指数为key,系数为value存入Hashmap中,最后调用MainClass中的printString方法输出。

作业1类图

复杂度分析:

可见Expression类中正则表达式分析部分复杂度较高。MainClass的printString方法复杂度较高。

第一次作业复杂度分析

第一次作业类矩阵分析

hw2

设计思路:

表达式类创建MultiOperation类,MultiOperation类创建因子类TermTerm类创建工厂类Factory类,Factory类创建三角函数和幂函数类。三角函数和幂函数都继承自Function类。以因子类作为键值,以系数为value存入Hashmap。

第二次作业类图

复杂度分析:

还是在输出和正则解析部分飘红了

第二次作业分析

第二次作业类矩阵分析

hw3

设计思路:

InputHandler完成所有关于Wrong Format的判断,并将进行简单处理的表达式返回到MainClass。再进入Add类,进行加减法的分析。分出的项以String类型进行传递,进入Factory类,经过分析,创建其余类,从而实现递归。单独创建正则表达式分析类,从Regx进行读出所需的正则表达式。

复杂度分析:

可以看到我这次代码其实写的还是有很大优化空间的,因为InputHandler内部直接自己通过递归遍历了一遍字符串,所以这部分复杂度较高。同时几种函数操作方法相互调用,复杂度较高。

2.分析程序bug

说起bug这个令人心痛的事情,我很有话说,我深刻感受到自己是一个“吃一堑不长一智”的人。(愤怒.jpg)

作业一思路比较简单,在互测过程中我看到有很大一部分同学直接一个MainClass就解决了仅包含幂函数和常数函数多项式的求导问题。情况相对来讲也比较少,所以bug不多。

作业二和作业三我都错在了一个地方:除了常数因子,三角函数和幂函数因子前面不能加+-因此导致我面对类似9++-x这样的测试用例,并没有爆出Wrong Format!,反而快乐求导了。并且由于对层次解析不清,导致当出现x-+-9x时,我对数字前面三个+-符号解析也出现了问题。导致第二次作业强测爆炸。/(ㄒoㄒ)/~~

而且有的时候,有些人就是很令人敬佩,比如我....我弘扬了“在哪里跌倒,就在哪里爬起来再跌倒一次!”优良无脑小强作风,第三次作业再次强测爆炸。第三次作业出现了从未想过的“Your output has a wrong format“错误。原因是我只考虑了第二次作业引起的输入处理错误问题,但忽略了输出格式也要符合表达式要求。出现错误2*-sin(x)*-x类的因子带符号的错误。在改正时,基于我已有的设计,我要保证这些输出格式不对的幂函数或三角函数因子成为表达式因子,即在乘法模块输出的字符串两端带上括号。

自以为没有优化的我已经放弃太多,值得被温柔以待。直到我发现现实是骨干的,没有足够的测试用例、完备的思维、对细节的准确把握,最终只有悔恨的眼泪。/(ㄒoㄒ)/~~

与其说是自己马虎,我更应当反思的是自己对设计整体层次的理解。在整体架构的时候其实是忽略了很多细节的,这个是不可避免的(尤其是对我这号菜鸡来说)。所以全面的测试用例的构造至关重要!!!(因为计算机并不一定和你想的方式执行的是一样的...小黄鸭可能不大能救得了你)不过通过我的悲惨经历发现,我比较容易出错误的地方在于对输入输出的处理。同时也暴露出我对递归的掌握程度不足,不过经过这次训练,我至少不再感到畏惧。Just Do It!(ง •_•)ง

3.互测用例构造策略

在”狼人杀“游戏中,感觉我当”平民“比较多。在第一二次作业刀了一些bug,第三次作业由于前期花费时间精力太长,就没再疯狂构造。作为一个并不会自动化测试的小菜鸡,对我来讲想测出他人程序的bug,重点要测试全面。通过看同屋别的同学的hack成功用例,也是一个很好的学习机会。请相信,只有你想不到,真的各种bug都有可能会出现!

  • 边界测试:在与Wrong Format的边缘徘徊。在本单元作业中体现为指数的50限制+前导零、+-0*x*+0

  • 压力测试:试图用超级大数、深嵌套击垮他。如((((((((((((x))))))))))))

  • 穷举...╮(╯▽╰)╭:比如空格的位置、加减号、加减与乘法混合运算

  • 还有重要的一点就是!首先要为自己的程序构造足够的用例,不然....可能和我一样找不到别人的错,反而发现了自己的问题。/(ㄒoㄒ)/~

  • 根据二八定律,bug往往比较集中。今后可以先应用插件分析其他同学的整体架构模式,然后对依赖度高、复杂程度高的模块所实现的功能进行重点测试。

4.对象创建模式重构

1.本次完成的项目设计

本次我采用了简单工厂模式,设计了Factory类。由Factory创建加减模块(Add)、乘法模块(Multiply)、嵌套模块(Conpound)以及因子模块(CosfuncSinfuncXfuncConstant)。这样设计的好处是不同减少了因子模块间的直接调用,而是都经过Factory这个枢纽。但是也存在不足,简单工厂模式的可扩展性较差,如果新添函数类型或者函数操作,就要对Factory类进行修改。并且工厂类判断条件复杂,在我完成作业的过程中,测试出的bug主要集中在Factory类。

2.针对对象创建的改进思路

首先做一个工厂的抽象类。可以做一个表达式的工厂类,解析表达式,表达式工厂创建项工厂,项工厂调用因子工厂创建因子。这样可以降低原有中心Factory类的耦合度。通过工厂方法模式的创建,可以提高代码的可扩展性。

5.对比和心得体会

对比:

应用对象创建模式最大的优势在于可以提升代码的可扩展性。虽然我们的作业第一单元就此结束,但是在实际项目中,优化永无止境。如果加入反三角函数、对数函数等,就可以在第三次作业的基础上添加创建工厂和相关的函数类即可。而无须像我这三次作业走过来一路重构,其实是很低效的设计方案。

心得体会:

首先这三周下来,可以说面向对象对我来讲是一门比较有难度的课程。给我最大的印象是抓狂的挣扎抱着电脑入睡的夜晚完成一个作业的成就感

不过这种挣扎也是值得的,通过这三次作业,我学到了面向对象的思想,从面向过程的直线思维逐渐向功能封装转变。我还学会了对象创建模式中的工厂模式,是一种实现高内聚、低耦合的方法,从而提高代码的可重用程度。同时迭代过程中一定要注意题目要求,这次就吃了对题目理解一直延续了第一次作业的思维惯性,导致不小得到损失。

对于接下来的一周,我希望自己能够逐渐找到代码重写的方法,并且增强测试,锻炼自己的自我测试能力。

 

posted @ 2020-03-20 00:05  Windy·秋  阅读(173)  评论(0编辑  收藏  举报