前言
第一单元的作业主题是多项式求导,从第一次最简单的幂函数求导,到第二次幂函数和三角函数的求导,再到最后一次幂函数加三角函数的嵌套式求导,不论是分析难度还是代码量都是不断递增的。而最后一次的作业,也因为我的不重视导致自己连中测都没有通过,虽然最后又通过了一周的时间补写了第三次作业并通过了强测,但整体的代码结构依然比较糟糕,还有许多值得改进的地方。
第一次作业分析
1.度量分析
程序类图
程序复杂度
可以看到第一次作业我是一main到底的,是完完全全的面向过程程序设计。整个程序只有一个main类实现了添加元素和输出结果的方法,整体的复杂度是很高的,各个方法之间的耦合度也很高。其中最复杂的addmap方法,我是通过自己的逻辑判断,设计了6层if语句的嵌套来实现对于input字符串的解析,所以才会有这么高的复杂度。这样的实现方法不仅仅增大了代码量,而且也加大了编程难度,导致我在完成第一次作业时就感到了吃力。并且因为复杂的逻辑判断导致我的两个方法都是超过了60行的规定行数,所以最后我的代码风格得分只有60分,这对这次作业最后的成绩相比有很大的影响。
2.程序bug
第一次的测试我通过了所有的强测样例,但是在互测阶段被人找到了两个非同质bug。第一个是我在输出求导结果为0的项时并没有添加+,这导致类似于x**1+0*x这样的表达式我会输出10这样的结果。第二个bug是在整体求导结果为0时,我没有输出,造成这个的原因是最后在输出hashmap中保存的求导结果时,我会将指数为0的项忽略不输出,所以在类似于x-x这样的样例中我会没有输出。
3.发现别人bug所用的策略
第一次的互测我下载了别人的代码并且花费了许多时间认真的阅读了其中的3份代码,但是并没有发现其中的BUG。最后为了节约时间手动构造了比较复杂的样例但是并没有成功hack到别人,导致了我第一次互测挂零。但是在互测阶段通过阅读别人的代码我也学习到了许多很好的面向对象式的设计方法,这对我第一次代码的重构还有第二次代码的顺利书写打下了基础。
第二次作业
1.度量分析
程序类图
程序复杂度
第二次作业的架构与第一次相比有了很大的变化,因为在第二次作业中加入三角函数,还有对于程序鲁棒性的测试——WF的判断。所以在这次作业中我一共实现了4个类,分别是Poly类,Term类,Func抽象类,还有PowFunc类(Func的子类),并划分了三个层次Poly->Term->Func。其中Poly类用于对整个表达式的WF判断以及化简表达式并且有一个
在每一个类中都实现了求导方法和输出结果的方法(但三个类中这两个方法没有统一命名,这一点很不好),在每个层次的求导过程中回调用下一个层次的求导方法,最后的求导结果用输出结果的方法传到上一层。
关于化简。这次的化简可以说是强行化简,我只实现了过滤掉多余的1*并且为了实现这个优化导致了许多bug的产生,然后在互测过程中被hack。
这次的作业中最复杂的方法是Term类的输出方法,这也是意料之中的,因为把三角函数归到幂函数中增加输出复杂度,再加上本来函数连乘的求导结果输出本就很复杂,导致到最后output的复杂度暴增。
总的来说这次作业我认为完成的还是不错的,已经初步有了面向对象设计的味道。不过还是有很多可以改进的地方,比如代码的耦合度还可以解的更低,各个层次的分工也可以更细致。
2.程序bug
第二次的测试我通过了所有的强测样例,但是由于强行优化在互测阶段被人找到了两个理论上的非同质bug,不过我还是通过5行以内的改动修复了这两个bug。第一个bug和第一次作业一摸一样(又中枪了。。。),第二个bug是我把输出存在一个字符串中,在输出是将零指数的项判断为无输出,但是在优化输出的过程中有对于输出字符串的访问,这导致了字符串的访问越界异常。
3.发现别人bug所用的策略
第二次的互测我通过同学的自动评测机(菜鸡还没学会怎么搭)跑别人的代码发现了别人的代码中+-号的bug。
第三次作业
1.度量分析
程序类图
程序复杂度
第三次的作业由于我的不重视在星期六早上才开始完成这次作业,导致未能在截至时间之前通过中测。不过在之后的时间,我还是按照自己的思路完成了这次作业并通过了强测。这次作业的难度明显增加了,首先是对于WF的判断,由于嵌套的存在不再能够通过像第二次作业的大正则完成,必须对于每一个层次进行正则判断。然后便是对表达式的处理和求导,由于有嵌套的存在这两个都需要涉及到递归调用,其实解决了其中一个另外一个也就自然解决了。当初就是在递归的问题上没有思考清楚导致无从下手,最后未能通过中测。这次还是像第二次那样采用了三个层次的架构,每个类内部用的是Arraylist容器,每个类都有parse,derivative,tostring方法分别完成字符串解析,求导,和输出的工作。对于嵌套的处理是在求导的过程中执行的,如果有嵌套就根据其是普通因子还是表达式因子创建一个新的实例并调用对应类的方法判断是否合法,然后对其进行解析,和求导。这样的设计思路和第二次很像,需要重构的地方很少,但是缺点特别明显。首先就是对于化简几乎无能为力,而且输出的表达式十分臃肿,几乎是放弃了性能分。
2.程序bug
3.发现别人bug所用的策略
很不幸未能参加这次互测。
心得体会
1.寒假的pre训练为我们的面向对象编程能力打下了一定基础,让我们了解了正则表达式的使用,继承与多态的使用。这对于第一个单元的作业完成都有莫大的帮助。
2.讨论区是思路不清晰时的好棒手,在我对作业没有很好的思路的时候我会浏览讨论区中的内容,里面很多值得学习的东西——设计思路,方法,各种技巧等。
3.经过这个单元的训练,我不敢说对于面向对象设计有了熟练的掌握,可能入门都算不上(因为最后一次的作业都未能完成,完成了也写的那么臃肿),但是还是体会到面向对象的一些思想,学习了接口,继承,工厂这些在面向对象设计是至关重要的方法。
虽然学期才刚开始我就已经感觉到了亚历山大,但是还是不妨碍我认为OO这门课是一门好课,特别是课程流程的设计让我感受到了老师和助教们的用心良苦。最后感谢助教老师们为课程改革付出的努力。