其他分享
首页 > 其他分享> > 2022_BUAA_OO 第一单元总结

2022_BUAA_OO 第一单元总结

作者:互联网

2022_BUAA_OO 第一单元总结

OO第一单元的作业主题是表达式化简,主要的学习任务是熟悉Java语言基础操作,掌握面向对象的思想,学会并习惯用类来管理数据,实践分工协作的行为设计理念。以下便是我第一单元的学习心得与实践总结。

Homework1

代码结构分析

第一次作业涉及的表达式结构较为单一,实现的代码结构也相对简单。UML类图如下:

Method CogC ev(G) iv(G) v(G)
Lexer.Lexer(String) 0 1 1 1
Lexer.getCurToken() 0 1 1 1
Lexer.getNumber() 2 1 3 3
Lexer.next() 3 2 2 3
Lexer.process(String) 0 1 1 1
MainClass.main(String[]) 1 1 2 2
Operator.Operator() 0 1 1 1
Operator.Operator(BigInteger, BigInteger) 1 1 2 2
Operator.add(Operator, Boolean) 3 1 3 3
Operator.getCoef(BigInteger) 0 1 1 1
Operator.getMap() 0 1 1 1
Operator.merge(BigInteger, BigInteger) 5 1 3 3
Operator.mul(Operator) 8 1 7 7
Operator.output(StringBuilder, BigInteger, String) 4 1 2 4
Operator.power(Operator, BigInteger) 1 1 2 2
Operator.toString() 13 4 5 8
Parser.Parser(Lexer) 0 1 1 1
Parser.getNum() 3 1 4 4
Parser.parseExpr() 6 1 5 6
Parser.parseFactor() 8 5 5 5
Parser.parseTerm() 1 1 2 2
Class OCavg OCmax WMC
Lexer 1.6 3 8
MainClass 2 2 2
Operator 3.6 13 36
Parser 3.2 5 16

从代码复杂度分析数据中可以看到,绝大多数方法的圈复杂度以及模块设计复杂度都相对合理,只有Operator类中的toString方法的基本复杂度较高,主要原因是该方法的实现较为随意,缺乏较好的设计,同时追求在该方法内完成表达式的全部化简工作,导致诸多选择结构、循环结构等不完整。整体上来看,各方法的iv(G)都较低,各类的OCavg也处于正常水平,说明整体设计的内聚度还是较高的。

评测方面

由于结构相对简单,本次作业在各次测试中均未出现bug,整个房间也没有出现成功hack的样例,几无收获。。。

Homework2

代码结构分析

本次作业加入了三角函数、求和函数以及自定义函数因子,表达式结构的复杂度骤然上升,我不得已选择了重构。UML类图如下:

Method CogC ev(G) iv(G) v(G)
MainClass.main(String[]) 1 1 2 2
factor.Constant.parseFactor(Lexer) 12 1 8 8
factor.Expr.parseFactor(Lexer) 1 2 2 2
factor.FactorFactory.FactorFactory(Lexer) 0 1 1 1
factor.FactorFactory.getFact() 6 6 6 6
factor.Power.parseFactor(Lexer) 2 2 2 2
factor.Sum.parseFactor(Lexer) 18 2 11 12
factor.Triangle.parseFactor(Lexer) 23 3 7 11
factor.Vba.Vba(ArrayList, String) 0 1 1 1
factor.Vba.parseFactor(Lexer) 11 1 8 9
module.Element.Element(BigInteger, BigInteger, BigInteger) 0 1 1 1
module.Element.Element(Element) 0 1 1 1
module.Element.compareTo(Element) 4 5 4 5
module.Element.elementEqual(Element) 1 1 3 3
module.Element.getCoefficient() 0 1 1 1
module.Element.getInnerIndex() 0 1 1 1
module.Element.getOutIndex() 0 1 1 1
module.Element.setOutIndex(BigInteger) 0 1 1 1
module.FunctionSet.addEle(String) 3 1 3 3
module.FunctionSet.getEle(String) 0 1 1 1
module.Operator.Operator() 0 1 1 1
module.Operator.Operator(BigInteger, ArrayList) 0 1 1 1
module.Operator.Operator(BigInteger, BigInteger) 2 1 1 2
module.Operator.Operator(BigInteger, BigInteger, BigInteger, boolean, boolean, boolean) 0 1 1 1
module.Operator.add(Operator, Boolean) 16 1 8 8
module.Operator.getConstant() 0 1 1 1
module.Operator.getData() 0 1 1 1
module.Operator.getInnerIndex() 0 1 1 1
module.Operator.getTri(StringBuilder, Element) 6 1 4 4
module.Operator.isConst() 0 1 1 1
module.Operator.merge(Term, ArrayList) 9 4 5 5
module.Operator.mul(Operator) 10 1 5 5
module.Operator.pow(Operator) 1 1 2 2
module.Operator.toString() 42 3 12 14
module.Term.Term(BigInteger) 0 1 1 1
module.Term.Term(BigInteger, BigInteger, BigInteger, boolean, boolean, boolean) 8 1 3 5
module.Term.Term(Term) 2 1 3 3
module.Term.addAble(Term) 15 7 5 8
module.Term.getCoefficient() 0 1 1 1
module.Term.getCos() 0 1 1 1
module.Term.getIndex(Element, boolean) 14 6 8 8
module.Term.getSin() 0 1 1 1
module.Term.setCoefficient(BigInteger) 0 1 1 1
module.Term.termMul(Term) 26 1 9 9
proocess.Lexer.Lexer(String) 0 1 1 1
proocess.Lexer.getCurToken() 0 1 1 1
proocess.Lexer.getEle(boolean) 8 1 6 6
proocess.Lexer.next() 4 2 3 4
proocess.Lexer.process(String) 0 1 1 1
proocess.Parser.Parser(Lexer) 0 1 1 1
proocess.Parser.parseExpr() 6 1 5 6
proocess.Parser.parseTerm() 1 1 2 2
Class OCavg OCmax WMC
MainClass 2 2 2
factor.Constant 8 8 8
factor.Expr 2 2 2
factor.Factor n/a n/a 0
factor.FactorFactory 3.5 6 7
factor.Power 2 2 2
factor.Sum 9 9 9
factor.Triangle 11 11 11
factor.Vba 4.5 8 9
module.Element 1.5 5 12
module.FunctionSet 2 3 4
module.Operator 3.79 16 43
module.Term 3.5 9 35
proocess.Lexer 2.2 4 11
proocess.Parser 2.33 4 7

