OO第一单元总结

第一次作业
由于第一次的作业较为简单,我仅设置了两个类,即主函数类和用于存储表达式的atom类,在atom类中,我分别记录了幂函数的指数和系数。在本次作业中,我才用了arraylist的容器用于存储每个单项式,利用arraylist的遍历来进行化简。
(1)基于度量来分析自己的程序结构

正如前文所述的,我只采取了两个类,且大多数方法均在MainClass中实现。
OO第一单元总结_第1张图片
这是两个类的UML图。结构较为简单。
OO第一单元总结_第2张图片

(2)分析程序中的bug
在第一次作业中,我没有在强测和互测被查出bug,但由于在首项为负数时可能会没有将其放到后面导致性能分不是满分。

(3)分析自己发现别人程序bug所采用的策略
在第一次作业中,由于还没有搭建自己的自动化评测脚本,因此在这一次作业中我主要是采用了手动构造一些测试用例来寻找别人的bug。

第二次作业
在第二次作业中,由于出现了sin(x)和cos(x),为了方便化简,我设置了三层的存储形式,最上的一层为Hashmap,每一个节点的key是该项sin(x)和cos(x)系数和,value是一个ExpressionList对象。第二层ExpressionList对象中有一个Arraylist,Arraylist的value是每个单项式SingleExpression对象。第三层SingleExpression对象中分别有存储系数、幂指数、两种三角函数的指数。
(1)基于度量来分析自己的程序结构
OO第一单元总结_第3张图片

可以看到第二次作业中,我依旧没有使用继承和接口,其主要原因一是我对其的继承和接口的用法还不够熟悉,其次是这一次的作业的结构与第一次作业有许多相似之处,为了简便,因此没有使用新的结构。
OO第一单元总结_第4张图片
OO第一单元总结_第5张图片
这次作业的主要问题是我没有复写tostring()函数,导致在输出的阶段,需要同时判断的条件很多,代码复杂度较高。因此在输出的过程中,我在强侧和互测中都被发现了bug。

(2)分析自己程序中的bug
这次作业中我的程序一共有三个bug,第一个bug是关于指数大于10000时产生WF的问题,由于我未仔细阅读指导书导致我理解错了题目的原意,错将x9999*x9999这样的表达式误认为了WF。第二个bug是有关于输出的。有前文所述,我的printExpression函数和printSin、printCos函数的代码复杂度过高,导致我分别少判断了一种不用添加‘*’的条件,致使在样例输出中遇到了格式错误。第三个bug是有关迭代器的使用。在合并同类项的过程中,我原本的设计是当最外层的Hashmap中的ExpressionList中的ArrayList为空时则删除Hashmap的这个节点,但由于在迭代器中其的节点已经存入了iterator集合中,导致在删除过后使用next()时可能会出现越界的情况。由于这个bug隐藏较深,未在强侧中被发现,但一位互测同学的代码恰好覆盖了这个bug。这也使我在第三次的作业中没有使用迭代器。
(3)分析自己发现别人程序bug所采用的策略
这一周我依旧采用了和第一周相同的寻找bug策略,但由于这次可能造成的bug原因更多,我只测试了一些自己认为可能的bug,而没有测试全部bug,使我这周仅发现了3个同质性bug。

第三次作业
这次作业我出现了严重的事故。在强测中被找到了6个bug,在互测中被hack到了27个bug,我至今还没有找出全部的bug。仔细看来,这是由于多方面的原因造成的。我将在之后的分析bug中进行详细的介绍。在本次作业中,我摒弃了第二次作业的ExpressionList结构,按照多项式,单项式,因子三个层次来进行存储。由于产生了嵌套,我采用了特殊字符@和#来先替换,在之后进行求导时再进行展开。
(1)基于度量来分析自己的程序结构
OO第一单元总结_第6张图片

