OO第一单元总结
单元任务与总体思路
第一次作业:表达式建模
架构的设计思路
-
我在做这个单元的第一次作业的时候,参考了本届OO实验给出的exercise和实验代码,摒弃了大正则的解析方式,而是选择了递归下降的方法来解析表达式,将表达式建模为多项式Poly、项Term和因子Factor的组合。递归下降的方法通过抽象层次的调用,将每一层代码分隔开,为代码的书写和理解带来了便利。
-
参考pre2-4建立同类型对象的方法,我采用了工厂模式来建立不同的因子Factor。同时,我使用了抽象类Factor因子,而具体种类的因子都是抽象类Factor的子类(不过后来发现,我使用抽象类更多是为了方法的一致性,不如直接使用接口)。抽象类 + 工厂模式建立对象,两种方法结合,将读入并解析字符串递归的底层层次parseFactor()的这个阶段的过程变得更抽象更清晰。
-
在Poly、Term和Factor等不同层级的类种,我都写了统一的化简方法deleteBracket()来进行去括号。顶层的poly调用该方法,就可以递归到底层因子的同名方法,以实现整个表达式的去括号。
-
计算方法:①Class Term里面写了两个Term相乘的方法 ②Class ExpFactor(表达式因子)的deleteBracket()展开方法中,在①的基础上,进行了a**b(a带括号的展开) ③Class Poly(多项式)中的相乘方法依然以①为基础
-
关于符号处理:我将符号都当作 +1 或者 -1的常数因子,放入每个Term对象的因子列表中,有些繁琐但是确保了这种读入方法的可扩展性。
感想与反思
因为老师和助教都一直在强调架构的重要性,我在第一次作业之前也是犹犹豫豫不敢下手。后来参考了许多他人的优秀架构,最后在做第一次作业的时候就使用了一个比较好的架构,整个单元的书写基本没有进行大的重构。
因为太懒,一直没有进行简单的合并优化,最后尽管代码没什么问题也还是进了B房,强测分也就是贴着80,会觉得有点可惜。
代码分析
测试
第一次作业我强测和互测都没有出bug,并成功hack了一次别的同学(指数带前导零的问题)。
第二次作业:增量开发
架构的设计思路
-
增加了三类因子:Sum,Defined(自定义函数因子)和Trig,依旧是继承于抽象类因子Factor并且使用工厂模式构造。
-
新建立了一个类SelfFunc来存储自定义函数的定义,并将存储多个自定义函数的容器作为参数传递,加入到了表达式的解析化简过程中。
-
对于两类函数,我在读取并建立该因子时,就进行了替换(虽然不是简单粗暴的字符串替换),将其转化为表达式因子来处理。
感想与反思
这次作业就是没有使用正确的方法。Constructor方法内内置了函数的调用,甚至还是用替换的方法做成的,可想而知有多容易出错。
代码分析
测试
第二次作业我强测有4个点没过,总结下来是两个问题 :
-
①函数调用替换时没有加括号,而我在建立因子时认为表达式因子是必须带一层括号的,所以也就没有转换成表达式因子(这就是不好的暴力替换方法带来的问题,本质是没有把函数调用当作表达式建模来处理)
-
②sum(i,s,e,t),getIndex最终读取位置忘记了加上最后一个后括号的1,本质是正则表达式基础不牢,使用String自带的一些基础方法,情况又没有考虑得很周全。
互测没有出bug,并成功hack了4次别的同学(①三角函数Trig带指数的问题没有考虑周全②三角函数内部因子带前置符号的问题③指数带正负号和前导零的问题)。
第三次作业:单层变多层
架构的设计思路
-
对于括号嵌套问题:第一次作业已有的架构完全可以实现
-
针对Sum和Defined函数多层调用的问题,我写了一个接口Func和类Re,目的是为了进行函数体的替换。
感想与反思
虽然本次作业依然使用了很粗糙的替换方法,但是还是解决了第三次作业的需求(还是为强测带来了隐患)。
同时,新的接口和类的抽象,使得第二次到第三次作业的改动非常的少。
函数嵌套,使得我第二次作业中解析函数调用分割得到实参的方法出现了一些问题,String.split()方法虽然简洁但是并不如正则表达式不容易出错。
第三次作业的bug仔细想想其实和第二次作业的bug具有同质性,只可惜我当时只解决了当前的bug却没有深入地去想有没有可能出现同质化的bug。
代码分析
测试
第三次作业我强测有1个点没过,总结下来是一个问题 :
-
当求和上限小于下限时,直接生成了常数因子而忘记了将sum(i,s,e,t)整个式子读完(其实是,读入整个式子那一段的代码被放到了else块里面)
-
出bug的主要原因依旧是
互测被hack了7次,总结下来是犯了两个低级错误
-
①sum(i,s,e,t),t中含有形如 [i**带符号整数]的结构,替换i时带来的错误
-
修改方式:替换时,用 “(常数)” 的整体替换i
-
-
②sum(i,s,e,t) s,e上下限之前采用了int来存,造成了溢出错误
整体测试思路:回归测试+覆盖性测试
回归测试:
将自己在公测阶段遇到的会出问题的数据保留起来,分析出问题的原因,再根据这个原因编造测试数据
覆盖性测试:
仔细阅读指导书,针对指导书的每一个要求和数据限制来编造测试数据
缺点:
耗时耗力,说是覆盖性测试但是测试的覆盖性由于本人水平的限制所以并不太高
希望下一个单元能更多的尝试自动化测试的方法,对讨论区大佬给出的测试方法,要有拿来主义的精神
单元总结、反思与展望
-
完成本单元作业的过程就是体会了面向对象程序设计思想的过程。
-
本次作业的建模结构,与pre2的例子非常相似,我从中体会到了抽象层次化编程的优势所在。
-
架构方面,因为我从第一次作业开始,就采用了很不错的顶层架构,所以后来两次作业完成得相当轻松;与之相反的是,底层采用了不好的方法,与之相关的bug数量就会急剧增加,由此我体会到了代码设计的重要性。
-
优化方面,在大家都对优化卷生卷死的时候,我却懒于做一些最基础的优化哈哈,导致性能分有点惨不忍睹。
-
-
展望
-
希望下一个单元的学习中,我能更多地和老师、助教、同学们沟通,不要再一个人死磕不重要的点,那样会事半功倍。
-
本次作业中,我照猫画虎使用了工厂模式,为设计带来了便利,希望下个单元我能更多的了解和使用设计模式
-
下一单元会在性能和正确性之间重新分配比重。
-
下一单元会更注重讨论区的内容,多多进课下测试
-