从代码复杂度分析数据可以看出,Operator类的toString方法的基本复杂度和模块设计复杂度都严重超标,这是由于基本存储单元模块设计较为复杂,导致输出需要考虑的情况众多,同时反映出我没有使用工程化思想设计该方法,主要是针对测出的bug进行缝缝补补。Term类中的termMul方法的基本复杂度和模块设计复杂度都较高,究其原因是我没有对于sin和cos集提取方法来统一处理。而是利用较多重复代码来处理,同时由于管理sin,cos集的是ArrayList,我需要在该类中对这两类的顺序进行维护。

从类复杂度分析数据可以看出,由于存储单元的变化,基本计算方法的实现过程的判断条件众多,再加上toString的不良设计,导致其总圈复杂度超标。

测评方面

本次强测出现了一个bug,是由于我初定的三角函数内部只能是幂函数或常数类,而为了能够处理常数的常数次幂的形式,我在自定义函数内用实参替换形参时均添加了括号,而这导致了三角函数内部可能出现了表达式因子,无法进行解析。这是出现bug方法的基本情况:

Method CogC ev(G) iv(G) v(G)
factor.Triangle.parseFactor(Lexer) 23 3 7 11

可以看出其圈复杂度还是处于正常范围,但其代码行数较长,这也导致我不易发现该bug。

在互测环节,我被测出了一个bug,由于本次作业中我的优化做的相对草率,对于sin()0进行无脑替换,没有考虑指数可能带有前导0。同时我测出了其他同学没有正确处理类似于sin(-1)2的形式,由于优化考虑不到位而输出-sin(1)^2,还有同学没有考虑toString输出为空的情形而出错。

Homework3

代码结构分析

本次作业支持三角函数内部嵌套因子类型,以及自定义函数可以进行嵌套,我选择在第二次作业的基础上进行增量开发。UML类图如下:

