BUAA-OO第一单元总结

一、程序结构分析与总结

  • UML图

架构

第一单元的任务是表达式展开,可以总体分为两个部分,其一是表达式的文法解析,其二是计算与化简。我采用的是递归下降法 + Poly架构,前者负责将表达式拆分出若干词法,后者负责计算与化简。类之间的关系如UML图所示,此处不再赘述。

其中值得一提的是,Mono(单项式)的结构可以形象化表达为该数学表达式:

$$ (C * x^ay^bz^c*\prod_isin(Poly_i)*\prod_icos(Poly_i)) $$

这样一种经过变形的单项式可以满足本单元作业的任何需求,该设计我认为还是非常简洁且强大的。

优点 :结构较为清晰,层次分明,并设立了若干工具类,有效的降低了类的内聚程度,避免了类过于庞大冗长的现象发生。可迭代性强,本单元作业无需重构。

缺点 :工具类的代码量过于庞大,复杂度高,在下文将详细说明。

  • 工程复杂度分析

可以看到,复杂度较高的类有DerivativesAnalyzer类、Exprprocesssor类、FuncAnalyzer类、Merge类和Parser类,都是一些工具类,这也警醒着我今后的设计中注意工具类的复杂度不要太高。工具类的设置本来正是面向对象思想的体现,但是若把工具类写的太冗长则反而不符合面向对象的基本思想。

  • 类复杂度分析

鉴于本次工程我设置的类的数量非常多,逐一分析显然不现实,于是这里只分析一些关键的类。

  • Mono类(单项式)

Mono类中最复杂的莫过于toString()方法,其余两个较为复杂的分别为sinToString()和cosToString(),是由于toString太过冗长而不得不分出去的方法,所以总的来说我在将Mono类型转化为String的方法写的不是很好。经过反思,主要是因为我在toString()方法里用了大量的if-else结构,我是对Mono的属性逐一判断以后,再决定转化为什么字符串,所以就非常地笨拙。可以改进的方法为:将常数和幂函数再单独抽象为分别的方法。

  • Poly类(多项式)

Poly类最复杂的方法是mulPoly()方法,其中的CogC达到了惊人的38。其中的原因主要就是第二次作业加入了三角函数,并且我对其的处理不是很聪明。在第一次作业中,本来这个方法还较为简单,只需要把两个Poly相乘,x y z的指数分别相加即可。但引入了三角函数因子后,这个方法的复杂度就陡然上升。我是用HashMap<Poly, Integer>储存的三角函数,两个Poly相乘就是要把两个Poly的三角函数部分都装填到一个新Poly的三角函数的HashMap中。但由于HashMap的特性,如果两个三角函数相等,那第二次装填就不能成功。此时需要我们用双重for循环遍历,若两个三角函数的Poly部分相同,则将<Poly, Index1 + Index2>这个键值对存入新Poly的三角函数HashMap,这样这个函数就有了三层for循环,复杂度也自然就高了上去,应该降低这个方法的耦合程度。

  • 架构设计体验

如前文的UML图所示:

  • 白色部分:Hw1

  • 绿色部分:Hw2

  • 红色部分:Hw3

可以看到,我在第一次作业就已经确定了整个单元的基本架构,之后的几次作业便只是扩展了因子种类和响应的工具类而已,所以我在架构设计上并未遇到什么太大的阻碍,架构设计体验良好,花费时间比较多的是一些表达式的性能优化。

  • 总结

总体来讲,我认为自己在总的架构方面设计的还算不错,具有较高的可迭代性与较低的内聚程度;但是在个别类里面的方法还有提高的空间,比如降低方法的复杂度与内聚程度,在个别功能的实现方式上也有一些优化的空间。

二、BUG分析

  • 自己的Bug

  • 公测Bug

我在Hw1与Hw3中公测均未出现bug,但在Hw2中折戟沉沙、损失惨重,其中有12个强测点未过,直接导致我失去了进入互测的机会。冷静下来分析后发现,其中十个测试点都是由于我在自定义函数预解析时出现了问题,我在预解析后忘记处理符号,就出现了连续的正负号,导致我接下来在分析函数定义式时无法解析;还有两个是由于我在优化性能时出了bug。

修改的代码如上图所示,短短两行代码直接影响了十个强测点,每每想到不免一声叹息。

  • 互测Bug

我在Hw1和Hw3都进入了互测,也都被房友们hack出了Bug,下面将分别剖析两次作业遇到的Bug。

