HW1
UML类图
架构分析
本次作业架构首先是预处理,将所有的’\t‘和‘ ’删除,并将变量因子和表达式因子前的正负号处理掉,具体是替换为+1或-1乘以该因子。同时,处理掉在一起的运算符,方便进行运算。
建立了运算相关的类,乘法进行表达式因子的拆分和变量因子的指数相加,加法和减法只是进行字符串的拼接。
建立了处理输入的类,利用递归下降的方法,将预处理完成后的字符串进行拆分和运算,具有很多高复杂度的类,分支高达30,这是因为要将输入分割,因此要将很多分支来进行不同的分割,因为并没有对表达式项的存储,因此是在递归中计算,复杂度较高。
建立了化简的类,在运算结束后进行化简,会将x0变成1,x1变成x,并进行同次数项的合并,最后,判断第一项的情况,如果是有-,就寻找后面的每一项,直到找到一个正项,并进行交换,来进行长度的缩短。
建立了匹配和分割的类,负责按一定规律将字符串分割开。
架构的优点是可拓展性强,但是因为平均圈复杂度较高,程序不易读且修复较难。
架构设计体验
第一次作业写起来很匆忙,误解了要面向的对象,使得架构设计体验很糟糕。
对于除法的可扩展性比较高,能够在不动原有架构的基础上增加除法。
bug分析
因为在运算结束后才进行化简,大大增加了程序的耗时,使得强测TLE问题的出现,同时,预处理方法出现了无法处理连续的*-,使得运算的方法报错,导致了互测bug的出现。同时,减法的方法进行的拼接在开始时无法处理多项式之间的拼接,尤其是减数含有正负号时,导致了强测和互测bug的出现。
出现这样的问题是在于自己架构运行的缓慢,对方法抽象不完全,没有找到各种情况的共性,同时还有时间不足导致的没有对自己代码进行充分的测试。
在互测阶段寻找别人的bug,我的方法是首先测基本的方法,在用较复杂的表达式因子的相乘,构造一些极端数据来找寻bug。并没有结合被测者代码进行有针对性的测试,因为被测者代码太多,不熟悉的架构很难读完和读懂。
bug大多出现在圈复杂度高的方法;圈复杂度低的方法几乎没有bug,出现bug了也很容易解决。降低圈复杂度的方法我认为是将相关代码进行封装,进行代码功能的单一化处理。
HW2
UML类图
架构分析
第二次作业在第一次作业的基础上,新增了函数类,对原本的运算类进行了修改,对化简的方法进行了重构。
函数类负责储存函数和输出函数的替换结果。
预处理将exp变成了e。
运算类对于exp的计算出现了问题,因此进行了修改。
将上次的化简进行简化,并开始递归运用,每次碰到exp就将里面的内容进行化简,同时进行一个排序,在x相同,exp内容相同的情况下系数合并,因为将exp里的内容进行了排序,因此可以判断相同exp的不同格式,最后判断exp需不需要额外加括号,进行这样的递归化简来进行整体的化简优化。
架构设计体验
第二次作业的架构设计体验比第一次要好,任务很明确,增加函数,增加exp,但是因为未及时重构,导致方法圈复杂度较高,出现了很多bug,使得debug时间延长。
bug分析
bug的处理主要在于exp的计算之中,将exp,x和常数变成同一类在进行计算,同时,对于自定义函数的储存也需要注意,因为这部分的预处理与主要部分大大预处理位置不同,以及对于自定义函数的输出函数的正确性的判断也需要在意,我将x,y,z先换成了abc,在之后换回来,避免了不必要的替换。
对x的指数的储存用到的是int,导致了公测bug的出现。
大部分bug出现在了新增的方法中圈复杂度较高的乘法的地方,降低圈复杂度需要将乘法的功能分隔开,每一个方法执行一部分,即实现方法功能的单一性。
优化
处理了含exp的乘法的问题,在运算过程中删掉一部分0,对于乘方运算会先对内部进行运算。
HW3
UML类图
架构分析
增加了求导的类及其子类,并将其与运算的类进行连接。根据课上内容进行了多态的运用。
求导的类具有判断输入是什么类型并将其改变成该类型的方法和求导的方法,平均圈复杂度较整体圈复杂度有明显的改善。
bug分析
本次作业与上次作业的改变仅在求导的地方,因此bug也针对于这个地方,比如加减和乘法以及各种因子的求导结果的正确,同时进行一些处理,将其变成可以进入运算类的形式。
此次在公测并未出现bug,然而,TLE的问题虽然经过优化,但仍然存在。未出现bug的原因可能就是新增方法圈复杂度低,因此容易发现和解决。
在互测也没有找到bug,并没有结合代码来特定分析。采用了各种可能的情况,即常数,未知数,exp,存在乘法和加减法的导数,但是都没能找到bug。
优化
优化了乘方运算,对单独x进行从内而外的处理。
心得体会
在这三次作业中,我对于面向对象编程有了更多的理解,对于圈复杂度有了更多的了解,对单一功能原则有了更多的感悟。同时,我还对抽象有了更多的认识,对于debug有了更多的经验。我还认识到了读题的重要性,我在第一次互测才知道输入的要求。对于讨论区也要多多借鉴,而不是闭门造车。在对代码进行优化时要优先在意正确性,不因小失大。意识到正则表达式的局限性,要减少对正则表达式的依赖。通过第一周就开始的高强度的编程,我对于架构的重要性有了更多的认识,不好的架构在debug的时间可能比重写还要费时间。
未来方向
第一单元三次作业中最后一次相对来讲简单了太多,希望能够降低前两次的难度并将之分给第三次作业。性能分占比希望能低一点。