Method CogC ev(G) iv(G) v(G)
MainClass.main(String[]) 1 1 2 2
factor.Constant.getNum(Lexer) 3 1 4 4
factor.Constant.parseFactor(Lexer) 2 1 2 2
factor.Expr.parseFactor(Lexer) 1 2 2 2
factor.FactorFactory.FactorFactory(Lexer) 0 1 1 1
factor.FactorFactory.getFact() 6 6 6 6
factor.Power.parseFactor(Lexer) 2 2 2 2
factor.Sum.parseFactor(Lexer) 18 2 11 12
factor.Triangle.parseFactor(Lexer) 21 3 6 11
factor.Vba.Vba(ArrayList, String) 0 1 1 1
factor.Vba.parseFactor(Lexer) 5 1 5 5
module.Element.Element() 0 1 1 1
module.Element.Element(BigInteger, HashSet, boolean) 0 1 1 1
module.Element.Element(Element) 0 1 1 1
module.Element.compareTo(Element) 4 5 4 5
module.Element.elementEqual(Element) 1 1 2 2
module.Element.equals(Object) 3 3 2 4
module.Element.getFactors() 0 1 1 1
module.Element.getIndex() 0 1 1 1
module.Element.hashCode() 0 1 1 1
module.Element.isExpr() 0 1 1 1
module.Element.setIndex(BigInteger) 0 1 1 1
module.Element.sumLength() 1 1 2 2
module.FunctionSet.addEle(String) 3 1 3 3
module.FunctionSet.getEle(String) 0 1 1 1
module.Operator.Operator() 0 1 1 1
module.Operator.Operator(BigInteger, BigInteger) 0 1 1 1
module.Operator.Operator(BigInteger, HashSet) 0 1 1 1
module.Operator.Operator(Operator, BigInteger, boolean, boolean, boolean, boolean) 0 1 1 1
module.Operator.add(Operator, Boolean) 16 1 8 8
module.Operator.factorExtract(BigInteger, Term, StringBuilder) 34 1 11 11
module.Operator.findRepeat(HashSet, Element) 3 3 3 3
module.Operator.getConstant() 0 1 1 1
module.Operator.getData() 0 1 1 1
module.Operator.getTri(Element, boolean) 12 3 9 11
module.Operator.merge(Term, HashSet) 12 4 6 6
module.Operator.modeCheck(String) 14 3 8 13
module.Operator.mul(Operator) 10 1 5 5
module.Operator.nonEquSquare(Term, Term, HashSet, boolean) 9 1 11 12
module.Operator.pow(Operator) 1 1 2 2
module.Operator.searchEle(HashSet, HashSet) 5 3 2 4
module.Operator.simplify1(Term, HashSet, boolean) 54 5 13 18
module.Operator.simplify2(Term, HashSet) 35 11 14 17
module.Operator.splitFactors() 13 1 6 6
module.Operator.toString() 13 6 7 9
module.Term.Term() 0 1 1 1
module.Term.Term(BigInteger) 0 1 1 1
module.Term.Term(BigInteger, HashSet, boolean, boolean, boolean, boolean) 8 1 3 5
module.Term.Term(Term) 2 1 3 3
module.Term.addAble(Term) 1 1 1 2
module.Term.findElement(Term, Element, boolean) 12 6 4 6
module.Term.getCoefficient() 0 1 1 1
module.Term.getCos() 0 1 1 1
module.Term.getSet(boolean) 2 2 1 2
module.Term.getSin() 0 1 1 1
module.Term.orderIn(Boolean) 2 1 2 2
module.Term.setCoefficient(BigInteger) 0 1 1 1
module.Term.termMul(Term) 8 1 5 5
module.Term.toString() 6 1 5 5
proocess.Lexer.Lexer(String) 0 1 1 1
proocess.Lexer.getCurToken() 0 1 1 1
proocess.Lexer.getEle(boolean) 8 1 6 6
proocess.Lexer.next() 4 2 3 4
proocess.Lexer.process(String) 0 1 1 1
proocess.Parser.Parser(Lexer) 0 1 1 1
proocess.Parser.parseExpr() 6 1 5 6
proocess.Parser.parseTerm() 1 1 2 2
Class OCavg OCmax WMC
MainClass 2 2 2
factor.Constant 3 4 6
factor.Expr 2 2 2
factor.Factor n/a n/a 0
factor.FactorFactory 3.5 6 7
factor.Power 2 2 2
factor.Sum 9 9 9
factor.Triangle 10 10 10
factor.Vba 3 5 6
module.Element 1.58 5 19
module.FunctionSet 2 3 4
module.Operator 3.65 14 43
module.Term 2.5 6 35
proocess.Lexer 2.2 4 11
proocess.Parser 2.33 4 7

从代码复杂度分析数据可以看出,由于本次对于toString方法内部提取了若干方法,同时进行了分层的封装处理,这个毒瘤终于被拿掉,但是简化相关的方法由于判断条件众多,简化形式众多而表现出较高的圈复杂度和模块设计复杂度、

从类复杂度分析来看,本次作业与上次情况大致相同,各类的内聚度依然较小。

评测方面

强测方面,由于忘记考虑三角函数内部嵌套的sum或自定义函数的解析结果可能是表达式,忘记添加括号,导致输出格式错误。这是出现bug方法的基本情况:

Method CogC ev(G) iv(G) v(G)
factor.Triangle.parseFactor(Lexer) 21 3 6 11

其圈复杂度和代码行数与其他方法相比并无异常,这主要是我考虑不周以及测试不到位引起的

互测方面,又由于sum内部循环变量的数据类型使用的是int类,而被房间的同学群起而攻。同时我发现有较多同学没有考虑常数的常数次幂的情况。

发现BUG策略

为实现覆盖性测试,我认为应当对知道数的形式化描述进行细致分析,然后从最底层的因子开始向上分析构建样例,尽量覆盖全部情况,同时注意指导书中给出的一些情况的特殊处理,如sum函数内的求和上限低于下限的情况。再次要在一些边缘数据上下功夫,如测试一些0特殊情况、因子单独出现、考虑选取的数据类型的范围。由于时间问题,我没有尝试构建自动化测试。

心得体会

标签:OO,Term,Lexer,BUAA,module,Element,2022,factor,Operator
来源: https://www.cnblogs.com/luiluizi/p/16054130.html