程序及bug分析:
第一次作业
设计思想:第一次作业要求的功能较为简单,所以我只设计了三个类,一个主类用来放置main函数,同时简单处理输入,一个表达式类实现求导的主要功能,包括有将表达式的每一项存储,简单排序使得最终结果以正项为第一项,合并同类项,求导,最后输出。最后一个类为幂函数类,拥有系数和指数两个属性,只有构造方法、get方法和set方法。
UML类图
程序复杂度
设计反思:显然,这一次的作业对于高内聚、低耦合要求的实现是很令人不满意的。
由于第一次作业要实现的功能较为简单,再加上当时我没有建立起面向对象的思想,导致仅仅面向过程实现了这次的功能,这为之后的扩展带来了极大的麻烦。
bug分析
这次作业因为其功能较为简单的原因,在强测和互测都没有出现bug,最大的问题就是不具有可扩展性。
第二次作业
设计思想:第二次作业加入了三角函数求导,我依旧分了三个类来完成,处理的最小单位是形如a*x**b*sin(x)**c*cos(x)**d的形式。主类使用大正则的方法,对输入的表达式进行格式正误判断。poly类依旧实现添加最小单位项、合并、求导、化简、排序、输出。最后一个类为最小单位项类,四个属性分别对应abcd。只有构造方法、get方法和set方法。
UML类图
程序复杂度
设计反思:尽管自己因为上次可扩展性不强而重构了第二次作业,但是我还是没有吸取上次的教训,没有按照面向对象的思想来完成这一次的作业,使得这次的复杂度甚至高于上一次。
bug分析:这次作业在强测和互测中均被发现了bug,经过我的修复,一共是两个问题,一是对空白字符的处理出现了问题,我因为偷懒,把空格和tab直接全部写为了\s,这样使得一些不合法的字符被忽略了。另一个问题是输出简化时,在处理系数为±1时没有考虑清楚,错误的省去了不该省去的字符。
总而言之,第二次作业完成的让我不太满意,出现了很多的纰漏,并且不具有可扩展性,导致了时间和分数上的损失。
第二次作业
设计思想:这次的作业难度明显高于之前,加入了嵌套的求导,因此我之前使用的大正则直接匹配全串的方式在这次无法使用,并且也不能将每个项写成统一的格式,因此我不得不全部重构之前的代码。
最终采用的方法依旧分了阶段处理。
整体结构上,构建了表达式类,项类。采用工厂模式构建因子类,因子类是一个抽象类,只提供了抽象求导方法,共有常数因子、幂函数因子、sin函数因子、cos函数因子、表达式因子五类继承自这个类,并重写了求导方法和tostring方法。
输入部分,采用递归的方式,将每个表达式拆成若干的项,每个项拆成若干的因子,在处理因子区分不同类型,如果是表达式因子就再进入一次递归。在拆分的同时进行格式正误的判断,如果正确就存入arraylist中。
求导部分,遍历主表达式的全部项,对于每个项调用其所有的因子的求导方法即可。
输出部分,遍历求导结果表达式的全部项,对于每个项调用其所有因子的tostring方法,并在表达式的tostring和项的tostring中提供了简单的化简处理。
UML类图
程序复杂度
设计反思:吸取了前两次的教训,这次的作业在动手之前进行了很长时间的思考,最终选择了一个较为合理的方法,第三次作业的复杂度明显小于前两次,但是也出现了主类复杂度较高的问题,主要原因是把对于输入处理的方法全部放在了其中,如果将有关方法放入到一个专门的处理输入的类当中效果会更好,更符合高内聚、低耦合的要求。
本次作业对于化简的处理十分小心,尽量不要为了化简的20分而失去正确性的80分,因此对于合并项或三角函数化简并没有做处理,如果要做处理的话,可以考虑建立一个新的类,包含全部的化简处理方法,在求导结果产生后进行调用。
bug分析:这次作业在强测中没有被发现bug,而在互测中出现了一个问题。经过排查发现,依旧是化简是出现了过度省略的问题,当因子为0时,没有了输出,导致了输出出现了格式错误。
发现别人bug的策略:
我测试别人程序的方法主要分三类。
一是覆盖性测试,通过构建尽可能包含全部合法要求的表达式,对于程序的基本功能进行测试,比如如果要测试对于空白字符的测试,那就构建一个包含全部合法因子的表达式,在全部可以插入空白字符的地方插入两种空白字符。
二是极限测试,通过构建符合条件的尽可能极限的表达式,比如让指数最大,或者是在第三次作业中嵌套尽可能多的括号。
三是针对代码本身测试,这种方法需要仔细阅读对方的代码,检查其逻辑中是否有疏忽的地方,针对性的提出问题,这种方法效率比较低,但是可以通过阅读别人的代码来锻炼自己阅能力,丰富自己的编程思想,优化自己的代码结构。
应用对象创建模式来重构:
在第三次作业中,吸取了前两次的教训,我采用了简单工厂模式来构建这次的代码,通过构建factor抽象类,生成不同的所需子类,这种方法最大的好处就是可扩展,便于添加新的因子。
心得体会:
三次作业难度不断增加,我在不断构建代码的过程中,通过上网查找资料,与同学交流,学到了许多关于java的特性以及构建代码的方法。早就听闻OO是一门硬核的课程,经过三周的学习我确实感受到了压力,但是也是感觉很有收获的。深刻的意识到了,在完成之后的作业时,要先进行足够的思考再动手,并且要给自己的代码留下足够的扩展性,不要再出现这次一新增要求就需要重构的现象了。
同时自己也需要学习自动评测机的实现,这可以大大节省我在对自己代码测试花费的时间,在互测中也更容易发现别人的问题。