Hw1的Bug是由于我在遇到开头是符号的表达式是我在前面多加一个“0”,以保证输入的首项永远为正;在整个流程走完之后,我为了优化性能,边将第一个“0”删去。此时缺乏对于输出字符串长度的判断,若长度等于1,即输出只有一个“0”,表达式便为空了,因此我被诸如0*0这样的数据hack了两刀。这显然是由于我对于边界条件的考虑不够所导致。

Hw3的Bug是由于我在预解析自定义函数的定义式时,只字符串替换了空格,没替换tab,房友用带tab的数据就hack了我两刀。

  • 别人的Bug

我在这一单元hack别人次数不是很多,主要是通过用评测机跑别人代码的方式来hack,在Hw1时还可以hack到一些,但是到了Hw3大家的代码已经都用评测机调教得很完善了,便很难再找出Bug。

  • 总结

第一单元做下来Bug数目不算少,也为我后面的单元敲响了警钟,我主要的感悟有以下几个方面:

  • 慎用字符串处理,因为字面上的处理有很多情况是想象不到的,可控性低。

  • 不要迷信评测机,评测机主要是靠随机生成测试数据,很难随机出一些边界条件,一些边界条件还是需要靠自己手动生成。

  • 优化有风险,代码需谨慎,切忌过度优化,一定要保证在正确的基础上进行优化。

  • 多做测试!多做测试!多做测试!

三、心得体会

这一单元是面向对象的第一单元,也是极具面向对象特色的一个单元。虽然之前上过先导课,但还是有被第一单元震撼到。在之前上先导课时,我已经觉得代码量相当之大并且编写也较为吃力,但和正式的OO课程比起来还是小巫见大巫了,这一个月的OO之旅下来我也是感慨良多。

首先是一些知识层面的收获。相比于上学期的先导课,这学期我在OO作业上的编程明显更加符合面向对象的思想,类与类之间的内聚程度更低了,也有了设立工具类的意识,这样的进步离不开OO理论课的指导。还有,研讨课也能让我收获一些很有用的知识点。举个例子,在第一次研讨课上我在聆听同学们的实现方法时学到了TreeMap这种数据结构,这样就能有效地实现判断三角函数里面因子是否相等的问题。这些理论上的收获无疑是对我做作业有这么大的帮助的。

其次是一些做作业时的体会,也是为后面的几次作业敲响警钟。重中之重就是在测试方面千万不可掉以轻心,我在Hw2写评测机时由于抱着侥幸心理就没有加入自定义函数功能,导致在强测环节爆出大问题;在Hw3时的自定义函数定义式里忘记加入空白字符,导致在互测时不幸中刀。这几处其实都是由于我对于测试的重视程度不够,写评测机时一定要仔细按照指导书中的题面好好模拟,切不可漏掉某项,否则也许就会酿成大错。还有就是写作业的时候也要集中精神,有些明明是相似功能的代码,结果一处有bug一处没bug,这便是由于集中程度不够所导致。此外,我还深切的体会到了构思的重要性,我在第一次作业动笔前构思良久,在架构的思考上花了很大功夫,确实起到了事半功倍的效果,后面我都没有再动过整体的架构,每次迭代也较为轻松,尤其是第三次作业,顺水推舟一般很顺利得就完成了。

最后还想说说我在做第一单元作业时的一些心境上的感悟。记得当时在Hw2开放互测的时候,我满怀期待的打开互测页面想拿出已经准备好的数据hack别人,结果却发现自己没进互测,那一刻无疑如同一道晴天霹雳。有了这次的惨痛教训,我也有了一些感悟。感悟最深的就是在做作业时首先应该保证正确性第一,在第一单元的评分标准中,优化和正确性本就是一场博弈,优化的难度高、收获也相对低,但是那二十分属实诱人,很难忍住止步于80分,于是就开始铤而走险地在优化道路上越走越深,结果却连基础的80分都丢了。所以说要懂得“舍得”,不只是OO,很多事情也亦如此,有舍才有得,切忌因小失大,为了捡芝麻而丢了西瓜。

为期一个月的OO第一单元结束了,但愿我在后面的单元再写博客时不要再重蹈此篇博客里记录下的bug,希望我的OO之旅可以更加顺利。

