OO第一单元总结

OO第一单元总结


作者:Appleuiy 一只greenbird

前言

  • 如果有幸,这篇博客在未来被某个学弟学妹看到了,并且你想要学习借鉴我的学习经验,建议你先快速浏览整篇博客,因为我的架构虽然我通过了前两次作业,但不能否认它是一个失败的架构,你可以参考一下,避免自己出现相同问题

转眼间4个周过去了,OO第一个单元也迎来了结束。先说一下结果吧:三次作业提交,前两次都非常顺利,被hack次数为0,第三次没有通过中测(留下了悔恨的泪水)。

从第一周java语言0基础到现在能够较为熟练的使用java编写程序,不得不说,这高强度的3个星期,给我带来了非常巨大的收获。


单元任务概述

第一单元的作业主要围绕着多项式,包括多项式的展开、化简、函数替换、求导等。

通过一步步的迭代,使得学生能够在期间慢慢理解到底什么是面向对象,同时在一次次难度的提高中,也让学生渐渐明白,一个良好的架构对一项需要不断迭代的工程有多么重要


具体实现

题目

  • 这是第一次作业的描述,第二、三次会有新增的要求

给定带有括号、指数、参数有xyz的多项式,要求将其展开,并尽量化简,最后输出的等价式子越短,性能分越高

KaTeX parse error: Expected & or \\ or \cr or \end at position 106: …5929f3732a6.png#̲pic_center) ![在…

递归下降

展开、合并化简等多多项式的操作,离不开解析多项式,对于第一次作业,可以取巧使用正则表达式,但是正解还得是我们的递归下降

递归下降在我理解是一个文法分析算法,他能处理一些有层次、文法的语言,这里的递归、下降针对的其实就是文法定义中的递归定义。第一次作业文法如下,细细品味一下不难发现其中的**“递归、下降”**

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-L4hET9EO-1679193567799)(C:\Users\ZP and ZNQ\AppData\Roaming\Typora\typora-user-images\image-20230316212325193.png)]

基本架构

  • 后面的迭代都是在最初的架构上进行,所以最初的架构非常重要,但是在初次架构上,我并没有用长远的目光去给未来的迭代留下过多的可能,为我后面的失败埋下了伏笔。

第一次题目题意描述上非常简单,对于化简后的多项式,我们稍加分析,就能得到基本项(我将其命名为Basic,并将其创建为Basic类)的表现形式,如下:
B a s i c = t ∗ x a ∗ y b ∗ z c \huge Basic = t*x^a*y^b*z^c Basic=txaybzc
各个因子都能
解析成为一个Basic类
,而最终表达式化简的结果一定是这样的:
E x p r = B a s i c 1 + B a s i c 2 + B a s i c 3 + . . . + B a s i c n \huge Expr = Basic_1 + Basic_2 + Basic_3+ ...+Basic_n Expr=Basic1+Basic2+Basic3+...+Basicn
Basic这个类是我架构的核心,理解它基本上就理解了我的架构。详细的架构思路我会在在每次作业中具体描述

第一次作业

架构
  • 有了Basic类的支持,第一次作业就变得简单了

下图就是我第一次作业的架构,因为每个因子都能表示成为一个Basic或者Basics,所以我们使用以下具体架构。

  • Factor、Term、Expr中的结果最终都是若干个Basic,所以每个类中保存一个Basic类的列表
  • 合并展开的时候,针对的是每个类中的Basic类的列表,用这个来合并展开化简,那么就不必要过多的在意所谓的层次结构(事实上这是不对的)
Expr
Term
Factor
ExprFac
Basic,Basics
Number
Var
Expr
Basic,Basics
Term
Factor
ExprFac
Number
Var

第一次作业类图

在这里插入图片描述

第一次作业课后感想
  • 第一次作业不该过于在意自己做对与否(当然,能做出来尽量做出来),或者说我们的目标并非在我们成功过了中测、强测那一刻就结束了,我们要学习的是面向对象这种抽象的思想(时至今日,第一单元结束,我认为自己才堪堪入门,了解其中九牛一毛),这将更有利于后面作业的分析与架构,也更能达到提升自我素养的目的
  • 当我真正体会到所谓面向对象的时候,我不禁感叹这真是一个伟大的语言

第一次作业对我来说压迫力最大的。

因为我没有学习过先导课,并且暑假没有预习,以至于开学第一周过多而难的作业砸下来让我直接目瞪狗呆。 好在,巨大的压力给我带来了巨大的动力,不得不说,不同于过去一年多大学的摆烂生活,开学第一周是我大学生活以来最为充实的一周

