OO第一单元总结

第一次作业

结构分析

Methodev(G)iv(G)v(G)
MainClass.main(String[]) 1 1 1
Poly.Derive() 1 3 3
Poly.Output() 1 6 9
Poly.Poly() 1 1 1
Poly.Poly(String) 1 2 3
Poly.add(BigDecimal,BigDecimal) 2 2 3
Poly.add(String,int) 1 6 8
ClassOCavgWMC
MainClass 1 1
Poly 4.17 25

第一次作业我的设计比较简单,用正则表达式解析输入,用Poly类来保存多项式,其中用HashMap保存每一项的系数和指数。这样的架构好写,但是缺点也致命,那就是缺乏可扩展性,导致我第二次作业需要重构。

Bug分析

由于第一次作业内容简单、代码量小,我在强测、互测中都没有被测出bug

发现别人Bug所采用的策略

我没有手写评测机做黑箱测试,而是通过看别人代码的方式做白箱测试,但是构造了一些我构思的可能出错的点,一无所获。最终我们房间也没有一起有效Hack。

第二次作业

结构分析

Poly.add(Poly)111
Poly.add(Term) 1 1 1
Poly.clone() 1 2 2
Poly.insert(Poly) 1 2 2
Poly.insert(Term) 4 4 5
Poly.isEmpty() 1 1 1
Poly.toString() 1 4 6
PowerFunc.PowerFunc(BigInteger) 1 1 1
PowerFunc.clone() 1 1 1
PowerFunc.derive() 1 2 2
PowerFunc.equals(Object) 2 1 2
PowerFunc.getType() 1 1 1
PowerFunc.hashCode() 1 1 1
PowerFunc.multiply(Factor) 1 2 2
PowerFunc.toString() 3 1 3
SinFunc.SinFunc(BigInteger) 1 1 1
SinFunc.clone() 1 1 1
SinFunc.derive() 1 2 2
SinFunc.equals(Object) 2 1 2
SinFunc.getType() 1 1 1
SinFunc.hashCode() 1 1 1
SinFunc.multiply(Factor) 1 2 2
SinFunc.toString() 2 1 2
Term.clone() 1 2 2
Term.derive() 5 4 5
Term.getSign() 2 1 2
Term.insert(Factor) 1 2 2
Term.insert(Term) 1 2 2
Term.mergable(Term) 7 5 9
Term.merge(Term) 1 3 3
Term.multply(Factor) 1 1 1
Term.multply(Term) 1 1 1
Term.toString() 3 7 9
ClassOCavgWMC
ConstantFactor 1.2 12
CosFunc 1.5 12
MainClass 4.36 61
Poly 2.22 20
PowerFunc 1.62 13
SinFunc 1.5 12
Term 3.2 32

第二次作业我重构了我的设计,换成一种使用类似于自动机(这篇中的讨论是以我第三次作业的架构写的,不过差别不大)的方式解析输入并判断格式。而保存的方式为Poly-Term-Factor三级,Poly中保存由Term组成的Arraylist,Term中保存由<Type,Factor>组成的HashMap,而Factor作为接口实现了ConstantFactor,PowerFunction,SinFunction,CosFunction四种类。

求导也是由各级之间分工完成。Poly对其中的每个Term逐个调用其求导方法,而Term中逐因子调用求导方法,再由各个Factor返回求导的结果。

Bug分析

这次作业我出现了一个bug,这个bug是当输出系数为0的项的时候没有输出加号(由于自己时间不够了,就没有把输出优化做到位)。这个bug的产生和我的架构无关,但是和我的开发、测试方式有很大关系。我沿用了OI时代养成的一个坏习惯,总是喜欢写完所有代码后才开始一个一个debug,而不是写完一个模块就测试一个模块,导致我debug时面对着800+行代码无法一一发现其中的细节错误。这个bug给我的教训就是要写完一个模块就测试一个模块,不要等把所有代码写完后一起测试。

另外我的架构有个不好的地方是把对输入的处理写在了主类中,而没有另写一个类,这导致我的输入处理写的偏面向过程。

发现别人Bug所采用的策略

这次我依然是自己预先构思一些测试数据与阅读别人代码相结合,遗憾的是尽管我们房间有一些有效Hack,我依然没有找到别人的bug,并且代码量的增加也导致了阅读代码的测试方法的效率大大降低。

应用对象创建模式

这次作业中,我的输入处理会在解析出因子的类别、指数等信息以后交给对应的类来创建对象,然后加入包含这个因子的项中,再把创建好的项加入表达式。

对比和心得体会

我的测试方法需要改进,在OI中代码量一般只有100行不到,多的也很少超过200行,把代码全写好再整体测试的方法还算可行。但是在几百行上千行的工程中,这样的测试方法必然是无法把每个细枝末节都测试到,因此也就很容易有漏网之bug。

第三次作业

结构分析

