BUAA_OO_第一单元作业总结

BUAA_OO_第一单元作业总结

三次迭代式作业为一个单元的编程任务结束了,在此写下第一单元的学习心得。

一.基于度量分析代码结构

1.第一次作业

  • 第一次作业是对简单幂函数的求导,基本形式是a*x**b,也不需要判断输入数据的格式问题。因此,大致思路就是利用正则表达式取出每一个项(注意合并幂次相同的项),每一项求导相加即可。在化简部分,需要注意的是特殊的系数(比如:1,-1,0)和指数(比如0,1),化简内容少,难度不大。
  • UML类图:
    BUAA_OO_第一单元作业总结_第1张图片
  • 耦合度
    BUAA_OO_第一单元作业总结_第2张图片
  • 分析:这次作业我一共写了三个类,MainClass类负责读取字符串;Expression类就是需要实例化的表达式类,它负责分解读入的表达式,创建出Term类的一个实例化ArratList;Term类储存的是幂函数的系数和指数。由于Expression类执行了大部分工作,它的复杂度也比较高。

2.第二次作业

  • 第二次作业增加了简单三角函数(包括sin(x),cos(x)),并允许乘积形式的项,如a*x**b*sin(x)**c*cos(x)**d,并且需要判断输入的表达式是否合法。大致思路是,读取表达式后,先判断合法性,再提取每个项,然后求导相加。值得注意的是,这次三角函数的化简更加复杂,出于对正确性和性能分的权衡考虑,我只是把求导后的项合并同类项,没有在三角函数的深层次化简上下功夫。
  • UML类图
    BUAA_OO_第一单元作业总结_第3张图片
  • 耦合度
    BUAA_OO_第一单元作业总结_第4张图片
  • 分析:这次作业在上一次作业的基础上,增加了两个类:PowerFunction,TrigonometrFunction。这两个类分别存储了幂函数的系数和指数,三角函数的系数和指数。同时还有对应的函数求导法则。为了方便求导,我选择把a*sin(x)**b*cos(x)**c看成一个整体进行求导,再与a*x**b进行求导分配原则。由于多了函数的类别以及WF判断,Expression类的复杂度进一步增加;由于三角函数的求导规则,TrigonometrFunction的复杂度也比较高。

3.第三次作业

  • 第三次作业增加了复合原则,即a*sin(factor)**b,其中factor的定义更加复杂,可以多次嵌套。大致思路是,由于复合函数的复杂性,不能使用大正则表达式判断WF,因此受讨论区的启发,把括号()中的内容当成一个整体,递归判断括号内部的正确性。判断完正确性后,再拆分项和因子,进行递归求导。由于这次的化简规则更加复杂,我只考虑了系数(0,1,-1),和指数(1,0)的情况。化简带来的可能是性能分的大幅度提升,也可能是疏忽带来的bug。
  • UML类图
    BUAA_OO_第一单元作业总结_第5张图片
  • 耦合度
    BUAA_OO_第一单元作业总结_第6张图片
  • 分析:在第二次作业的基础上,把幂函数,三角函数分开处理,并且顺应复合函数的规则,三角函数的自变量增加了更复杂的递归定义。比如sin(sin(x**2)),首先实例化一个正弦函数S1,S1的自变量定义为sin(x**2),再将它实例化为S2,S2的自变量定义为x**2,最后实例化一个幂函数X1,X1的自变量定义为x,结束。这样做的结果就是,三种函数的求导方法互相调用,耦合度大大提升。但是,这样做并没有出现TLE情况。经过验证,在形如(((((((((((((((((((((((((((((x)))))))))))))))))))))))))))))这种深层递归的数据下,我的程序运行时长无需担心。

二.程序bug分析

  • 第一次作业发现的bug数较少,一般就是在化简时系数和指数的处理不当,输出形如-*x的结果。
  • 第二次作业,由于有了第一次的经验,而且第二次作业难度也不大,因此基本上没发现bug。
  • 第三次作业,bug数翻倍(也就是有4~5处比较考验数据随机性的bug)。首先,在判断表达式正确性上,我就因为sin( x)三角函数的内部空格没考虑引发了bug。然后,在拆分项和因子的时候,()括号处理不当导致bug。另外,在对性能进行优化的时候,类似(sin(x)+x)*(sin(x)+x)*(sin(x)+x)的数据让我输出了(sin(x)+x)**3这种错误格式。可以说,如果没有测评机的随机数据,我基本发现不了这些bug。

三.互测策略

  • 在第一次作业中,容易引发bug的数据不多,因此可以手动写好易错数据点。
  • 在后两次作业中,情况太复杂了,不上测评机的话得de到什么时候,这时就需要测评机来随机生成数据和评判。
  • 发现一个hack数据后,可以把数据抽丝剥茧,找到程序的核心错误。

四.基于对象来重构

  • 这次作业我没有使用到继承或者实现关系,也没有用到工厂类。主要是根据我的求导策略,需要的函数类别只有三类,没必要实行工厂化。如果之后再增加函数的类别,可以考虑用工厂化模式。

五.对比和心得体会

本次作业的设计中还存在一些问题:

  • 一些方法冗长
  • 没有用到抽象层次结构
  • 作业的迭代性还需要提升

通过这单元的学习,我认识到了代码可迭代性的重要性,测评策略在开发中的重要性,更好的理解了面向对象的意义。另外,讨论区的帖子也给了我很多的启发与提示,收获颇丰。

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