OOP第一次作业
第一次作业
第一次作业思路:在第一次作业中有三个类:主类Main、判断字符串是否合法的类Strformat以及提取和转换数据的Poly。我先是将字符串进行合法性判断,再将其通过正则匹配匹配出项,最后通过项的所有可能情况进行分类讨论, 直接把求导结果放入ArrayList,最后将其进行合并,后通过print函数输出。
(1)基于度量来分析自己的程序结构
由于本次作业的难度不是很高,于是类的属性个数、方法个数、每个方法的控制分支数目和类总代码规模都不多。但是由于是初次面向对象,并没有很明白面向对象的含义,于是变成在Poly中面向过程,Poly的构造方法也有110行。而且在Poly类中,还将解析和求导整合在了一起,非常不利于代码的复用,而且Strformat的定位也不太清晰,应该使用一个InputHandler来处理字符串合法问题以及字符串解析问题。
由于本次作业难度不高,所以未分析耦合和内聚的情况。
类图如下
优点:第一次作业除了学习正则表达式没有什么优点。
(2)分析自己程序的bug
一个是使用正则表达式分割字符串出现的正则表达式漏了一些情况的问题,体现了对正则表达式的掌握不够熟练。
忽略了\v、\f的问题,使用\\s时不够重视细节。
(3)分析自己发现别人程序bug所采用的策略
在第一次作业中由于还不会使用对拍器和数据生成器,所以采用的是靠手写边界数据来进行手动测量。除了要重复运行各个Project的效率问题,大体上效果还较为不错。而且通过明白部分北侧程序的代码的设计结构来构造课程出现问题的测试用例。
第二次作业
第二次作业思路:在第二次作业中出现了加乘组合的情况,我一共使用了4个类主类Main、InputHandler、PolyNomial、Term,我采用的是是先判断字串的是否合法,然后对字符串进行处理,然后使用正则表达式来匹配单个项,再使用*作为分割条件分割出各个因子,然后提取出常数、幂函数、三角函数的指数,将其存储在Term中,将各个Term合并并且求导,再次进行合并并且进行关于sin(x)^2+cos(x)^2的化简,并且迭代多次,以解决化简后的项可以继续化简的情况。
(1)基于度量来分析自己的程序结构
这一次听从老师的建议,添加了InputHandler这一个类,但是并没有想清楚类与类功能分离这一要点,InputHandler也只是起着读入输入数据的作用,对于格式的判断仍旧是在PolyNomial中进行的,也就造成了PolyNomial难以复用的问题。在这一次作业中,类的属性个数、方法个数、每个方法规模、每个方法的控制分支数目、类总代码规模都控制的较好,没有出现明显的问题。
类图如下
这一次代码中,PolyNomial是由Term聚合而成的。类直接的耦合性较低
优点:PolyNomial由Term聚合而成,所以就使得程序较第一次的程序具有更加好的层次性。
缺点:仍旧没有构造出面向对象的结构,在类中的方法仍旧是函数。InputHandler没有实现应有的功能,导致虽然存在但毫无意义。
(2)分析自己程序的bug
在公测中没有出现bug,但在互侧中出现了\t和\\t的问题,我将字符串中的\t打成了正则表达式中习惯的\\t,使得一旦出先TAB就会出现问题。这是自己在测试时没有覆盖这一方面的疏漏。
(3)分析他人程序的bug
使用对拍器进行对拍(将整个工程打包,每个工程一个文件夹,使用Python进行调用以及数据比较),依靠自己手写的数据进行评测,由于这一次他人的程序无注释,难以理解,没有针对被测程序的代码结构来设计测试用例。
第三次作业
第三次作业思路:在第三次作业中,出现了表达式嵌套的情况,于是得使用递归下降的方法,先判断空格非法的情况,再去空格对字符串进行处理,隐藏括号内的+、*,然后恢复括号外的+、*,然后使用+和*分割出项和因子,在使用工厂创建因子对象,若是表达式进行递归分析。最后进行求导以及输出。
(1)基于度量来分析自己的程序结构
优点:对括号内的*和+进行处理,使在分割项和因子时,就变得很方便。
(2)分析自己程序的bug
在互测时被找到sin()内因子的处理疏漏导致sin(-6)会判断为WF,容易漏掉考虑的情况,也就是这一处理框架的一大问题。
(3)分析自己发现别人程序bug所采用的策略
使用对拍器进行分析,不过还是采用手写数据,加上sympy求特殊点进行比较的方法。发现了许多的bug,和上次类似,由于没有注释,难以看懂长代码,所以没有根据被测程序的架构进行测试点的构造。
(4)Applying Creational Pattern
在前两次的作业中,我并没有显式的运用设计模式,在第三次作业中,我使用了简单工厂来创建具体的表达式因子、三角函数因子、幂函数因子,然后统一求导,就充分的体会到了解耦的好处,明白了OOP的要点之一是低耦合。
如果要进行重构,我会将字符串的语法判断和解析单独封装在InputHandler中,降低因子和项的复杂度,然后在其中创建各个项和因子。然后在Main中调用求导。