BUAA_OO_2020_Unit1总结

oo第一单元的作业主题为表达式化简,主要学习目标为熟悉面向对象思想,理解并学会层次化设计

第一次作业

(1)UML图

(2)oo度量

 

 

 

 

 

(3)作业设计思路

Main类负责表达式的读入。Preprocess类负责表达式的预处理,目前只负责去空白字符。Lexer类负责解析表达式,Parser类递归下降,和Lexer一起将表达式解析成树状结构,形成表达式树。expr包中创建了Factor接口,并在Factor类中定义了抽象行为toPoly,返回Polynomial,Expr类、Number类、UnkownX类分别实现该接口并重写toPoly方法。其中,Expr类的terms属性为一组类为Term的容器,储存项;Term类的factors属性为一组类为Factor的容器,储存因子,形成递归层次结构,是将表达式解析成树状结构的基础。poly包中包含PolyTerm和Polynomial两个类PolyTerm表示形如a*xb形式的单项式,其中属性coefficient=a,power=b;PolyTerm储存由加号连接的多项式,多项式中的每一项都和PolyTerm表示的单项式相同。

(4)bug分析

此次作业较简单,并未发现bug

第二次作业

本次作业较第一次作业增加了三角函数因子,自定义函数和求和函数的处理。

(1)UML图

(2)oo分析

 

 

 

 

 

 本次作业比第一次作业更加复杂,处理sum和自定义函数的方法是简单粗暴的字符串替换,oo度量和第一次作业相比直线上升也是意料之中。

(3)作业设计思路

此次作业我在第一次作业的基础上做了一些修改。

1.增加Tri类来实现Factor接口

Tri类中的name属性用于储存“sin”或者“cos”,区分正弦和余弦函数;

2.PolyTerm更改为储存形如a*xb∏Tri(a*xb)c形式

在PolyTerm类中增加: private final HashMap<Tri, Integer> tris;  Integer 表示三角函数的幂次项

3.增加ReplaceFunc类和ReplaceSum

在表达式解析前,将自定义函数和求和函数替换

4.增加function包

用于储存输入的自定义函数

5.修改Term、Lexer和Paser

修改Term中的toString方法,使可以输出三角函数;修改Lexer和Paser使可以读取三角函数

(4)bug分析

此次作业的oo复杂度较高,bug较多也是意料之中的事情了。

1.遗漏三角函数内为负数的情况,即sin(-1)的情况;

2.三角函数中的co为int型,无法处理大数据型,即sin(21344454312)的情况;

3.sum函数中begin和end为负数的情况没有考虑;

第三次作业

本次作业较第二次作业放开了三角函数和自定义函数的限制。三角函数括号中的因子可以为表达式因子,自定义函数的实参可以包含自定义函数和求和函数。

(1)UML图

(2)oo复杂度

 

 

 

 

 

 (3)作业设计思路

 此次作业在第二次作业的基础上做了简单的迭代。

1.去除Tri类中的co和pow属性,增加Expr expr属性。

其实第二次作业我就想用这个处理方法,这样一来,Tri因子的输出以及读取都可以利用到第一次作业中的方法,形式会比较简单,而且第二次作业中三角函数中出现的负数、大数溢出问题都不会出现,但之前读取三角函数括号中内容的时候,不知道为什么,始终有个右括号不能被处理,导致报错。所幸第三次作业中,很顺利的读取到了三角函数括号中的因子(虽然相较上一次,我并没有什么修改)。

2.修改Function类

将Function类中的属性改为了:

private final char name;
private String content;
private final HashMap<Integer, Character> paras = new HashMap<>();
这个修改主要是因为第二次作业分别用三个字符储存形参的形式显得代码有点“丑陋”,所以我做了一些修改,这也也使得ReplaceFunc中的代码更好调整。

3.修改ReplaceFunc类

ReplaceFunc中增加方法

public HashMap<Integer,String> actParas(String s,HashMap<Character, Function> functions)

在该方法中可以读取实参,并将每个读取到的实参都进行sum函数和自定义函数的替换,最终将实参化为形如第二次作业的形式

 ReplaceFunc func1 = new ReplaceFunc(act.toString());
 String f1 = func1.replace(functions);
 ReplaceSum sum1 = new ReplaceSum(f1);
 String s1 = sum1.replace();

(4)bug分析

这次作业修复了第二次作业中已经发现的bug,但在互测过程中发现sum函数的begin和end不能使用int定义,需要使用BigInteger。

此外我还发现因为sum函数中替换i时没有加(),导致处理sum(i,-2,-1,i**2)之类的函数会出bug

发现bug策略

根据自己代码的已知问题,构造数据。观察他人代码逻辑较复杂处,尤其是分支结构比较多的情况,构建边界情况,进行测试。

心得体会

  • 寒假的pre很重要  

    在寒假的两次pre中,我初步建立了面向对象的设计思想,了解了类、接口、继承、实现等基础概念,并尝试构建了归一化结构。这使得我在面对第一次作业时更加从容。

  • 善于利用讨论区

    在讨论区中,我看到了许多有价值的帖子,帮助我形成自己的架构和规避一些bug。比如说,在自定义函数的替换中,在讨论区中,有人提出了需要将形参x在最后替换,

    避免重复替换的情况;还有替换的实参需要加括号等。这些都补上了我思考过程中的漏洞。

  • 好的架构很重要!

    一个好的架构具有良好的拓展性。第一次作业的架构做好了,第二次作业就可以在第一次的作业基础上进行拓展,而无需进行重构。此外,好的架构也容易定位bug。

  • 注重归一化设计

    归一化设计可以避免掉很多分支判断情况,使得代码更简洁,也不容易出现bug。

posted @ 2022-03-25 12:49  Hu_ly  阅读(39)  评论(0编辑  收藏  举报