一、基于度量分析程序结构
第一次作业,简单多项式求导:
好吧,初来乍到的我相当于只写了一个Poly类,
于是...
构造函数Poly中,input字符串,output这个Poly对象每一项的系数、指数,存于HashMap中。
由于没有使用正则表达式进行匹配(不熟的原因,只用了分割和去除空白字符),
在构造函数中,为了得到每一项的系数、指数,分割多项式后,对每一项的字符串进行了遍历,
同时为了判断合法性,建立了5个标志位,导致了一堆的if-else if-else...
自己写的都头皮发麻,不过,还好写出来了
心力交瘁的我就顺理成章的没有想到正项提前的优化。
要说优点,就是充分的体现了理科生严谨的思维(毕竟是这么多的逻辑、分支)
缺点,同样的,就是繁琐,不好debug,可读性差......
第二次作业,加入sin、cos:
很自然的想到把每一项都统计成 a*x^b*sin(x)^c*cos(x)^d,就能得到任意项的求导公式;
同样的,把式子分成若干项之和,把项分成若干因子乘积,在Atom类里进行每种因子的正则匹配。
用上了正则和分层的思想,这一次作业,不算上优化的话,代码量比第一次都要少。
在输出时,函数PrintTerm由于要考虑指数为0、1等多种情况,我又搞了一些if-else,好像不太好,指标又红了...
在Atom构造函数里,我进行了正则的匹配,判断,捕获系数指数的操作,现在认识到这些不太应该写在构造函数中
优化就是考虑了一个肯定能在有限步完成的合并和一个肯定能减少一项的合并,这个优化肯定不会是最优的了
第三次作业,加入嵌套因子:
由于加入了嵌套因子,递归肯定成了首选;
还是一样分割的思路,只不过我就直接粗暴的递归了
项、表达式,都是以系数及字符串的形式存储的,个人也没有想着去怎么优化了
感觉上,是没有做到老师希望我们使用的继承和接口了...
对自己写的代码也不是很满意,感觉到了一些地方的冗余、繁琐
二、程序BUG分析
第一次作业:
互测bug:表达式结尾有 * ,会出异常,报错;
bug位置:Poly类构造函数Poly,使用正则分割乘号后,去除空白字符会有空字符串,没有进行判断,访问了空指针。
原因:思维漏洞,程序的繁琐逻辑;没有使用try-catch
第二次作业:
互测bug:表达式结尾有 *,不会判定为WRONG FORMAT;
bug位置:Term类构造函数Term,使用正则分割乘号,由于*后无字符,不会再进行是否为因子的正则匹配
原因:对String.split不熟悉;没有进行充分的测试
第三次作业:
强测、互测bug:对于表达式 -(x) 类,得结果(1)
bug位置:Term类方法derivation,求导后项的系数(正负号)判断错误,应该使用求导因子的正负号
原因:对于递归传参没有考虑清楚
互测bug:对于sin(sin(x)^5),output :WRONG FORMAT!
bug位置:Atom类中方法firA、NfirA,对于判断sin、cos可嵌套的因子种类不全面
原因:思路不清晰,进行了画蛇添足,可以直接以嵌套因子new一个因子,归到前面的分类中
三、发现BUG策略
1、进行基本功能测试,确定基础的求导公式正确
2、进行边界数据测试,包括空或极大的系数、指数......
3、找到一些关键代码进行逐行阅读(例如正则...),发现一些细节问题
4、大致理解思路后,对一些易错、易疏漏的点进行分类测试
5、随便瞎试
6、找同学求珍藏易错bug
四、Applying Creational Pattern
写作业之前,本人是不太了解对象构造模式的;
不过,这一单元中,我使用的对象构造方式比较接近factory模式。
对于表达式,每匹配到一个项/因子后,用factory构造相应的项/因子对象。
大概是
if(...matches(...)){
构造对象...
}else if(...matches(...)){
构造对象...
}
...
总结:
在oo第一单元的学习中,主要是学习了面向对象的思想和分层次的程序设计。
主要的感受就是,写代码前,一定要构思好程序的框架,都应该有哪些对象类型,类与类之间的关系是什么,
每个对象类型的数据、方法都应该有什么,不应该有什么......
一个好的思路,一个好的框架,写起来也更加明确,错误更少,事半功倍。
希望在接下来的学习中,带着oo思想,多思考,多练习吧。