OO2021-第一单元作业总结

OO2021-第一单元作业总结

 

第一次作业

 

本次作业目标是对表达式结构进行建模,完成单变量多项式的括号展开,初步体会层次化设计的思想。

(1)基于度量来分析自己的程序结构

类分析如下所示:

  可以看出部分类的复杂度很高。其中Calculator的复杂性在于需要对运算种类进行判断,每一次判断都将产生出一个新的分支。如果想要降低Calculator的复杂度,可以考虑为各种运算符号构建一个类。

  其次calpart.Molecule的复杂度也很高,Molecule类作为主要的运算单元,需要实现多项式的表达,并且能够和其他的Molecule进行运算,还参与到Calculator本身的构成中。但我认为Molecule的高复杂性是不可避免的,其必须要承载高复杂度的数据结构。

方法分析如下所示:

 

  由于篇幅没有完全展示,在本次作业中复杂度高的方法有Calculator类的构造方法,其需要将获取到的一个后续表达的字符串转化为Molecule的对象。另外还有Molecule的加法和减法运算比较复杂,从中也可以看到方法度往往与其实现功能本身的复杂性和工作量挂钩。

术语解释:

ev(G) 基本复杂度:衡量程序非结构化程度,非结构化程度高会使得难以模块化和维护。

iv(G) 模块设计复杂度:衡量模块判定结构,即模块和其他模块的调用关系。软件模块设计复杂度高意味模块耦合度高,这将导致模块难于隔离、维护和复用。

v(G)圈复杂度: 衡量模块判定结构的复杂程度,数量上表现为独立路径的条数,即合理的预防错误所需测试的最少路径条数,圈复杂度大说明程序代码可能质量低且难于测试和维护。

类图如下所示

 

 

  在最顶端是主方法Mainclass,为了实现题目要求将内容分给了Lexer, Perser, Calculator三类处理。而Parser为了做到将输入转化为后续字符串,又进一步使用了表达式(Expr),项(Term),因子(Factor)类等,在转换完成后返回一个Expr对象,而Calculator则将这个Expr中的后续表达式进行运算化简。因此Calculator又需要使用分子(Molecule)和原子(Atom)两个类。

优点:

1. 层次逻辑清晰,体现了创作者高超的编程水平。
2. 数据结构,不同模块的作用和分工明确。
3. 扩展性强。

缺点:

1. 小缺点是部分类的功能比较强大,相应的复杂度高。比如Molecule就承担了4种运算功能,不过隔壁的BIgInteger默默点赞。

(2)分析自己程序的bug

  第一次作业中无论是别有用心的中强测,还是群雄争霸的互测,本代码都轻而易举地过了。虽然,还是有一些性能上的bug。

  那时的我还比较年轻,在使用Molecule进行相互运算的过程中,没有复制出新的Molecule,而是直接在原有的Molecule上进行运算。当然,为了避免原有的Molecule在我不知情下被使用,运算方法会返回新的Molecule对象。但出于巧合,在乘法计算中没有使用等号进行重新赋值,而原有的Molecule对象被改变使得测试总能通过。

  悲剧还是在强测中发生了,见下图。

 

  旧有的Molecule中为0的系数没有被清理掉,直接输出导致本测试点的性能分为0。此时我才明白,前辈BigInteger在运算后不修改原有值实乃明智之举。

(3)分析自己发现别人程序bug所采用的策略

  第一次测试房间里所有人共计发起27次hack,但大家都相安无事。我也有下载别人的代码用本地的测试机跑,但有的同学使用了预处理,有的同学没有实现指数8以上的功能(本次允许),这使得本地评测机受到极大限制。即便有可以正常测试的,也总是AC all。

  于是,第一次debug无功而返。

第二次作业

 

  本次作业额外加入了三角函数,自定义函数,求和函数。

(1)基于度量来分析自己的程序结构

类分析如下所示:

 

 

  本次类分析中似乎可以看见醒目的红,一种合理的解释是标红的类复杂度过高了。那就进一步思考复杂度过高的原因吧,一方面是数据结构本身就比较复杂,另一则可能是面向对象思想学的还不够到位。在引入了三角函数后,Atom和Molecule仍然要实现相关运算,又缺乏新的类来分担工作量,致使类的复杂度显著增大。

