OO课第一单元总结
程序结构分析
在做作业时,花费了大量时间来学习递归下降算法,但是仍然没有看懂,所以在完成本单元的作业时使用了学校提供的预解析程序简化了作业的完成。
hw1
作业要求简介
- 读入一个包含加、减、乘、乘方以及括号的单变量表达式,输出恒等变形展开所有括号后的表达式
本次作业思路
- 在本次的作业中我我是利用TreeMap进行数据的储存,将函数的幂作为key,他们的系数作为value。且对于每一种运算都建立了一个类,使用了一个String类的容器来存储经过预解析处理之后的命令,利用operate类对其进行判断操作,其中neg、pow的操作可以通过已经搭建好的sub,mul来进行操作。在做加减运算时只需要遍历其中一个TreeMap,在另一个Treemap中找到是否有对应的key,如果有相同的key,那么进行运算,没有在TreeMap中进行添加。对于乘法操作则需要遍历两个TreeMap,将key相加,value相乘,存储在第三个TreeMap中。
- 在本次作业中我还建立了两个类,Exp和Getnum,由于每次执行完运算操作后时想将其以字符串的形式进行储存,所以利用Exp将TreeMap中的元素化成字符串,每次运算时又将字符串中的元素提取出来放进TreeMap中。当做完第二次作业之后我才意识到这不仅没什么用,还多次调用类中的方法增加了程序的复杂度和出bug的概率,完全做了无用功,感觉挺傻的。(;′⌒`)
类图
代码分析
hw2
作业要求变化
- 本次作业新增加了三角函数,求和函数,自定义函数,且括号层数增加。
本次作业思路
- 对于新增的函数作业要求我新增了类Sin,Cos用来处理,利用字符串拼接来完成该功能,为了便于后续的三角函数的化简,我在方法中加入了若三角函数中系数为负,则三角函数中的因子整体乘一次负的规定,例如sin(-x),会将其变为-sin(x)。
- 由于增加了三角函数,使得第一次仅仅使用TreeMap存储数据的方式失效,于是建立了一个新的类Factor来存储一个项,随后利用ArrayList来存储表达式。其中Factor中有一个系数coe,一个幂数power,一个TreeMaptrigs来存储三角函数,其中key是三角函数,value是幂,比如sin(x)**2*cos(x),则其存储形式是在一个coe=1,power=0,TreeMap中含有<sin(x),2>,<cos(x),1>的Factor中。
private BigInteger coe;
private int power;
private TreeMap<String, Integer> trigs = new TreeMap<String, Integer>();
- 由于数据存储的形式发生了变化,使得计算方式也产生了变化,该存储形式的变化主要是为了在进行乘法时对于带有三角函数的项可以做到一定程度的简化。在进行加减法时,建立了一个新的类Function,该类的方法主要是判断两个Factor的除系数外的部分是否相同,从而决定加减法应当如何进行。
类图
代码分析
method |
CogC |
ev(G) |
iv(G) |
v(G) |
Add.Add(List) |
0.0 |
1.0 |
1.0 |
1.0 |
Cos.Cos(List) |
0.0 |
1.0 |
1.0 |
1.0 |
Factor.addcoe(BigInteger) |
0.0 |
1.0 |
1.0 |
1.0 |
Factor.getCoe() |
0.0 |
1.0 |
1.0 |
1.0 |
Factor.getPower() |
0.0 |
1.0 |
1.0 |
1.0 |
Factor.getTrigs() |
0.0 |
1.0 |
1.0 |
1.0 |
Factor.setCoe(BigInteger) |
0.0 |
1.0 |
1.0 |
1.0 |
Factor.setPower(int) |
0.0 |
1.0 |
1.0 |
1.0 |
Factor.setTrigs(TreeMap<String, Integer>) |
0.0 |
1.0 |
1.0 |
1.0 |
Factor.subcoe(BigInteger) |
0.0 |
1.0 |
1.0 |
1.0 |
Mul.Mul(String, String, List) |
0.0 |
1.0 |
1.0 |
1.0 |
Neg.dothing(String) |
0.0 |
1.0 |
1.0 |
1.0 |
Operate.print() |
0.0 |
1.0 |
1.0 |
1.0 |
Pow.Pow(List) |
0.0 |
1.0 |
1.0 |
1.0 |
Sin.Sin(List) |
0.0 |
1.0 |
1.0 |
1.0 |
Sub.Sub(List) |
0.0 |
1.0 |
1.0 |
1.0 |
Cos.dothing(String) |
2.0 |
1.0 |
3.0 |
3.0 |
MainClass.main(String[]) |
2.0 |
1.0 |
3.0 |
3.0 |
Sin.dothing(String) |
3.0 |
1.0 |
3.0 |
3.0 |
Factor.addtrig(String) |
6.0 |
1.0 |
5.0 |
5.0 |
Pow.dothing(String, String) |
7.0 |
3.0 |
5.0 |
5.0 |
Add.dothing(String) |
10.0 |
4.0 |
7.0 |
7.0 |
Sub.dothing(String) |
10.0 |
4.0 |
7.0 |
7.0 |
Function.equals(Factor, Factor) |
19.0 |
8.0 |
6.0 |
10.0 |
Mul.dothing() |
21.0 |
1.0 |
9.0 |
9.0 |
Pos.dothing(String) |
31.0 |
2.0 |
12.0 |
15.0 |
Operate.gettype(String) |
34.0 |
1.0 |
20.0 |
20.0 |
Exp.getstring(ArrayList) |
74.0 |
2.0 |
32.0 |
33.0 |
Getnum.get(String) |
149.0 |
24.0 |
26.0 |
34.0 |
Total |
368.0 |
69.0 |
154.0 |
170.0 |
Average |
12.689655172413794 |
2.3793103448275863 |
5.310344827586207 |
5.862068965517241 |
class |
OCavg |
OCmax |
WMC |
Neg |
1.0 |
1.0 |
1.0 |
Cos |
2.0 |
3.0 |
4.0 |
MainClass |
3.0 |
3.0 |
3.0 |
Sin |
2.0 |
3.0 |
4.0 |
Factor |
1.4444444444444444 |
5.0 |
13.0 |
Pow |
3.0 |
5.0 |
6.0 |
Add |
4.0 |
7.0 |
8.0 |
Sub |
4.0 |
7.0 |
8.0 |
Function |
9.0 |
9.0 |
9.0 |
Mul |
5.0 |
9.0 |
10.0 |
Pos |
13.0 |
13.0 |
13.0 |
Operate |
10.5 |
20.0 |
21.0 |
Exp |
22.0 |
22.0 |
22.0 |
Getnum |
31.0 |
31.0 |
31.0 |
Total |
|
|
153.0 |
Average |
5.275862068965517 |
9.857142857142858 |
10.928571428571429 |
hw3
作业要求变化
- 本次作业支持因子嵌套在三角函数里面,并整体作为一个因子。
本次作业思路
- 由于之前将Factor存储转变为字符串存储,需要时再使用Exp进行转换的方法已经不再适用,所以想到了一个新的方法,建立新的类part,里面存储着Factor的容器,每次使用时只需要更新该容器,在最后输出的时候使用Exp将其转化为字符串进行输出即可。
类图
代码分析
Method |
CogC |
ev(G) |
iv(G) |
v(G) |
Add.Add(ArrayList) |
0 |
1 |
1 |
1 |
Add.dothing(String) |
12 |
4 |
7 |
7 |
Cos.Cos(ArrayList) |
0 |
1 |
1 |
1 |
Cos.dothing(String) |
24 |
1 |
10 |
13 |
Exp.getstring(ArrayList) |
74 |
2 |
32 |
33 |
Factor.addcoe(BigInteger) |
0 |
1 |
1 |
1 |
Factor.getCoe() |
0 |
1 |
1 |
1 |
Factor.getPower() |
0 |
1 |
1 |
1 |
Factor.getTrigs() |
0 |
1 |
1 |
1 |
Factor.setCoe(BigInteger) |
0 |
1 |
1 |
1 |
Factor.setPower(int) |
0 |
1 |
1 |
1 |
Factor.setTrigs(TreeMap<String, Integer>) |
0 |
1 |
1 |
1 |
Factor.subcoe(BigInteger) |
0 |
1 |
1 |
1 |
Function.equals(Factor, Factor) |
19 |
8 |
6 |
10 |
Getnum.get(String) |
5 |
1 |
5 |
5 |
MainClass.main(String[]) |
2 |
1 |
3 |
3 |
Mul.Mul(String, String, ArrayList) |
0 |
1 |
1 |
1 |
Mul.dothing() |
33 |
1 |
12 |
12 |
Mul.dothing2(ArrayList, ArrayList) |
29 |
1 |
10 |
10 |
Neg.Neg(ArrayList) |
0 |
1 |
1 |
1 |
Neg.dothing(String) |
3 |
1 |
3 |
3 |
Num.getnum(String) |
0 |
1 |
1 |
1 |
Operate.gettype(String) |
17 |
1 |
13 |
13 |
Operate.print() |
0 |
1 |
1 |
1 |
Part.addFactors(ArrayList) |
1 |
1 |
2 |
2 |
Part.addfacor(Factor) |
0 |
1 |
1 |
1 |
Part.getFactor(int) |
0 |
1 |
1 |
1 |
Part.getFactors() |
0 |
1 |
1 |
1 |
Pos.dothing(String) |
1 |
1 |
2 |
2 |
Pow.Pow(ArrayList) |
0 |
1 |
1 |
1 |
Pow.dothing(String, String) |
15 |
1 |
7 |
7 |
Sin.Sin(ArrayList) |
0 |
1 |
1 |
1 |
Sin.dothing(String) |
26 |
1 |
11 |
14 |
Sub.Sub(ArrayList) |
0 |
1 |
1 |
1 |
Sub.dothing(String) |
12 |
4 |
7 |
7 |
Class |
OCavg |
OCmax |
WMC |
Add |
4 |
7 |
8 |
Cos |
5.5 |
10 |
11 |
Exp |
22 |
22 |
22 |
Factor |
1 |
1 |
8 |
Function |
9 |
9 |
9 |
Getnum |
5 |
5 |
5 |
MainClass |
3 |
3 |
3 |
Mul |
7.67 |
12 |
23 |
Neg |
2 |
3 |
4 |
Num |
1 |
1 |
1 |
Operate |
7 |
13 |
14 |
Part |
1.25 |
2 |
5 |
Pos |
2 |
2 |
2 |
Pow |
4 |
7 |
8 |
Sin |
6 |
11 |
12 |
Sub |
4 |
7 |
8 |
三次作业过程中出现的bug
hw1
- 对于pow的系数是1时所作的特殊处理产生了错误,最终输出错误。
- 在某个类中处理的时候虽然注意到了需要使用BigInteger,但是使用的先转化为int,然后使用valueof(int)转换为BigInteger,没能了解到可以直接将字符串转换成BigInteger的用法,最终导致运行时报错。
hw2
- 对于三角函数中的因子如果幂大于1的情况考虑不周全,在判断三角函数的幂时仅仅使用了对于"**"查找的判断,忽略了可能因子的幂大于1但是三角函数的幂是1的情况,从而导致运行错误。
hw3
- 在第三次的弱测过程中出现了一个bug,由于第三次作业改动较大,在进行重构时对于修改的改动较大,所以在对三角函数中的因子乘-1时,出现了错误,导致输出的时候存在2*-sin(x)的错误。
互测和自测
互测
- 对于前两次作业,由于自己出现了BigInteger的错误,下载代码后发现部分同学虽然通过了弱测,但是是使用的long类型,所以在互相hack的时候使用了超过long的数据最终使得他们运行错误。
- 在第三次作业中,对于易错的三角函数的嵌套进行研究,发现有同学对于三角函数中的因子的多次幂的展开有错误,从而进行hack。
自测
- 对于前两次作业,每建立一个新的运算类,就对其进行功能的测试,便于找出bug。
- 自己构造复杂的数据,来测试程序是否能够正常运行。
架构设计的体验
- 在前两次的架构设计时自己设计的十分糟糕,中间有十分冗余的步骤,比如在字符串和Factor类之间进行多次的转换,而这种转换是十分复杂且容易出现问题,而且导致程序变得十分复杂难懂。
- 在第二次作业中设计了关于三角函数的存储方式,当时在设计时就考虑到了三角函数中的嵌套结构,从而使得第三次作业进行时对于数据存储的结构没有发生太多变化,大部分时间都在解决第一次确定的架构所留下的冗余和困难。
总结
通过这次单元作业我体会到了好的架构和坏的结构在迭代时所带来的完全不同的体验,明白了自己在学习的路途上还有很远的路要走,编写程序不仅仅要为了完成输入输出的任务,也要使其变得优美易懂。
心得体会
在本次作业中自己按时完成了各项作业,第一次体会到了迭代写作的感觉,但是对于始终没有学会递归下降的方法而感到十分的遗憾,在此次的博客撰写的过程中看到每一个代码的类图和各种分析之后也明白了自己的代码写的十分的糟糕,各种类的耦合度也比较高,完全没有达到课程组所要求的程度。且在作业的过程中发现自己仍然无法摆脱部分方法代码过长的问题,这也体现了自己在处理类与类之间的关系的过程中仍然出现问题,没有使用面向对象的思想和方法,仍然拥有很高提升空间。也明白了自己和同学们之间的差距,在日后的时间里面会和同学进行更多的交流,学习更优秀的思想,更加优美的代码风格。U=•x•=U