本单元一共三次作业,逐次递进地实现了对一个较复杂的表达式的解析和求导。
一、程序结构
1.第一次作业
1.1 UML
第一次作业较简单,只需要对带系数的幂函数项的加和进行解析求导。我这里使用了三个类,其中Term是Poly的内置类。
Term类通过系数和指数储存带系数的幂函数信息,提供了求导、比较(compareTo,方便化简)和格式化输出方法;然后Poly类通过Term类储存多项式信息,提供了求导(diff)、添加元素(add)和格式化输出(toString)方法。
1.2 代码复杂度分析
方法复杂度
方法规模
类规模
2.第二次作业
2.1 UML
第二次作业增加了三角函数,而且项之间的组合形式也增加了,可以以乘积项的形式出现。我使用了五个类和一个接口。
Term接口规定表达式中一个基本的项单元,实现加、乘、获取更改系数、创建新实例和求导功能,此时包含三角函数和幂函数,即Power类和Tri类。
Part类储存表达式中的乘积项,提供逐项加入的实例化方法,以及求导和格式化输出功能。
Poly类储存表达式,表示Part项的加和,同样提供逐个加入的实例化方法和求导、格式化输出功能。
对于输入字符串的处理,是在main中初步处理,变成一个个乘积项的形式,然后对于一个个乘积项,下放到Poly,再由Poly下放到Part中处理。
2.2 代码复杂度
方法复杂度
方法规模
类规模
3.第三次作业
3.1 UML
第三次作业让项的形式变的更加复杂了,可以有复合函数的形式。
思路是仍然采用之前的程序结构,通过在Term中增加表达式这一属性,实现对表达式的递归解析和求导,未完成。
二、Bug分析
第一次作业主类中的表达式捕获少捕获了一个空格,导致符号出现问题。
第二次作业由于未提供clone方法,导致同一个乘积项中的三角函数在求导并化简时对于数据是共享的,从而求导结果出现错误。
反思:第一次作业把读入,表达式解析,输出整个都放到了主类中,导致代码逻辑不清晰,容易出现细节性的问题;第二次作业没有认清深拷贝和浅拷贝的区别。
三、互测数据分析
第一次作业的情况其实并不多,可以通过提供所有的特殊、边界情况进行黑盒测试。
第二、三次作业的情况就比较多了,都涉及到了较为复杂的化简,在提供一般的数据和较为特殊的数据进行黑盒测试之后,可能在程序中还存在某些特殊的,因为化简等操作导致的bug,就需要阅读别人的代码,理解了逻辑之后再提供特殊的测试代码。
四、应用对象创建模式
本次作业的对象还是比较明晰的,每一种项对应着一个对象,每一种项的组合方式也可以对应一个对象。
第一次作业到第二次作业时,重构了代码,将内置类变成了一个单独的类,并提供了一个统一的接口对项进行管理,使代码的逻辑变清晰了,并且提高了类功能的内聚性。
五、心得体会
第一单元的作业暴露出了我的许多问题。
1.构造测试数据能力弱,没有尝试写过评测机,数据纯靠手敲或评测机
2.面向对象编程经验不足,很多明明可以单独列出来的功能总是杂糅在一起了
3.java基础理解不够,经常会出现关于深拷贝、浅拷贝这样的理解性的问题