BUAA-OO 第一单元总结相关推荐

  1. OO第一单元作业总结

    OO第一单元作业总结 第一次作业 结构 OO第一次作业是简单的多项式求导,在这次多项式求导中,仅包含了幂函数和带符号整数的一些简单求导运算.在经过自己的一些简单分析后,我认为第一次作业最重要的部分是判 ...

  2. OO第一单元总结博客

    OO第一单元作业总结 本单元的三次作业内容为多项式求导.第一次作业中,表达式支持因子形式为带符号整数,以x为底数的幂函数.第二次作业中,表达式因子形式在第一次作业的基础上,支持标准三角函数(sin(x ...

  3. oo第一单元总结~~

    OO第一单元总结~~ 经历了三次oo作业的洗礼,我感觉我的IDEA已经是一个成熟的IDE了,应该学会-(划掉).总之学习面向对象编程是一个思路慢慢转变的过程,最开始的时候我觉得其本质就是封装,类的函数 ...

  4. BUAA OO第二单元作业总结

    一.作业设计策略 (一)第一次作业设计方案 模型:生产者消费者模型 两个线程:输入线程(生产者).电梯线程(消费者) 共享对象:请求队列 退出模式:输入线程读到null,退出run,并将null传入请 ...

  5. BUAA OO 第二单元总结

    OO 第二单元总结 本文为OO 第二单元电梯作业总结,本单元主要是掌握多线程和线程安全.三次作业总的架构类似,可分为输入线程.调度线程.电梯线程.三次作业的增量迭代如下 第五次作业 六部电梯 第六次作 ...

  6. 不学无术的下场——OO第一单元总结

    第一单元OO作业总结 第一次作业 ​ 第一次作业的要求是对仅有常数和幂函数的式子进行求导. ​ 由于是第一次接触JAVA,对很多东西都还不熟悉,尤其是正则表达式做得不好.当时我的思路如下: 建立Pol ...

  7. BUAA OO 第二单元 电梯

    前言 第二单元的主要任务是模拟电梯,主要涉及调度.电梯内部运行策略.换乘等,培养多线程编程的能力. 第一次作业 第一次作业的要求较为简单,模拟6部电梯的运作以及调度即可. 分析 笔者参考了上机所给的代 ...

  8. 面向对象OO第一单元三次作业总结

    (一)第一单元的作业围绕着多项式的求导,从简单到复杂,主要的要求是 作业一:只有两种格式的因子:带符号整数(+02)和幂函数(x^+02). 作业二:在作业一的基础上添加了:sin(x)和cos(x) ...

  9. BUAA OO Unit1 单元总结

    面向对象第一单元总结 前言   本次面向对象程序设计与构造第一单元的三次作业,通过迭代开发实现了更多功能的表达式解析.通过这三次作业,我对递归下降.深克隆.接口等等有了更深刻的认识. 程序结构分析   ...

  10. OO第一单元总结__多项式求导问题

    作业一.含幂函数的简单多项式的求导 (1)基于度量的程序结构分析 1. 统计信息图: 2. 结构信息图: 3. 复杂度分析 基本复杂度(Essential Complexity (ev(G)).模块设 ...

最新文章

  1. premiere pr 把切开的视频合并起来
  2. 韩信走马分油(C语言)
  3. 【数据结构与算法】【算法思想】回溯算法
  4. Python中的各种if语句(if条件判断、if...else、if...elif...else、if...else嵌套)
  5. 2018 终了,是时候秀出我的 Git 进化日志了!
  6. Entity Framework(EF)数据查询
  7. java 释放锁,在Java中以原子方式释放多个锁
  8. 为什么这么多的学校都选择这款收费管理系统?
  9. Ubuntu安装显卡驱动详细步骤
  10. win11家庭版安装时如何跳过联网设置 windows11家庭版跳过联网设置的步骤方法
  11. [C]结构体数组初始化
  12. 策略和投资组合分析-收益分析、风险回报分析和回撤分析
  13. 在c语言中的变量分为三种类型,在C语言中的实型变量分为两种类型,它们是_______和__________ 答案:float double...
  14. FMS4.5限制连接数
  15. Android 自动旋转屏幕总结
  16. Python 学习4-集合、序列
  17. vivo Hi-Fi+QQ音乐 数字音乐市场的一剂良方
  18. JS逆向加解密——python 实现AES加解密
  19. debian时间同步_如何在Debian 10上设置时间同步
  20. 西红柿鸡蛋热面烹饪步骤

热门文章

  1. Matlab绘图总结1
  2. wx-wow微信小程序实现wow.js功能(微信小程序动效库)
  3. sqlzoo刷题——SUM and COUNT(聚合函数)
  4. 世上没有该结婚的年龄,只有该结婚的爱情。其实这个观点我很认同,世上不仅没有该结婚的年龄,也没有注定该一辈子单身的人。只有该结婚的爱情,和该主动的爱情
  5. fpga4fun.com/Music box
  6. 变频电风扇c语言编程,乐高EV3第二讲,电风扇,大型电机的应用
  7. Moravec,Forstner和Harris特征点提取opencv实现
  8. Java入门第82课——StringBuilder的append方法
  9. 3天过去了,这个直播间里发生了什么……
  10. 遥感影像分类、目标检测、语义分割、实例分割的异同