oo第一单元的作业是对多项式的求导。下面就是对三次作业分别进行分析。
第一次作业
分析
第一次作业相对来讲比较简单,甚至不用面向对象的思想都能十分轻松的完成(实际上自己就没有使用),包含的内容只有常数项和指数项。实际上这次作业给我的最大收获是初步认识了正则表达式的使用。程序的结构如下:
设计
结构十分简单,只有一个类(就是面向了过程。。。),类的构造函数用以处理输入的字符串,calcDiff()用来计算导数。
度量分析
从表格中可以看出来,factor()方法的复杂度与独立路径条数较高,这是因为这个方法中进行了太多的if-else判断,代码的分支条数太多,导致代码可读性不高。
强测
这次比较失误的是没有仔细审好题目,以为++x这种操作是不合法。导致扣了一定的分数。
总结
本次作业难度不高,对于刚刚学java的菜鸟还是十分友好的,但由于对面向对象的思想还是比较陌生,所以写出来的代码确实不忍直视。但是收获还是有的,比如学会了正则表达式等工具。
第二次作业
分析
这次作业明显就要比上一次的作业难度上有了很大的提升。以及老师在周四的课堂上最后说了一句,“觉得第一次代码写的不行就赶紧重构吧,否则第三次作业是一定过不了的”。于是乎果断重构了代码。通过揣摩指导书(提醒了这次作业三角函数中只有x这种变量),我提前预判到下次作业可能是复合函数求导hhh,所以在构思的时候就把复合函数考虑了进来,在factor类里增加了一个expression类型的私有属性。
设计
UML图如下:
与第一次作业相比,这次的设计要复杂的多,也有了面向对象的影子。
度量分析
这次有好几个方法的V(G)值很高,一部分原因是因为我考虑了factor中存在expression的因素,导致多了很多分支判断。另一部分原因是因为在做输出优化的时候没有想清楚具体的优化方法,单纯一味的if判断。
总结
因为这次所设计的需求超过了实际需求,所以耗费了很多的时间,但也为下次作业节省了不少时间。同时这次作业的测试规模已经十分之巨大了,所以我也学习了一下规模化规范测试的方法,用Junit进行了批量测试。
第三次作业
分析
实际上这次作业在发布之初我就非常的兴奋了,因为基本符合了我在作业二时所做的预判,总算没有白费功夫。。所以实际上我的代码结果和上次来讲基本相似,花费的时间也比较短暂,一天就完成了此次作业。比较大的区别就是在于输入判断这块,由于factor里面还有expression,这种带括号的文法是无法直接用正则表达式进行匹配的,所以我的解决方法是进行迭代处理。比如像sin((xcos(x)))这种Term,我是先将内部括号代换成x即sin(x),之后判断外层语法是否正确,然后在将(xcos(x))代换回来,等到factor内部的expression再进行判断。
设计
UML图如下:
总体思路和上次一毛一样,就是修改了一些细节以及增加了一些用来优化的方法。
度量分析
总结
实际上我的这个设计上是有很大的缺陷的,实际上像加减乘除运算都应该从factor,term,expression类中抽离出来,单独做一个运算类,高内聚,低偶和。而我现在所做的并没有达到这一目的。所以每次修改一个类的方法都会导致一连串的连锁反映,这也导致之后在强测的时候发现有一处判断没有修改而出现了错误。代码的可读性也差了很多。
Bug分析
三次作业的bug主要出现的位置就是在输入处理和优化上面,输入有审题不认真导致也有边界考虑不周全导致。这部分的处理确实十分的棘手也很麻烦。只要思维稍有不连惯性就很有可能出现了bug。优化上的问题从根本上考虑就是设计上的缺陷导致,没有很好的分析清楚各个类之间的继承关系,导致每个类内的书写非常的累赘。
分析自己发现别人程序bug所采用的策略
实际上我没有刻意的去挖掘他人的代码缺陷并精心设计针对性的测试程序,还是主要使用的黑盒来进行测试。在测试时,我编写了一个自动生成测试用例的脚本(sympy进行验证),来测试代码的正确性,会不会爆栈等。同时也人工设计了一些格式上有问题的数据来检测程序的输入处理上是否有问题。
Applying Creational Pattern
前两次作业因为功能相对简单,在没有创建模式的概念下也能比较舒服的完成。但第三次作业的时候就感到十分不舒服了。如果要让我重构的话,我觉得我会创建一个接口类以及常数类、三角函数类、表达式类、项类。用接口类给出不同的运算接口。然后再在每个类中实现它。
总结
这三次作业做的确实都比较仓促,由于还有别的一些事情,没有花费足够的时间在这上面,之后应该多花费时间在面向对象这门课来。
不过通过这三次作业,我对Java语言的掌握程度提升了很多,也对面向对象编程有了进一步的认识,逐渐摆脱了面向过程的思想。更加注重程序的可扩展性和鲁棒性。