抽象类Factor有两个子类,即sin类和exp类,sin类是存储所有三角函数因子的类,而exp类是用于存储所有多项式因子的类。至于常数项和幂函数,我延续了之前的存储结构,仍将其放在单项式term类中存储。Pre类的操作是将读入的字符串先进行一些预处理,将三角函数嵌套和多项式因子用特殊字符代替,方便后续的切割单项式。
OO第一单元总结_第7张图片
OO第一单元总结_第8张图片
相比于第二周的作业,我第三周的作业的代码量反而增加的不多,这是由于我改变了原来的存储结构和输出方式。相比于原来存储指数的方式,由于考虑到嵌套不方便输出,我直接用字符串来存储相应的单项式和因子,在输出时,只用改写tostring函数来将其输出即可。因此可以看到,本次作业耦合度较高的地方为求导,并将求导结果变成合法字符串的过程。
(2)分析自己程序中的bug
在bug分析之前,我先反思了一下我的程序中整体架构设计的不合理之处。首先,我没有延续前两次存储系数的方式,而是直接存储字符串,看似是减少了许多的代码量,但这对之后我的化简工作挖下了一个大坑。这导致了我无法通过一遍输出一边分析来化简输出,只能通过完全输出字符串以后的静态分析来去除+0,1,多余的括号,这会带来两个问题,根本无法合并同类项以及会有想不到的情况导致bug,后面有关输出的bug就跟此有关。其次就是我由于采用了替换因子的手段来进行输入的处理,这会带来两个问题,一是这一块的代码很复杂,其次是为了获取外层括号需要嵌套,时间复杂度较高,且无法进行输入前的预处理。在研讨课中,一位同学提出了基于有限状态机的读取外层括号的方法,我认为更加可取。
这次程序中我的bug主要分为两类,一类是和输出相关的bug,一类是和运算相关的bug。由于bug我还没有全部修复,因此我仅在这里提及bug产生的原因。与输出相关的bug主要是在删除
1,+0时误将不该删除的部分如**1删除,导致格式错误。还有就是括号添加的不合理。这是整体架构不合理所造成的,由于我在输出内层字符串时,往往无法知晓外层的信息,因此不得不加上括号来避免格式错误,这会导致多层不必要的括号的嵌套以及我在某种特定情况下漏加括号的bug。
与运算相关的bug主要是正负号的计算问题,由于这样的bug出现了不止一次,且基本均为手误输错的问题,在这里就不再展开赘述。
发生了这么多的bug的原因首先要归因于我自己debug的不足。在本周作业中,我借用评论区的模板搭建了自己的测试机,但由于某些Linux操作上的失误,导致脚本会一直输出ac的结果,使我忽视了bug的存在。其次就是由于弱侧对于负数的测试不多,导致我的bug恰好没有反映出来,这也就让我更加放松了警惕。
(3)分析自己发现别人程序bug所采用的策略
正因为这次我的程序出现了严重的事故,导致我强测错误点过多分入了C房,加之自己的测试机的使用,这次我利用测试机找到了大量的bug。bug的类型也有很多。
(4)应用对象创建模式进行重构
纵观三次实验,我的MainClass越来越短,将工作更多的交给底层的class来实现,但不可否认的是我的面向对象思想还有很大的提升空间,在三次实验中,我只有在第三次使用了抽象类的继承,没有使用接口,也没有使用工厂模式,这些都是我需要在之后的作业中需要完善的。
(5)对比和心得体会
对比各位大佬的代码,我深知自己的不足,我也不想在这里对自己的代码妄下什么评论了,至于心得和体会,前面提到了很多,但我通过这三周的作业深深的体会到了将工作拖到ddl之前是多么的不可取。当每周四下午才刚开始写本周代码的我看着评论区的大佬提出的各种优化方案之时,我却发现自己甚至连基础的结果都没输出。每周六下午才写完代码也导致了我没有太多的调试时间,造成了太多的bug。

你可能感兴趣的:(OO第一单元总结)