Methodev(G)iv(G)v(G)
ConstantFactor.ConstantFactor(BigInteger) 1 1 1
ConstantFactor.clone() 1 1 1
ConstantFactor.derive() 1 1 1
ConstantFactor.equals(Object) 2 1 2
ConstantFactor.getConstant() 1 1 1
ConstantFactor.getType() 1 1 1
ConstantFactor.hashCode() 1 1 1
ConstantFactor.isOne() 1 1 1
ConstantFactor.multiply(Factor) 1 2 2
ConstantFactor.setConstant(BigInteger) 1 1 1
ConstantFactor.toString() 1 1 1
CosFunc.CosFunc(BigInteger,Factor) 1 1 1
CosFunc.clone() 1 1 1
CosFunc.derive() 1 2 2
CosFunc.equals(Object) 2 2 3
CosFunc.getType() 1 1 1
CosFunc.hashCode() 1 1 1
CosFunc.isOne() 1 2 2
CosFunc.multiply(Factor) 1 2 2
CosFunc.toString() 2 1 2
MainClass.constantProcess(String) 3 4 8
MainClass.cosProcess(String) 4 2 5
MainClass.factorProcess(String) 8 8 9
MainClass.getFactor(String) 3 4 7
MainClass.getPoly(String) 8 5 11
MainClass.getPower(String) 5 4 9
MainClass.isNum(char) 1 1 2
MainClass.isSign(char) 1 1 2
MainClass.main(String[]) 1 5 5
MainClass.passWhite(String) 1 2 3
MainClass.polyProcess(String) 4 2 5
MainClass.powerProcess(String) 2 1 2
MainClass.sinProcess(String) 4 2 5
MainClass.termProcess(String,int) 9 5 11
MainClass.white(char) 1 1 2
Poly.Derive() 1 2 2
Poly.Poly() 1 1 1
Poly.add(Poly) 1 1 1
Poly.add(Term) 1 1 1
Poly.clone() 1 2 2
Poly.derive() 1 2 2
Poly.equals(Object) 2 1 2
Poly.getPower() 1 1 1
Poly.getType() 1 1 1
Poly.hashCode() 1 1 1
Poly.insert(Poly) 1 2 2
Poly.insert(Term) 5 5 6
Poly.isEmpty() 1 1 1
Poly.isOne() 1 1 1
Poly.multiply(Factor) 1 2 2
Poly.toFactor() 3 1 3
Poly.toString() 1 6 8
Poly.toTerm() 3 3 4
PowerFunc.PowerFunc(BigInteger) 1 1 1
PowerFunc.clone() 1 1 1
PowerFunc.derive() 1 2 2
PowerFunc.equals(Object) 2 1 2
PowerFunc.getType() 1 1 1
PowerFunc.hashCode() 1 1 1
PowerFunc.isOne() 1 1 1
PowerFunc.multiply(Factor) 1 2 2
PowerFunc.toString() 2 1 2
SinFunc.SinFunc(BigInteger,Factor) 1 1 1
SinFunc.clone() 1 1 1
SinFunc.derive() 1 2 2
SinFunc.equals(Object) 2 2 3
SinFunc.getType() 1 1 1
SinFunc.hashCode() 1 1 1
SinFunc.isOne() 1 1 1
SinFunc.isZero() 1 1 1
SinFunc.multiply(Factor) 1 2 2
SinFunc.toString() 2 1 2
Term.clone() 1 2 2
Term.derive() 5 4 5
Term.getSign() 2 1 2
Term.insert(Factor) 6 7 8
Term.insert(Term) 1 2 2
Term.mergable(Term) 7 5 9
Term.merge(Term) 1 3 3
Term.multply(Factor) 1 1 1
Term.multply(Term) 1 1 1
Term.toFactor() 4 2 4
Term.toPoly() 5 2 5
Term.toString() 3 7 10
ConstantFactor1.1813
CosFunc 1.44 13
MainClass 4.4 66
Poly 2.17 39
PowerFunc 1.44 13
SinFunc 1.4 14
Term 4 48

第三次作业比起第二次作业多了嵌套的情况,对于这一点我虽然没有在第二次作业中直接支持,但是也预留了扩展的余地。比起第二次作业开天辟地,第三次作业我只做了小小的改动便满足了需求。但是我的架构也有不少不好的地方。

首先输入的处理依然在主类中,依然有很明显的面向过程的影子。并且这次为了简化输出,给Term类添加了更多优化方法,导致Term类的方法数过多。另外,由于支持表达式嵌套,PolyProcess方法中出现了间接自己调用自己的递归,整个存储结构则出现了Poly-Term-Factor-Poly这样的相互调用。

Bug分析

本次作业我又出现了一个bug,由于沿用了上次作业中把x**2表达为x*x的优化,结果输出结果出现了格式错误。这虽然和架构无关,但是依然是我的考虑不周造成的。

发现别人Bug所采用的策略

本次互测,我的测试手段进行了大幅提升,变成了以手写评测机黑盒测试为主,手动针对性构造为辅。大多数人上次使用正则表达式解析输入,在本次作业中不得不重构,结果就有不少人栽在了输入上,有的人对于正负号的处理出现了错误,有的人把正确格式判成WF。

应用对象创建模式来重构

对象的创建基本和上次作业一样

对比和心得体会

两次作业我都因为一个细节的错误而大量失分,心痛之余,也不得不反思自己的坏习惯到底有多可怕。我应该多看看讨论区中关于测试方法等等的讨论。看别人成形的经验,了解大工程的开发、测试方法,这些是很有必要的,我会发现困扰我的问题其实别人早已提出了成熟的解决方案,比如TDD、Junit。我一直对讨论区中分享的方法有一种误解,以为不过是些花拳绣腿,对于我这样的实用主义者性价比太低。但是事实证明了,搞这些东西的人他们也是实用主义者,他们做这些就是为了避免更大的损失,这些损失,轻则是作业中无谓的丢分,重则可能是工作中项目的不可维护乃至饭碗的破碎。前人走过的路、踩过的坑,我更应吸取他们的教训,领会他们的经验,而不是以盲目的自信四处乱闯,结果重蹈覆辙。

 

原文地址:https://www.cnblogs.com/Brookssxj/p/12527337.html