oo第一单元总结

综述

  一个月前,从刚刚开始接触java起步,现在虽然已经完成了一个单元的作业,但还是没有完全脱离原来面向过程的编程思维,而且工程化思想也还是处在培养阶段。整个单元的作业,基本还是处在Cjava的阶段,基本没有应用设计模式,也没有完全树立按照面向对象的思想实现。某种意义上,还是在面向作业和测试编程。养成OO思想,工程化思想以及熟练应用设计模式的路还很长呢。

作业分析

第一次作业

  第一次作业相对较为简单,但由于刚刚接触java语言,所以并没有习惯java面向对象的设计方法,基本只是把类看成了容纳函数的容器进行处理。首先,通过main函数来进行输入输出。然后,用输入表达式生成Polynomial对象,在对象生成方法中,对表达式的格式进行了判断。之后,对表达式按‘+’号进行拆项,将每一项生成一个Item对象,在Polynomial中设计了一个Hashmap来存储项和指数,并在生成过程中合并同类项。最后调用求导方法,获得结果。

  总体来说,第一次作业的难点在于处理表达式格式,而优化的主要方向在于合并同类项。

 

第二次作业

  第二次作业,依旧还是延续了上次作业的策略,在对表达式格式进行判断后,按‘+’号拆项,只是修改了Item类,将它由 a * x ^ b 变成了 a * x ^ b * sin(x) ^ c * cos(x) ^ d 。虽然还是一个类似面向过程的逻辑,而且可拓展性比较差,但是较上次而言,遵循了一定的面向对象原则,比如求导后,不在原对象的基础上直接修改,而是返回一个新的表达式对象;将项的toString方法放在Item类中,而不是直接在Polynomial类中的toString方法中实现。该次作业虽没有提高拓展性方面,不过通过try-catch方法提高了鲁棒性,并降低了类之间的耦合性。

  该次作业的主要难度依旧在于处理表达式格式,优化的主要方向主要是合并同类项,尚未实现对三角函数的合并化简。

 

第三次作业

  第三次作业是在第二次作业的基础上增加了嵌套因子的定义,但难度大大上升。该次作业中,对项的求导沿用了第二次作业的Item类,增加了HandleExp类处理表达式,Polynomial则不再处理表达式格式的问题,而且其结构设计从简单HashMap改为了表达式树。该次作业的难点除了复杂的格式判断,还有可以嵌套的求导过程。所以,通过设计表达式树,来简化求导过程。但由于对设计模式尚未有深入的了解,构建表达式树的过程依旧是面向过程的构建方式,递归构建二叉树,对嵌套因子则只保留左支,相当与构建了一个栈。在拆项时,过去的直接按‘+’拆项方法也不能适用,而是选择首先对表达式的括号进行匹配,然后按括号外的第一个‘+’或‘*’的位置对左边和右边依次递归建树。

  该次作业的难点在与格式判断以及表达式树的构建。由于该次作业的代码逻辑较之以前有了较大的变动,所以完成处理表达式和表达式树的构建后没有再进一步的进行优化。对优化方向的一个想法是删去系数为0的项,然后通过贪心的方法去除多余的括号。

 

度量分析

 第一次作业

 

第二次作业

第三次作业

总结

  首先,可以发现每次作业中处理表达式的类复杂度都相对较高,这跟我判断格式时用了许多if-else 来针对性判别有关。第二次作业和第三次作业基本使用了一模一样的Item类,在Item生成方法中,由于需对  a * x ^ b * sin(x) ^ c * cos(x) ^ d 按‘*’拆项后再赋值,故而也用了许多if-else来判断,并用了两个循环来完成初始化,大大增加了复杂度。第三次作业中,复杂度除了之前提到的两部分,基本都集中在了find和toPoly两个方法上,这两个方法正是构建表达式树的方法,toPoly中用了大量的if-else语句来确定表达式树的各个节点的值,find中则维护了一个栈,先进行了括号的匹配。

  由于没有完全脱离过去的写代码模式,这三次作业中核心算法的复杂度都较高,以后可以通过套用一些设计模式,来将这几个方法进一步拆分,从而降低总体复杂度。以后的作业中,也要注意将算法拆分开来,避免先过去似的,一个方法写完。

Bug分析

   这三次作业中,第一次作业错误较多,共包含3个方面。第一,正则表达式应用不熟练,部分正则书写出错。第二,考虑拆项时,直接忽略了空串,导致对 x+ 这种错误直接被忽略。第三,在输出格式时,为了化简而省略了系数为0 的项,而在判断空串时,又只是考虑了Hashmap为空,而忽略Hashmap不为空,但合并后结果为0 的情况,从而对 x-x 输出了空串。

  第二次作业没有被测出bug,但在后来自己测试时,发现正则中又是少写了一项。第三次作业中,出现了一个设计中的bug,就是在求导时,只关注了sin和cos的嵌套因子的前导符号,而忽略了表达式因子前的符号。而在自己测试时,并没有构建完备的测试,而是主要去关心了嵌套因子的求导结果,导致出错。

互测分析

   第一次互测,就是非常机械地下载代码,逐个测试,效率极低。通过多次调试和阅读部分代码,找到了几个人在构建正则表达式中判断输入格式时出现的不完备性。

  第二次互测,参考着评论区大佬以及一些搜到的资料搭建了一个小的对拍器,不过没有使用自动化生成测试样例的方法,而是将自己构建的样例进行输入。之后,又阅读了几个人的代码,找到了其中两个人在判断格式时的不完备性。

  第三次互测,依旧是将自己构建的样例输入对拍器,然后对输出结果调用sympy进行化简再进行比较。这次,只用自己构建的样例便测到了3个bug。

模式分析

   这三次作业中,并没有套用什么设计模式,也没有用到接口和继承,只是简单地将任务拆分成了几个类,然后依次调用每个类的方法来完成任务。

  以第三次作业为例,将任务分配给了3个类,其中HandleExp负责处理字符串,并生成表达式树,表达式树的每个叶子节点都是项。在求导时,表达式树依次递归求导,到叶子节点时,就将求导过程交给Item类的求导。

 posted on 2019-03-27 16:04  Eric_Zhuo  阅读(236)  评论(0)    收藏  举报