当时还什么都不懂,编写代码的逻辑全依赖于以前的算法竞赛的基础,并没有领略到面向对象编程OOP的真正含义,更多的,我是在面向过程编程,也就是没有转化到正确的编程角度。 从这方面来看的话,虽然第一次作业我拿到了一个不错的分数(一度让我沾沾自喜),但是我却是失败的,因为没有学到课程组想让我真正明白的东西——面向对象的思想、抽象的概念、层次架构的意义等等


第二次作业

  • 从第一次到第二次作业,这之间是一座大山,架构层面上的问题初显
要求增添

第二次作业在第一次作业的基础上,增加了如下要求:

  • 允许出现新因子 sin(factor) cos(factor)
  • 定义了函数,在化简合并的过程中要替换题目中的函数、函数最多不超过3个,函数中参数也是最多3个

输入例子如下 : 1 f ( x ) = s i n ( x ) + 1 需要化简的表达式如下: f ( x ) ∗ ∗ 2 则最简答案如下: s i n ( x ) ∗ ∗ 2 + 2 ∗ s i n ( x ) + 1 \huge \begin{align} \huge &输入例子如下:\\ \huge &1 \\ \huge &f(x)=sin(x)+1\\ \huge &需要化简的表达式如下:\\ \huge &f(x)**2\\ \huge &则最简答案如下:\\ \huge &sin(x)**2+2*sin(x)+1 \end{align} 输入例子如下:1f(x)=sin(x)+1需要化简的表达式如下:f(x)2则最简答案如下:sin(x)2+2sin(x)+1

解决方案

函数与新因子的引进给我们带来了许多的麻烦

函数参数的替换

首先,函数上我们必须明确函数名以及对应的每个参数是什么。

为了解决这个问题,我是用了HashMap<>

HashMap1
fucName
fucPara
HashMap2
fucExpr

上图的含义如下:

  • 我是用了两个HashMap<String,String>
  • 第一个使用函数名字符串映射函数的参数字符串
  • 第二个使用函数名字符串映射函数的表达式字符串

H a s h M a p 1 < f > = X Y Z H a s h M a p 2 < f > = ( X + 1 ) ∗ ∗ 2 \huge \begin{align} HashMap1<f> &= XYZ\\ HashMap2<f> &= (X+1)**2 \end{align} HashMap1<f>HashMap2<f>=XYZ=(X+1)2

注意:为了避免替换的时候出现问题,我们应该将形参xyz,替换为别的字符,我的选择是将其替换为大写,即XYZ

通过上述方法,我们很容易的可以将表达式内的函数变成一个没有函数的表达式, 到了这里,我们要做的就回到了第一次作业了,只需要将表达式解析一遍,然后返回解析后的Basic类的列表或集合即可

三角函数因子的处理

三角函数的引入其实并没有影响我们的架构,它只是让我们需要对Basic类做出调整。
B a s i c = t ∗ x a ∗ y b ∗ z c ∗ H a s h S e t < T r i F u c > \huge Basic = t*x^a*y^b*z^c*HashSet<TriFuc> Basic=txaybzcHashSet<TriFuc>
做到这里,架构层面上的问题就出现了,三角函数的增加没有影响我的正确性 ,事实上添加一个类甚至没有在我主要的架构上进行过多的操作,但是其最致命的问题在于:

  • 三角函数的引入让我的合并同类项变得非常困难
  • 知识浅薄的我无法准确的实现不同Basic之间的合并,因为我很难确认两个Basic是否是等价的
无法合并的结果

三角函数的结果让我无法合并,最后的问题非常明显,就是我不再能够拿到任何一点性能分

我和一个架构好的佬对比了一下一个相同输入:

  • 他的输出长度: 9000+
  • 我的输出长度: 100,0000+
第二次作业类图

在这里插入图片描述

第二次课后感想

就正确性而言,这次作业我依然0被hack过了。这之后我就开始了摆烂,感觉过了,问题就解决了,没有丝毫优化的劲头,更多的可能是不知道如何优化

但是架构上的缺陷与漏斗让我不得不失去性能分。也就是这一次作业,我开始意识到一个好的架构的重要性。为我下一次重构埋下伏笔

第三次作业

  • 最初的架构在这一次作业中被彻底击碎(其实按照我现在来看,还是能缝缝补补,但是当时的我实在没有什么可以解决问题的方法)
要求增添
  • 此次作业允许了求导因子的出现,但是只能出现一次
  • 函数表达式中可以出现求导因子,同时也能出现其他已经定义的函数

举例输入如下 : 3 f ( x ) = x g ( x , y ) = x + y h ( x , y ) = d x ( f ( x ) + g ( x , y ) ) 需要化简的表达式: f ( x ) + g ( x ) + h ( x ) 最终的答案: 2 ∗ x + y + 2 \huge \begin{align} &举例输入如下:\\ &3\\ &f(x) = x\\ &g(x,y)=x+y\\ &h(x,y)=dx(f(x)+g(x,y))\\ &需要化简的表达式:\\ &f(x)+g(x)+h(x)\\ &最终的答案:\\ &2*x+y+2 \end{align} 举例输入如下:3f(x)=xg(x,y)=x+yh(x,y)=dx(f(x)+g(x,y))需要化简的表达式:f(x)+g(x)+h(x)最终的答案:2x+y+2

