面向对象第一单元总结
面向对象第一单元总结
第一次写博客,不足之处请多多指正。
简介
第一单元作业为多项式的求导,其中第一次作业为简单多项式导函数的求解,第二次作业增加了简单正余弦函数的导函数的求解,第三次作业增加了正余弦函数及其嵌套组合函数的导函数求解。
第一次作业
程序结构
程序类图如下图所示
程序采用多项式-项-因子的层次结构,多项式使用Poly
类,项使用Term
类,此次作业中因子只有幂函数(常数可归为幂函数的特殊情况),故只设了一个PowFunc
类。
求导的方式为在多项式、项、因子中实现derivation
方法,主要思想为因子根据其求导法则进行求导得到新的因子,项对组成的各个因子进行求导并组成新的项,多项式对所组成的各个项进行求导得到新的多项式。
多项式、项、因子均重写了toString
方法转为字符串输出。
PolyParser
类的作用是对输入的字符串进行解析,由于此次作业没有错误格式处理,所以解析的方式为使用正则表达式进行匹配解析出项和因子。
度量分析
如下图所示
可以发现,Poly类和Term类的toString方法的耦合度和复杂度都较高,难以进行扩展。
优缺点分析
优点:采取此结构进行解析和求导的可扩展性较好,事实上三次作业我都采用了同一种结构,即多项式、项、因子的结构
缺点:难以进行某一些优化,如合并同类项时就要对项组成的因子进行比较,工作量较大
bug分析和hack策略
本次作业没有被检出bug,对于hack方面,我没有什么构造样例的心得,只使用了一个极大的幂函数指数样例hack了一个人,说明了BigInteger类使用的重要性。
第二次作业
程序结构
程序类图如下图所示
第二次作业在结构上稍作改进,由于增加了表达式因子,因此实现了Derivable
接口,将表达式,项,各类因子均视为可导对象。项可以视作由若干个可导对象的乘积组成,因此采用ArrayList保存组成项的各个因子,同时实现Mergeable
接口,实现了项内各因子的合并。(未实现表达式内各项的合并)
由于表达式因子的引入,在表达式的解析上进行了重构,采用递归下降分析法对字符串解析出项和各个因子
度量分析
如下图所示
这次作业在解析因子parseFactor
的方法和向项中增加因子方法addFactor
的复杂度较高,原因可能是解析因子时比较面向过程地使用了较多的if-else语句,增加因子方法中一并加入了合并因子的操作使得耦合度增加。在重构之后Poly类和Term类的toString
方法的复杂度有所降低。
优缺点分析
优点:此次作业实现了接口,使得程序的逻辑层次更加清晰
缺点:某些方法的复杂度仍比较高,程序的运行时间可能会过长
bug分析和hack策略
本次作业出现了一个意料之外的bug,是在处理的嵌套表达式嵌套的层数较多的时候,程序运行时间过长的bug,这个bug导致了强测丢了两个点,互测被hack1次,但是这个bug又是情理之中,因为我在没发现自身bug的时候用多层嵌套的表达式hack了同屋的3个人。对这个bug的具体修复策略目前在toString
方法中尽量使用中间变量保存中间结果,避免多次调用方法浪费时间,使用该策略让我的程序对于超时样例回到的合理的时间范围内。
第三次作业
程序类图
如下图所示
第三次作业得益于前两次作业的优良结构,在第二次作业下稍作改动便实现了新的要求,这也体现了面向对象思想的优越性。本次作业在SinFunc
类和CosFunc
类中加入factor
属性,并相应地修改求导方法,多项式和项层次不需进行变动,即可完成新的要求。
而本次作业新增了对异常输入的辨别,我的解决方法时,在解析多项式时当出现错误的匹配时便抛出异常,解析过程同样以递归下降法实现。
度量分析
如下图所示
由于增加了异常输入的分析,parseFactor
方法的复杂度变得更高,这是程序的一个大缺点。其余的与第二次作业差别不大。
优缺点分析
优点:程序的结构体现了面向对象的优越性,不需太大的改动便实现了迭代的过程。
缺点:仍有某些方法的复杂度过高。
bug分析
这次作业出现的bug为在解析表达式的过程中错误格式的误判,这是我测试过程的遗漏,同时也警醒我对自己的程序进行充分的测试。
心得体会
这三次作业由易到难的设计让我比较满意。在这三次作业中,我在第二次作业进行了一次小规模的重构,重构的过程还是相当痛苦的,但重构过后,类的功能相对变得明确,可扩展性大大增强,并且大幅度减少我在第三次作业中的工作量。可惜的是,我这三次作业都没有作太多的优化,有时候也比较懒,没有充分的测试和缺少对别人的hack。这是我所发现的自己的不足之处。希望之后三个单元有所进步。