oo第一单元Java实现多项式求导总结
第一次作业
-
架构概述
Item类的构造方法会循环地进行幂函数或者常数的匹配,并不断分析刷新Item的factor和index属性,最终存入Poly的ArrayList中。
-
(1)基于度量的分析
类的属性方法和代码规模
类 属性个数 方法个数 代码规模 Task1 0 2 25行 Poly 2 6 114行 Item 2 10 124行 每个方法规模、每个方法控制分支数目:

分析类的内聚和相互间的耦合情况:

通过Iv(G)的大量标红可见,Poly类和其他类的调用关系较为严重,toString和构造方法,此外根据ev(G)可见,toString方法的非结构化程度较大,偏离了程序的高内聚低耦合的原则,应当加以调整和优化。
类图及优缺点

三个类poly,item,task没有用到继承关系,仅有的优点是适合熟悉面向过程的人熟悉java的编程,但是不利于程序的扩展,后续的程序只能进行重构了。
poly类根据+-号对字符串进行切分,item紧接着根据乘号对已经切割过的字符串进行再度切分,进而传入构造方法中产生对象。
(2)自己程序的bug分析
这次作业难度较为简单,不容易出错,强测和互测都没有出现bug,就不在这里进行深入分析啦。
(3)发现别人程序bug所采取的策略
第一次作业的代码量少,我是先简单读一读对方程序的逻辑,据此判断一下是否有存在bug的可能,没有采用评测机,自己手动列了一些输入结果进行尝试,确实是结合了被测程序的设计结构来构造的,可惜在第一次作业中互测屋内始终没有bug被发现。
(4)重构经历总结
刚开始接触面向对象思路并不熟练,完成第一次作业前,我曾几乎是完全的面向过程进行程序设计,好在时间还有富余,进行了重构,结合了面向对象的设计思路进行重新构思,逐渐建立起了从第一次作业到第三次作业的逻辑框架。
(5)心得体会
第一次作业难度不大,但是利用第一次作业可以在一定程度上提升自己面向对象思想的应用,实现从其他语言向java的过渡。
第二次作业
-
架构概述
有了三角函数和允许非三角函数内的括号嵌套,使得第二次作业的难度陡增,,在Poly对输入的字符串进行处理之后,任意一个字符串str,都是a-b*e-c的类型,先根据+-号进行切分,再在Item里面根据乘号进行切分,传入工厂方法中,返回每一种具体类型的Poly子类对象。
Poly和Item类型都有一个Arraylist属性,用来存放各个该类型的各种项或者因子,
-
(1)基于度量的分析
类的属性方法和代码规模

每个方法规模、每个方法控制分支数目:


sin和cos类基本一致,主类较简单,不再赘述。
分析类的内聚和相互间的耦合情况:

此次的作业难度较上次而言因为嵌套递归的存在大幅提升,因为时间紧促很对地方都设计不到位,导致类之间方法的调用较为复杂,程序的结构性不够好。
类图及优缺点

继承关系较为符合实际逻辑,便于编写代码,子类可以存放在父类的容器中,并且对父类的方法进行对应的重写,容易进行统一的解析和运算,而且可拓展性强。
缺点是代码之间的关联度高,不容易达到“高内聚低耦合”的原则,程序的结构化程度不是很好。
各种类设计的考虑:Sum类是最抽象,最笼统的类,设计它可以充分利用多态,减低程序复杂性,Mult是乘积类,多个项连乘必须用到的类,下设Basic类将其子类的代码写在Basic上面,那么子类需要重写很少的方法就行,而且容易进行错误排查。
(2)自己程序的bug分析
第二次作业因为最后在输出的时候把”0+“替换成了空串,造成了许多意想不到的错误格式,化简的时候没考虑清楚,造成的尴尬真的是一言难尽,因为这一个错误,被疯狂hack,以后一定要长记性。当时应该做的是当对象在容器的时候就应该根据条件进行删除操作,而不是在最后进行字符串的查找替换。
该bug出现在toString方法中,有metrix分析可知,该方法的圈复杂度高,造成的bug难以预料,再设计时需要进行功能上的梳理和分解,降低单个方法的圈复杂度和代码行数。
(3)发现别人程序bug所采取的策略
这次代码的复杂度容易掌握,同时在写第二次作业的时候也积攒了一些测试用例,并结合互测屋内其他人的代码,进行针对性的hack,取得了不错的hack成绩,
同时也被hack了好多次,当时根据让对方爆栈,让对方的输出大于作业要求的字符串长度,还有自己手动尝试的一些用例,第一次体会到了疯狂hack别人的快感。(4)重构经历总结
本来以为这次作业不会出现sin括号内的嵌套,就设计了
a*x**b*sin(x)**c*cos(x)**d的模式,但是作业一出,人都傻了,就只能硬着头皮重构,从继承关系,到父类方法的设计,子类方法的重写,以及涉及到递归的工厂模式,进行了一番思考,刚开始的一两天写出的程序总不能很好的运行,调试了好久,最终赶在ddl前完成了此次作业。(5)心得体会
通过第二次作业,我意识到,要想写出一个健壮的程序,其架构一定要设计的足够合理,确定了宏观的逻辑,才方便于进一步的实现,其中通过工厂方法的应用,可以便捷的处理从字符串到相关类的对象的构建,在今后的作业中要增强实践,将好的方法和思想进行深入学习。
第三次作业
-
架构概述
第三次作业的变化不大,继承关系也类似,这次采用了sin,cos,常数,幂函数的共同抽象父类Basic使得程序看上去比较简洁,更加有利于编写。在格式判断方面,我一方面挑出一部分格式错误,另一些很明写的拼写错误交给程序运行,如果报出异常,意味着错误格式的发生,不是很纯粹的判断,容易产生bug。
-
(1)基于度量的分析
类的属性方法和代码规模