结构不适用
函数问题

函数问题还比较好解决,因为是使用的递归下降来分析文法,所以对这些函数的嵌套、递归等,都是非常自然而然能够完成的。

求导问题

按理说,求导不应该是一个过分苦难的操作,因为数据显示第三次作业,学生整体的通过情况是最好的。

但是,对于我的架构而言,这就是致命打击,以我当时的水平,我实在是无法想到有什么好的解决办法能够让我的架构支持求导

上机代码对我的影响

只有第三周的上机课,我看到了助教给的训练代码。当时正愁架构的我大为震惊。

”优雅!实在是!太优雅了!“ 这就是当时我的真实写照。 逻辑清晰、层次分明、结构明了,同时代码中使用了许多我之前不曾使用过的java语言的特性,这份代码对我来说,真的就是天外飞仙,天上馅饼,于是乎,我毅然决然的重构了。

  • 重构!重构!还是xx的重构!
重构方案

按照训练代码的架构,如果不考虑合并化简,那么其实,第三次作业就很简单的能够迎刃而解了。这样的认识导致我第三次作业的时候不再有紧迫感,一点都不急着去实际操作。

函数处理

函数处理沿用第二次作业的处理方案,不需要修改。

合并化简

其实训练代码唯一的问题在于合并化简,如何能构造出一种优雅的化简策略,是我此次重构的重要目标。

于是拿着训练的架构,结合我自己的想法,我苦思冥想了一段时间。(真的只是再想,一点没动手),我确信自己找到了一个合适的解决方案,能够成功解决化简问题(说实话并不优美,但是无伤大雅)。

  • 当我开始实现这个化简合并的时候已经是周日了,也就是提交的最后一天,当时的我迷之自信,相信自己能够在晚上8点前de完所有bug然后成功上交。、
  • 在这之前,助教还来提醒过我让我早点提交。
  • 这痛苦的重构过程我就不再赘述了,结果就是我没有交上最后一次作业
第三次修改完后的类图

在这里插入图片描述

第三次课后感想
  • 当中测开放结束的那一刹那,我后悔了,但我后悔的不是选择了重构,而是我明明可以做到,但因为自己的懒惰,又一次失败了

这之后的第二天,我成功de出了之前的bug,但是为时已晚。

回想起来,我并不后悔选择了重构,因为在这次重构中,我真的学到了很多东西。

最初的架构因为相关知识学习没有到位,有着种种缺陷和漏洞,即使后面随着知识的增加,意识到了相关的问题,但是实在是无能为力,对最初的代码无从下手。 自然而然,这过程中学到的东西,也没办法应用到代码中去。

但是这次重构,我把先前想用而未用的到接口、继承、深克隆、重写equals方法等种种学到的知识都应用到了代码中去,相较于第一次架构,这实在是一次赏心悦目的重构,即便它以失败收场

总结

关于重构

虽然我重构失败了,但是我仍然建议意识到自己架构有问题的同学进行重构,重构的过程真的能学到很多东西。

与其缝缝补补,写一堆让自己看着都难受的东西,尝试一下推倒重来,建一栋优雅舒适的大厦,你会感受到不一样的情绪。

结束语

总而言之,言而总之,第一单元最后一次未交上很遗憾。

但是,就像我开头说的,第一单元的要点,想让你学到的并非不择手段的去做完这三次作业

我们更应该紧扣课程名称面向对象,在这个过程中:

  • 真正地去领会面向对象的思想
  • 明白什么样的抽象适合于我们的解决方案
  • 同时如何得到良好的、清晰的、易扩展的架构

我觉得从同学那听来的这句话很有道理:

然建议意识到自己架构有问题的同学进行重构,重构的过程真的能学到很多东西。

与其缝缝补补,写一堆让自己看着都难受的东西,尝试一下推倒重来,建一栋优雅舒适的大厦,你会感受到不一样的情绪。

结束语

总而言之,言而总之,第一单元最后一次未交上很遗憾。

但是,就像我开头说的,第一单元的要点,想让你学到的并非不择手段的去做完这三次作业

我们更应该紧扣课程名称面向对象,在这个过程中:

  • 真正地去领会面向对象的思想
  • 明白什么样的抽象适合于我们的解决方案
  • 同时如何得到良好的、清晰的、易扩展的架构

我觉得从同学那听来的这句话很有道理:

  • ”其实这一路重构下来的同学,可能远比我们这些修修补补写下来的同学学到的东西多“
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值