OO第一单元总结
BUAA_BladeMonster_001
本学期笔者首次接触面向对象编程,深感其与面向过程编程的不同。这一点在第一单元的三次作业中也有所体现。
接下来笔者将从三次作业的整体思路、完成情况、bug分析、测试方法、对象创建和心得体会几个方面来阐述对面向对象第一单元内容的思考。
一、整体思路与完成情况
(一)第一次作业
此次作业是OO的第一次作业,内容是多项式的求导问题。虽然这门课叫面向对象,但是本质上还是用编程来解决问题,在笔者看来何种方法能有效的解决问题就是好方法,而不应该被局限于该是面向对象还是面向过程的选择之中。为了将来的可扩展性选择面向对象的方法固然很好,但是选择面向过程的方法直来直去追求更简洁的代码也无可厚非。
笔者在此次作业中选择的是偏向面向过程的方法,采取的解决方式是使用HashMap来存放数据,指数作为key值,系数作为value。这样做既方便处理也方便合并同类项进行化简。
本次作业未出现bug
UML图如下:
代码度量分析:
(二)第二次作业
这次作业增加了sin、cos函数和乘法求导法则,单纯的HashMap不足以应对这样的情况,于是笔者采用了创建对象 -> 求导 -> 创建对象 ->化简的方法。
本次作业中有两种因子:幂函数和三角函数,所以笔者创建了这两个类方便进行求导操作。但是在完成作业之后,因为只需要对对象进行求导操作,笔者感觉自己这仅有的部分面向对象思想似乎也不是很必要,整个过程可以更优雅得使用四元组来实现。
本次作业出现了一点bug,原因是对于指导书的形式化表述没有看明白,导致wrong format判断错误
UML图如下:
度量分析如下:
(三)第三次作业
这次的作业难度是有的,主要是因为增加了嵌套的求导法则,使得式子的求导方式变得极为多变。
在此次作业中笔者采用的方法是,先定义出式子的三种基本因子:常数、幂函数和三角函数,进行预处理之后建立表达式树,在这一步有两种可能的方法,第一种是采用栈来进行自底向上的构建,第二种方法是一种自顶向下的创建(实际上程序执行起来还是要从最后的叶节点开始建立)
具体方法是:找到该表达式中最后需要进行运算的运算符(同级运算符找第一个,有加号找加号,没加号找乘号,没乘号找嵌套)作为根节点,左右递归建树。需要注意的是在这一步一开始的时候需要去除左右两边多余的括号。这里值得一说的是,寻找运算符时我们可以使用一个数字来模拟栈,遇到左括号数字加一,遇到右括号数字减一,只有数字为零时才是表达式最外层的部分。
建立表达式树之后我们需要完成的是对于整个树的求导,在这里采取递归求导的方式即可,但应注意子树的求导之间不应相互影响。
下面说一下笔者对于这次作业化简的思路,笔者主要对幂函数和常数做出了化简,因为这一部分的优化效果是最明显的,相比较而言对于三角函数的化简更容易出现问题。而对于幂函数和常数的化简笔者的想法是将递归求导后的结果视为多层嵌套得到的结果,要对这种表达式进行化简,可以从表达式最内层开始化简然后向外逐层化简,化简外层表达式时应忽略括号中的内容。这样就保证了每一层表达式都得到了化简。经过上面的叙述,大家可以发现这可以是一个递归的过程,而我们的求导也是一个递归的过程,既然如此,我么可以将化简融入求导的过程中,将每一次加法法则和乘法法则求导后的表达式进行化简,这样我们就可以得到非常不错的化简效果(笔者化简的性能分接近满分)
本次作业出现了一点bug,原因是对于指导书的形式化表述没有看明白,导致wrong format判断错误
UML图如下:
度量分析如下:
二、bug分析
本单元出现的bug大都是wrong format有关的bug,主要是由于本人对与指导书的形式化表述认识不够明确(同时也对它深恶痛绝: D)
三、测试方法
在第一次作业的时候,笔者便使用java和python搭建了自用的评测机,大体思路为:生成评测数据,编译待测试代码,运行测试代码,检验输出。具体搭建方法在研讨课已经进行了分享,在之后的作业中,只需要更改生成测试数据的模块即可。
四、对象创建
本单元讲授了关于工厂模式的知识点,笔者在代码中也有所应用,基本上第二次和第三次作业的对象创建都用到了工厂模式。
五、心得体会
这是OO第一单元的博客,三次作业难度是递增的。笔者在思考题目做法和进行资料查阅时也耗费了不少的时间和经历,但总体而言投入和收获是成正比的。经历了三次作业的洗礼,笔者也对面向对象的编程思想初窥门径,但接下来的道路还任重道远,应当再接再厉。另外笔者也应当做出一定的反省,这三次作业每一次笔者都进行了重构,明显时没有考虑作业的可扩展性,敲代码的过程中随心所欲,这无疑是不利于代码的维护和迭代的,在接下来的作业中应当注意改善这一情况。另外,笔者在这一单元的很多错误都出在wrong format上,下一次应该予以更多的重视才行,不能再让千里之堤,溃于蚁穴。