本次博客做业,本人将以三次做业为单元进行分析,再借着讲查bug的方式说说本身的搭评测姬的方式,最后总结一些面向对象相关的经验。java
第一次OO做业的功能需求相对简单,本人把整个构造、简化输出以及它们用到的一些private方法所有丢到Polynomial类中实现,同时为了避免让文件数量太少显得尴尬我专门写了个求导类,用于求导功能的实现。因为第一次做业的业务逻辑以及优化逻辑相对简单,故这种“大锅菜”式的设计并无带来什么困扰,反而写的很快(雾正则表达式
如前文所言,本次做业,我写的比较面向过程,整个parse的过程所有丢在polynomial的一两个方法中完成,使得方法以及类的复杂度太高。多线程
这种设计在面对第一次这种较为简单的设计尚有生存的余地,当工程的复杂度持续走高的时候,仍然用这种方法基本上是自掘坟墓。less
第一次做业的主要难点在于正则表达式解析字符串,基本上用小正则不断分解字符串便可,大正则的朋友是真的狼。500行状态机的狼灭们,求求您们住手函数
第一次做业除了输入部分没啥坑点,因此很不巧,本人强测、互测都没被找出bug(摊手手学习
第一次做业的强测有一点点小尴尬,100分的门槛过低,致使一个屋内的水平差别有丶大,因此就出现了5锤3到4锤4的惨烈场面。测试
第一次做业中的BUG基本没有在计算上的问题,~~除了那些被不知道怎么混进来的,被捅了20多刀的朋友,~~问题主要在于输入处理上,好比先trim了一下再去判\v\f的状况,以及神奇的大正则爆栈。优化
这里要说个小插曲,在第一次讨论课分享后,本人竟然被人找上门婊了,对方的理由是“你不以为大家这种找别人\v\f的bug的行为很钻营么?”spa
这位同窗当时的意思(个人理解)是官方指导书说能够有“空白字符”,因此咱们用\v\f是钻营的。操作系统
exm??????
首先,WF问题原本就是官方规定的BUG之一,第一次做业并无取消这一hack方式,因此,hack这种数据彻底合乎规矩。
第二,互测自己就包括测试程序的鲁棒性,天然要测试程序在处理各类玄学输入状况的表现,输入\f\v有何不合理?
第三,官方给的“空白字符”有着明确的定义,横向制表符和空格符,咱们输入\v\f不属于此类。既然您喜欢先入为主,代入本身的主观理解,同时不去认真理解指导书的语义,那您被\v\f数据hack又岂是他人之过?
第四,水群里,讨论区里对于\v\f是否属于空白字符的讨论还少么?既然您喜欢自我封闭地处理本身不明确的定义,那么就请作好被hack的准备。
第五,本人对于那位同窗的水平也稍有认识,我不认为 ta 会跟我分到一个组,因此,冤有头,债有主,你找我干吗?
此次设计我用了常见的三级层次,最顶层为Poly,Poly由Term组成,Term由Factor组成。
此次的设计中,我仍然把Poly的构造与字符串检查与解析放在了Poly的构造函数中实现,同时把各类优化方法,是否包含Term的检查放在Poly类内部实现,使得这个类过于臃肿。
此外,此次的Term类内部也包含了各类计算方法,使得这个类有点臃肿。
Method | ev(G) | iv(G) | v(G) |
---|---|---|---|
CosFactor.CosFactor(BigInteger) | 1 | 1 | 1 |
CosFactor.derivation() | 2 | 2 | 2 |
CosFactor.toString() | 3 | 3 | 3 |
Factor.Factor(FactorType,BigInteger) | 1 | 1 | 1 |
Factor.getDegree() | 1 | 1 | 1 |
Factor.getType() | 1 | 1 | 1 |
FactorFactory.produce(FactorType,BigInteger) | 5 | 2 | 5 |
FactorFactory.produce(FactorType,String) | 2 | 2 | 2 |
Poly.Poly() | 1 | 1 | 1 |
Poly.Poly(ArrayList<Term>) | 1 | 2 | 2 |
Poly.Poly(String) | 3 | 2 | 5 |
Poly.add(Poly) | 1 | 4 | 4 |
Poly.betterSolution(ArrayList<Term>,Term,Term) | 3 | 4 | 9 |
Poly.canCos2ToOneSubSin2(Term,Term) | 1 | 3 | 5 |
Poly.canSin2AddCos2(Term,Term) | 1 | 2 | 3 |
Poly.canSin2ToOneSubCos2(Term,Term) | 1 | 3 | 5 |
Poly.cleanUp() | 1 | 3 | 3 |
Poly.derivation() | 1 | 2 | 2 |
Poly.getArrayList() | 1 | 1 | 1 |
Poly.getTerm(TermKey) | 1 | 1 | 1 |
Poly.hasTerm(Term) | 1 | 1 | 1 |
Poly.lengthBetter(Poly,Poly) | 1 | 1 | 1 |
Poly.main(String[]) | 1 | 3 | 3 |
Poly.mergeSin2AddCos2(Term,Term) | 1 | 4 | 4 |
Poly.mult(Poly) | 1 | 3 | 3 |
Poly.optimization() | 1 | 6 | 9 |
Poly.parsePoly(String,Pattern[]) | 2 | 5 | 6 |
Poly.parseTerm(Pattern[],Matcher,BigInteger) | 5 | 11 | 11 |
Poly.simplifyCos2ToOneSubSin2(ArrayList<Term>,Term) | 1 | 1 | 1 |
Poly.simplifySin2AddCos2(ArrayList<Term>,Term,Term) | 1 | 1 | 1 |
Poly.simplifySin2ToOneSubCos2(ArrayList<Term>,Term) | 1 | 1 | 1 |
Poly.sub(Poly) | 1 | 2 | 2 |
Poly.toString() | 3 | 3 | 4 |
PowerFactor.PowerFactor(BigInteger) | 1 | 1 | 1 |
PowerFactor.derivation() | 3 | 3 | 3 |
PowerFactor.toString() | 3 | 3 | 3 |
SinFactor.SinFactor(BigInteger) | 1 | 1 | 1 |
SinFactor.derivation() | 2 | 2 | 2 |
SinFactor.toString() | 3 | 3 | 3 |
Term.Term() | 1 | 1 | 1 |
Term.Term(ArrayList<Factor>) | 1 | 1 | 1 |
Term.Term(BigInteger) | 1 | 1 | 1 |
Term.Term(BigInteger,ArrayList<Factor>) | 1 | 1 | 1 |
Term.TermKey.equals(Object) | 4 | 1 | 6 |
Term.TermKey.getFactor(FactorType) | 1 | 1 | 1 |
Term.TermKey.hashCode() | 1 | 1 | 1 |
Term.add(Term) | 2 | 2 | 2 |
Term.contains(FactorType) | 4 | 3 | 4 |
Term.copy() | 1 | 1 | 1 |
Term.derivate() | 1 | 4 | 4 |
Term.getCoe() | 1 | 1 | 1 |
Term.getDegree(FactorType) | 2 | 2 | 2 |
Term.getFactor(FactorType) | 4 | 4 | 4 |
Term.getTermKey() | 1 | 1 | 1 |
Term.mult(BigInteger) | 1 | 1 | 1 |
Term.mult(Factor) | 1 | 1 | 1 |
Term.mult(Term) | 1 | 1 | 1 |
Term.put(Factor) | 3 | 3 | 3 |
Term.toString() | 7 | 7 | 9 |
Term.upToPoly() | 1 | 1 | 1 |
Class | OCavg | WMC |
---|---|---|
CosFactor | 2 | 6 |
Factor | 1 | 3 |
FactorFactory | 3.5 | 7 |
FactorType | n/a | 0 |
Poly | 2.92 | 76 |
PowerFactor | 2.33 | 7 |
SinFactor | 2 | 6 |
Term | 2.17 | 39 |
Term.TermKey | 2 | 6 |
可见,因为上文所述的设计结构上的欠考虑,此次的耦合度与复杂度是太高了。
主要体如今字符串解析,与各类Term,Poly的计算所有放在内部实现,所致使的臃肿。通过此次教训,本人在第三次做业对结构作出了必定的调整。
此次一部分同窗已经采用了多态的操做,这也就意味着,他们的Term内部极可能包含着几个Factor对象。
求导工做就是基于这几个对象的,这也就带来了一个问题,你的对象应该是可变的仍是不可变的,你的求导是直接改变对象自身属性仍是新建一个对象。
个人建议是对象不可变,任何运算都获得一个新的对象。这样能够有效防止本身时不时出现写着写着修改了一些共享的对象,从而致使一些本身一时看来匪夷所思的bug。
除了这个小难点之外就是优化了,本人数学不太好,因此此次涉及到各类数学公式的无聊的优化,我就随便搞了两三个就摸了。
本人此次没被查出bug,可是后来发现本身的hashcode彷佛写错了,但又好像没错,果真姿式水平不高,语言特性不熟悉。
此外此次强测有一些小插曲,致使了互测的神奇状况
本次公测中,我成功反向hack了公测数据(雾)
本次互测中我测出来的的BUG主要集中在输入处理部分,此次的正则表达式比上次难度提高了一些,可是并无本质区别,测出的bug更像是对指导书理解有误差。
计算的BUG主要在于合并同类项的时候在系数和指数的处理上出了些小BUG,以及在求导时忘了把那一项的系数乘上(雾
总而言之,此次的BUG中,WF的比率相对下降,计算、求导、优化的BUG更多。
本次做业我大致沿用了第二次做业的设计思路,多项式的结构分为三个层次 Poly,Term,Factor
稍有不一样的几点,
Method | ev(G) | iv(G) | v(G) |
---|---|---|---|
code.Calculator.add(Term,Term) | 5 | 5 | 5 |
code.Calculator.mult(Factor,BigInteger) | 1 | 1 | 1 |
code.Calculator.mult(Factor,Factor) | 1 | 1 | 1 |
code.Calculator.mult(Poly,BigInteger) | 1 | 2 | 2 |
code.Calculator.mult(Poly,Poly) | 1 | 3 | 3 |
code.Calculator.mult(Poly,Term) | 1 | 2 | 2 |
code.Calculator.mult(Term,BigInteger) | 1 | 1 | 1 |
code.Calculator.mult(Term,Factor) | 3 | 3 | 3 |
code.Calculator.mult(Term,Term) | 1 | 1 | 1 |
code.ConstantFactor.ConstantFactor() | 1 | 1 | 1 |
code.ConstantFactor.ConstantFactor(BigInteger) | 1 | 1 | 1 |
code.ConstantFactor.canExtract(Factor) | 5 | 3 | 6 |
code.ConstantFactor.canMerge(Factor) | 2 | 1 | 2 |
code.ConstantFactor.differential() | 1 | 1 | 1 |
code.ConstantFactor.equals(Object) | 3 | 1 | 3 |
code.ConstantFactor.extract(Factor) | 2 | 1 | 2 |
code.ConstantFactor.getValue() | 1 | 1 | 1 |
code.ConstantFactor.merge(Factor) | 1 | 1 | 1 |
code.ConstantFactor.optimization() | 1 | 1 | 1 |
code.ConstantFactor.toString() | 1 | 1 | 1 |
code.CosFactor.CosFactor(BigInteger) | 1 | 1 | 1 |
code.CosFactor.CosFactor(BigInteger,Factor) | 1 | 1 | 1 |
code.CosFactor.canExtract(Factor) | 5 | 4 | 7 |
code.CosFactor.canMerge(Factor) | 4 | 4 | 6 |
code.CosFactor.differential() | 3 | 2 | 3 |
code.CosFactor.equals(Object) | 5 | 4 | 7 |
code.CosFactor.extract(Factor) | 1 | 2 | 2 |
code.CosFactor.getInnerFactor() | 1 | 1 | 1 |
code.CosFactor.merge(Factor) | 1 | 1 | 1 |
code.CosFactor.optimization() | 2 | 2 | 3 |
code.CosFactor.toString() | 4 | 4 | 4 |
code.Extracter.extractForPoly(Poly) | 1 | 8 | 9 |
code.Extracter.extractTerm(Term,Term) | 5 | 6 | 8 |
code.Extracter.getSimplified(Term,Term) | 4 | 8 | 10 |
code.Extracter.getTheDeltaFactors(Factor,Factor) | 6 | 6 | 6 |
code.Factor.Factor(BigInteger) | 1 | 1 | 1 |
code.Factor.getDegree() | 1 | 1 | 1 |
code.Factor.upToTerm() | 1 | 1 | 1 |
code.Parser.Parser(String) | 3 | 1 | 3 |
code.Parser.checkBigDegree(BigInteger) | 1 | 1 | 1 |
code.Parser.clearBlank() | 1 | 2 | 2 |
code.Parser.getChar(int) | 2 | 2 | 3 |
code.Parser.getCosFactor() | 3 | 1 | 3 |
code.Parser.getDegree() | 2 | 2 | 2 |
code.Parser.getFactor() | 6 | 6 | 6 |
code.Parser.getInnerFactor() | 5 | 2 | 5 |
code.Parser.getPoly() | 2 | 6 | 7 |
code.Parser.getPolyFactor() | 1 | 1 | 1 |
code.Parser.getPowerFactor() | 4 | 3 | 4 |
code.Parser.getSinFactor() | 3 | 1 | 3 |
code.Parser.getTerm() | 4 | 6 | 8 |
code.Parser.staticCheck(String) | 3 | 3 | 5 |
code.Poly.Poly(ArrayList<Term>) | 1 | 1 | 1 |
code.Poly.canDownToTerm() | 1 | 1 | 1 |
code.Poly.cpTerms() | 1 | 1 | 1 |
code.Poly.deleteUseless() | 1 | 4 | 4 |
code.Poly.differential() | 1 | 2 | 2 |
code.Poly.downToTerm() | 3 | 2 | 3 |
code.Poly.equals(Object) | 9 | 3 | 10 |
code.Poly.getTerms() | 1 | 1 | 1 |
code.Poly.mergeSameTerm() | 1 | 4 | 4 |
code.Poly.optimization() | 1 | 2 | 2 |
code.Poly.toString() | 3 | 3 | 4 |
code.PolyException.PolyException() | 1 | 1 | 1 |
code.PolyFactor.PolyFactor(Poly) | 1 | 1 | 1 |
code.PolyFactor.canExtract(Factor) | 1 | 1 | 1 |
code.PolyFactor.canMerge(Factor) | 1 | 1 | 1 |
code.PolyFactor.cpInnerPoly() | 1 | 1 | 1 |
code.PolyFactor.differential() | 1 | 1 | 1 |
code.PolyFactor.equals(Object) | 4 | 4 | 6 |
code.PolyFactor.extract(Factor) | 1 | 1 | 1 |
code.PolyFactor.getInnerPoly() | 1 | 1 | 1 |
code.PolyFactor.merge(Factor) | 1 | 1 | 1 |
code.PolyFactor.optimization() | 3 | 3 | 3 |
code.PolyFactor.toString() | 1 | 1 | 1 |
code.PowerFactor.PowerFactor(BigInteger) | 1 | 1 | 1 |
code.PowerFactor.canExtract(Factor) | 3 | 2 | 4 |
code.PowerFactor.canMerge(Factor) | 2 | 1 | 2 |
code.PowerFactor.differential() | 1 | 1 | 1 |
code.PowerFactor.equals(Object) | 2 | 1 | 2 |
code.PowerFactor.extract(Factor) | 2 | 2 | 2 |
code.PowerFactor.merge(Factor) | 1 | 1 | 1 |
code.PowerFactor.optimization() | 1 | 1 | 1 |
code.PowerFactor.toString() | 2 | 2 | 2 |
code.SinFactor.SinFactor(BigInteger) | 1 | 1 | 1 |
code.SinFactor.SinFactor(BigInteger,Factor) | 1 | 1 | 1 |
code.SinFactor.canExtract(Factor) | 5 | 4 | 7 |
code.SinFactor.canMerge(Factor) | 4 | 4 | 6 |
code.SinFactor.differential() | 3 | 2 | 3 |
code.SinFactor.equals(Object) | 5 | 4 | 7 |
code.SinFactor.extract(Factor) | 1 | 2 | 2 |
code.SinFactor.getInnerFactor() | 1 | 1 | 1 |
code.SinFactor.merge(Factor) | 1 | 1 | 1 |
code.SinFactor.optimization() | 2 | 2 | 3 |
code.SinFactor.toString() | 4 | 4 | 4 |
code.Term.Term(ArrayList<Factor>) | 1 | 1 | 1 |
code.Term.Term(BigInteger) | 1 | 1 | 1 |
code.Term.Term(BigInteger,ArrayList<Factor>) | 1 | 1 | 1 |
code.Term.Term(Factor) | 1 | 1 | 1 |
code.Term.canDownToFactor() | 4 | 2 | 5 |
code.Term.canMerge(Term) | 11 | 7 | 12 |
code.Term.compareTo(Object) | 1 | 1 | 1 |
code.Term.containOnlyPolyFactor() | 6 | 3 | 6 |
code.Term.cpFactors() | 1 | 1 | 1 |
code.Term.cpSelf() | 1 | 1 | 1 |
code.Term.deleteUseless() | 1 | 3 | 3 |
code.Term.differential() | 1 | 4 | 4 |
code.Term.downToFactor() | 6 | 3 | 7 |
code.Term.getCoe() | 3 | 1 | 3 |
code.Term.getFactors() | 1 | 1 | 1 |
code.Term.getFactorsSize() | 1 | 1 | 1 |
code.Term.merge(Term) | 1 | 1 | 1 |
code.Term.mergeConstant() | 1 | 4 | 5 |
code.Term.mergeSameFactor() | 1 | 4 | 4 |
code.Term.mult(BigInteger) | 1 | 1 | 1 |
code.Term.mult(Factor) | 1 | 1 | 1 |
code.Term.mult(Term) | 1 | 1 | 1 |
code.Term.optimization() | 5 | 7 | 7 |
code.Term.toString() | 9 | 9 | 11 |
code.Term.upToPoly() | 1 | 1 | 1 |
code.Test.main(String[]) | 1 | 3 | 3 |
code.Test.outputLogic(Poly) | 1 | 2 | 2 |
Class | OCavg | WMC |
---|---|---|
code.BigDegreeException | n/a | 0 |
code.BracketException | n/a | 0 |
code.Calculator | 2.11 | 19 |
code.ConstantFactor | 1.73 | 19 |
code.CosFactor | 2.73 | 30 |
code.Extracter | 7 | 28 |
code.Factor | 1 | 3 |
code.FactorException | n/a | 0 |
code.FormatException | n/a | 0 |
code.Parser | 3.5 | 49 |
code.Poly | 3 | 33 |
code.PolyException | 1 | 1 |
code.PolyFactor | 1.45 | 16 |
code.PowerFactor | 1.67 | 15 |
code.SinFactor | 2.73 | 30 |
code.Term | 3.12 | 78 |
code.Test | 2 | 4 |
此次的复杂度主要在于Parser,Extracter,Term这三个类。
Parser中,我用了递归降低的操做,第一次使用这个方法,写得比较面向过程,也比较丑。
Extracter这个类是我周二晚上得知延时的消息后,连夜赶工的一个提公因式的类,时间紧促,就没有作太多的设计,致使比较丑。
Term类的设计中,我欠考虑了。本次个人主要优化操做是经过把Term转换成Poly或者转换成Factor来完成的,这须要不少的断定条件,我虽然把计算等方法提取出来了,可是这些断定方法我仍留在Term中,致使了较大的复杂度,这是设计上的败笔。
当加入了嵌套这一输入格式以后,单用正则表达式已经难以实现输入处理了。受同窗启发,我此次采用了递归降低的方法并结合正则表达式进行输入处理,利用正则表达式的group()来辅助递归降低的偏移量计算。效果相对较好。
因为第一次使用递归降低,在实现阶段,bug不断,常常出现漏加偏移量等BUG,并致使我在中测中浪费了大量提交机会。
这一次优化的重点在于去掉那些层次太深,且毫无心义的括号,本人此次的优化还算能够,可以去除掉多数状况的无心义括号。
此次本人测试本身代码的时候没有像之前那样先把数据生成器写好再进行测试,而是上来就手动测试并提交,致使BUG不断。
不过这些BUG都在于输入处理的递归降低之中,其余部分倒尚未找到bug。
不过,得益于那几天的血泪,公测、互测仍是满血过关。
此外,此次个人自动化测试还出了些小插曲,留到后头再说。
总得看来,此次课下测试真的把我打怕了,直到强测结果出来的时候才松了口气。
本人之后争取保证每次都作到“测试先行”
此次遇到的BUG又回到了输入处理上,这个也就没啥好说的了,递归降低处理这种多项式要注意的点仍是挺多的,没有自动化测试的状况下出现输入处理上的bug也很常见,虽然本不该该(
在本次做业的深夜爆肝中,我也时不时地和一些同窗交流问题。
其中一位同窗就说起了我以前说的共享对象的可变性致使的BUG。如今咱们面对共享对象出现的BUG的根源主要在于“对象”,“引用”没有分清,“深拷贝”,“浅拷贝”没分清,我我的的建议是,用不可变对象,每次计算或求导以后返回一个新的对象,而不在原有对象上修改,并利用JAVA的垃圾回收处理不被引用的对象。(想一想BIgInteger的计算,相似)
目前,咱们对于共享对象的问题主要在因而否可变,下一单元的多线程中共享对象怕是更加麻烦。(哭辽
今年和往年不同,再也不是一对一的solo,而是八人圣杯战争。
若是还像往年那样,逐字逐句地挑,显然有点太耗时间,且不太值得。
测试方法很简单,评测姬先每人扫上50份随机数据,若是有比较naive的bug的话,此时基本上就已经倒了。
以后对那些能顶50次的代码再进行千份级别的扫射,同时,本身打开代码看看有没有一些常见的BUG,并把本身曾出过问题的数据放进去测试。
若是这样子还没找到BUG,那大几率是没啥BUG了,不过总有例外,好比,我在自我测试的时候就扫出来过本身的一个BUG,是一个括号匹配问题的BUG,BUG很naive,可是我没注意到,通常状况下也不会生成那样的数据(好比") 1 ("识别不出来错误),扫射了几万份数据后终于查出。
因此对于那些足够“硬”的代码,我通常是睡觉的时候扫上个几万份,若是再没有BUG,就根据时间安排,决定是否要逐字逐句地找BUG。
这其中,每次做业均可以复用的是待测程序,标准程序的调用方法,结果存储的文件结构。
那么,为了代码复用,简化开发流程(留下了每次用C++从头rush评测姬的血泪)我利用java的继承和多态机制
实现了快速改装的评测姬。
下面简要介绍一下一些可能不那么丑的设计思路
1.文件结构
评测姬具备初始化文件夹与评测日志的方法。
每一个从者对应一个文件夹,Ruler做为标程。
每一个文件夹下存放对应从者的代码文件夹,以及各类测试数据的文件夹
各类测试数据的文件夹内存放着对应数据的测试结果以及统计信息。
2.测试数据生成器
测试数据生成器实现一个统一的“供弹”接口,使得咱们的评测姬能够选择不一样类型的测试数据。
这么作至少有一个好处,好比说,一我的的程序会在幂的整数带有正号的状况下崩溃,可是你又想找到他运算的BUG。那么,就能够为他设计一个幂不带正号的测试数据,从而便于区分非同质BUG。
利用评测姬进行扫射的基础是你的生成器足够强大,可以生成出命中对方思惟漏洞的数据(为何不说实现时的手残呢? 由于,这年头谁还没个评测姬了?)这也就要求,对方的思惟并无达到基本正确性的要求,而且你达到了。那么,你的数据生成器才是具备效力的。
此外,评测姬毫不仅仅是用来狼人的,不少时候是用来狼本身的,能够检查出本身思惟或者实现的错误。
这部分我将以我回答一些我思考过的问题的方式来呈现。
把问题用一个个点(对象)之间的联系方式来体现,从模型的构建上来看,比较方便且直观。
对此,我就想到了寒假摸得一个叫ROS的东西,那个机器人操做系统就是基于各个点之间的通讯来实现一个完整的功能,比方说,我如今想写一个自动驾驶(差速驱动转向)的程序,用java来写,我得有个轮子类,一个引擎类,一个地图类,一个雷达类,一个调度类,这些类组合成了一个新的类——小车,叫他小车有点low,那就叫他Pusher叭~,这个Pusher内部包含着上述几个类。在Ros中,体现为,引擎节点,雷达节点,调度节点等等。
在JAVA中,对象之间的联系由传参,返回值,共享对象之类的方式,ROS中也有请求服务方式(传参,返回值),话题方式(共享对象)。
说了这么多看似没啥关系的东西,我主要想说明一件事,我认为面向对象的做用主要体如今便于咱们把现实中的问题抽象出一个更贴近现实的模型,从而在思惟上解决起来更加容易。
前三次做业中,对象的复杂度愈来愈高,若是仍然把对象的建立经过一个简简单单的 new() 来实现,会致使,功能与建立过分耦合,代码复杂度骤然提升。因而我在第三次做业中把整个多项式最复杂的建立方式——字符串解析方式交由Parser实现。从而下降了复杂度。
此外,对于那些具备众多同类型属性、类似的不一样类咱们能够采用工厂的方式来建立新的对象,从而,进一步将对象的构造与功能分离,下降耦合度。