每个方法规模、每个方法控制分支数目:


未罗列的类均为basic的子类,仅重写了Basic类的构造方法。
分析类的内聚和相互间的耦合情况:

此次较第二次作业加入了格式判别,且笔者对此次作业进行了较为完善的化简,一定程度上增加了程序的复杂性,而且对程序各功能的规划设计的不够好,结构化失调,复杂度较高,容易出现bug,对于高内聚低耦合的原则没有充分的利用。
类图及优缺点

跟第二次作业一样,继承关系较为明朗,编写代码的时候不容易出现逻辑错误,子类可以存放在父类的容器中,并且对父类的方法进行对应的重写,容易进行统一的解析和运算,而且可拓展性强。
缺点是代码之间的关联度高,不容易达到“高内聚低耦合”的原则,程序的结构化程度不是很好。
各种类设计的考虑:Sum类是最抽象,最笼统的类,设计它可以充分利用多态,减低程序复杂性,Mult是乘积类,多个项连乘必须用到的类,下设Basic类将其子类的代码写在Basic上面,那么子类需要重写很少的方法就行,而且容易进行错误排查。
(2)自己程序的bug分析
本来以为第三次作业相对于第二次作业的难度提升不是很大,不容易出现奇怪bug,但是没想到格式检查的部分既容易出现漏检,有容易输出带有错误格式的字符串,真的是让人头大。
第一个bug是因为x**2变化为两个x相乘,在sin和cos的括号内,我会先进行判断,看其内是不是基本类型,x的二次方是符合的,故省去了一层括号,但是最终字符串输出的时候因为这个化简,导致大量的同质bug,真的是得不偿失,一定要在字符串转化的时候考虑清楚会带来哪些错误,最好能进行一个全方位的检测。
还有一个bug就是没有识别出sin(+ 9)这种错误格式,当时我考虑了许多种关于正负号和数字之间有没有空格的错误类型,但是偏偏漏了这一种,以后不能靠脑子枚举了,必须要通过一个形式化可操作性的方式,能够找出所有的错误类型才行。
果然,出现bug的代码所在的方法的代码行数和圈复杂度较高,容易遗漏掉一些情况,造成bug的出现。
(3)发现别人程序bug所采取的策略
第三次作业我没有用评测机,还是通过手动构造用例的方式进行,也结合了被测程序的设计结构来构造,但是由于第三次作业的复杂度较高,在阅读别人的代码的时候有一定的难度,比较花费时间,且就像对自己的程序进行测试的时候一样,很容易遗漏一些bug,很难做到全面覆盖,所以没能hack到别人,下一阶段自己一定要深入研究,动手搭建评测机。
(4)重构经历总结
第三次作业相对于第二次作业而言,改变并不是很大,但是格式检查确实有点麻烦,花费了一半的时间进行思考和实现。原来以为这次会加入多想是的指数次方,刚开始的时候加入了这种情况,后来考虑到需要进行格式检查, 而我的格式检查写的不够纯粹,需要在程序运行过程中进行判断,所以忍痛去除了这一功能。
(5)心得体会
经历了这三次作业的洗礼,确实体会到OO课程的难度,但是收获也很多,能够熟练使用java编程,能够将面向对象的思维运用起来,我觉得这难能可贵,在这三次作业的过程中,不乏一些bug因为很小的一个过失而产生,究其根本,还是自己有点懒,没有思考全面,进一步要改掉这个毛病。
这三次作业对我而言是一个非常有利的锻炼,引导我走向面向对象的殿堂,非常感谢课程组的老师和助教们的辛勤耕耘和慷慨帮助!

浙公网安备 33010602011771号