方法分析如下所示:

  类分析存在的问题也在方法分析时也有所体现。此处为了支持三角函数的加法运算,并且在相加的同时还可以实现三角函数的化简,使得Atom与Atom之间的运算过程更为复杂,甚至还为此引入了工具类Simple。但其实这里也是一个权衡的问题,可以通过不断构造其它函数使本函数复杂度降低,但函数与函数之间牵连关系就变强了,而且构造出的函数的确只需要在使用在一个地方。

类图如下所示:

 

 

优点:

  1. 相较于第一次作业只是增加了三角函数和自定义函数的类。

  2. 各个类之间的分工明确,构造清晰。

缺点:

  1. 在不断进行功能性的扩展中,部分类已经变得相当复杂了。

(2)分析自己程序的bug

  中强测和互测都是接近完美的,只是没有实现过多的化简功能。

  谈一下课下时找到的bug吧。由于阅读指导书不仔细,忽略了有关sum函数的约定。另外在三角函数中只能有因子,比如x**2不能写成x * x, 因此阅读报告还是要仔细啊。

(3)分析自己发现别人程序bug所采用的策略

  这次评测中很多同学为了性能分进行了三角函数的化简,不过逻辑并不正确,比如-sin(-1)**2就存在很多同学都没有能够正确处理。还有就是cos(0)和sin(0)也让不少同学折戟,这类属于化简思路错误。

第三次作业

 

本次作业允许了函数嵌套函数,三角函数嵌套函数。

(1)基于度量来分析自己的程序结构

  由于第三次作业新增的功能在第二次作业时已经实现,因此相关的复杂度分析和类图同作业二。

(2)分析自己程序的bug

  本次作用中互测时被别人hack了,原因在于三角函数里的因子判断函数没有写好,导致输出表达式的时候没有添加括号。实际上当时因为忙OS忘记提交最新版本,不过最新版本也没有注意到这一bug。。。

(3)分析自己发现别人程序bug所采用的策略

  这一期似乎大家嵌套函数的功能都做的挺好,主要问题还是三角函数加入括号的问题。将不同种类的表达式放入三角函数中观察输出即可。

 

经历总结

  布置第一次作业时的印象比较深刻,当时面对题目完全没有入手思路,在一时之间产生了自己不适合学习计算机科学的想法。

  所幸前辈们助力,在向学长求助时,学长告诉我如果不想要重构的话需要学习递归下降法,并且也对更多的架构细节进行指导,其中最重要的就是让我对于数据结构有了初步印象。不过助教们在几天后就给出了train的练习,其中恰好就有使用递归下降法,给我提供了本次作业的基本框架。

  虽然看起来train只是给了递归下降的实现思路,但价值是巨大的。首先递归下降是关键,也是难点,另外也启发了我首先将输入转换成后序表达,然后再进行计算。于是第一次作业就是不断往train的框架中填充功能,实现减法,次方的解析,添加各种类型的运算,以及++-和--+等一系列问题的处理。

  第二次作业中添加的三角和函数运算在当时看来似乎也不可能完成,所幸首次作业的框架很好,在进行分析之后不久就找到了新类添加的位置。而添加新类时也在思考着后期的扩展工作,这使得第二次作业已经完成了三次作业的要求。

  二次作业中的主要问题在于加入三角后的数据管理,相关的运算,还有就是很麻烦的化简问题。另外针对函数也构造了类,不过稍微简单一些。

  第三次作业是第一次被hack,当时过于骄傲了,没有认真检查三角函数的因子判断功能。

 

心得体会

  一开始架构相当重要,本次作业因为初始条件好避开了重构的命运,而且在第三次时也基本直接使用了二次的代码。

  IDEA确实很好,一开始我接触的是eclipse,当时还觉得eclipse用起来很顺手,然而IDEA的补全功能实在太棒了。

  作业并不只是一个人完成的,这期间有通过和同学一起探讨实现中的问题,有向学长和助教请教,老师的课堂内容也很重要。

posted @ 2022-03-25 15:49  早点明安  阅读(61)  评论(1编辑  收藏  举报