• 北航2020年OO第一单元总结


    题外话

    ​ 素闻 6 系 OO 费心劳神,极为恐怖,但程设未到平均分的本菜鸡无知无畏,我在寒假的时候试图通过直接阅读指导书来步入 OO 殿堂,于是就有了下面这一幕:

    ​ OK,认清现实,从零开始,针对 pre 中的需求,在网上找一些资料踏踏实实地来学习。经过几天的“自我扫盲”,起码算是入了门,知道了类和对象大概是怎么一回事,也初步了解了正则表达式和一些简单容器的使用,顺利通过了 pre。

    闲话结束,下面进入正题。

    1. 第一次作业

    1.1 思路分析

    第一次作业相对友好,仅仅需要针对幂函数这一种主体因子完成求导。本人的思路如下:

    • 由于第一次作业没有 wf 判断,先无脑去空白字符;
    • 根据幂函数特性编写相应的正则表达式,并调用Matcher类的find方法来分割字符串;
    • 分析字符串结构,完成幂函数的构造;
    • 简单求导;
    • 将指数和系数作为键值对来合并同类项,去除多余符号,同时提取系数最大项至最前,完成化简。

    1.2 结构分析

    UML 图如下:

    由于本人仍旧保留着严重的面向过程思想,只是新建了一个 Term 类,类中仅有一个上述的构造函数以及指数、系数属性,其余绝大多数工作,包括字符串的预处理,求导,乃至化简都是在主函数中完成,缺少 OO 思想和层次感,“一 main 到底”不忍直视;
    复杂度分析如下:



    可以看到,虽说实现的功能较为简单,但不善于利用模块化、结构化思想依然会使程序复杂度飙高。

    1.3 Bug 分析

    • 由于代码量相对较少,整体结构并不复杂,第一次作业我并未搭建评测机,而是手工构建出一些极端数据,修复了一些手抖产生的 bug,并且并未在强测和互测中被hack;
    • 人工检测 7 个人的代码,多少有点费力,好在最后还算有收获,发现某位兄弟遗漏了化简后应当输出零的情况,他的程序并未输出。

    1.4 感想与收获

    • 新手上路,还是习惯在舒适区里写大块代码,为日后的重构埋下隐患;
    • 对正则表达式加深了理解,用起来更加灵活;
    • 学会在实践中学习,写代码 →发现需求 → 查阅资料 → 使用容器、调用函数等解决问题 → 继续写代码;
    • 惊叹于别人优秀的代码,学到了很多,其中我第二次作业还借鉴了某位 roommate 在第一次作业中整体结构。

    2. 第二次作业

    2.1 思路分析

    第二次作业难度提升不少,又是 wf 又是三角函数又是乘积的,乍一看无从下手。一番仔细思考之后,有了自己的思路:

    • 先依据指导书中的形式化定义一步步写出正则表达式,并且封装在一个枚举类中,随用随调;
    • 去空白字符后,先整体判断是否合法;
    • 创建以x的系数,sin的系数,cos的系数这一三元组为键的HashMap,和第一次一样按项读入,不过提前合并;
    • 根据乘法求导法则完成求导;
    • 优化,将x**x化为x*x,a*sin**2+b*cos**2化为(a-b)*sin**2+b,cos**(i-2)*sin**jcos**i*sin**(j-2)合并。

    2.2 结构分析

    UML 图如下:

    第二次作业,逐渐有了面向对象的思想,针对幂函数、sin 函数、cos 函数分别构建类,并在类中实现求导方法,再往上是之前提到的三元组类 KeySet (名字取得不太好)以及项的类(叫 ThreeTerm 还是感觉有点奇怪),然后是多项式 poly 类,最后是实现化简的两个类,main 中仅仅完成一些事前和事后输出工作,结构还算清晰;
    复杂度分析如下:



    我得承认,在处理三元组以及最后化简时,我为了图省事把很多操作塞到一个方法里,导致相应数据飘红,不过整体来看,结合代码行数考量,和第一次相比在结构化方面有所进步。

    2.3 bug 分析

    • 第一次研讨课的时候,听着大佬们分享各式各样的评测机写法,我听得云里雾里,深感惭愧,因为我对此可以说是一窍不通,学 Python 嚷嚷了几万次,每次都无果而终。终于,纯手工造数据已无法满足自测的需求(尤其是我还优化了),现实逼迫我再怎么着也得弄出一个评测机来。于是,我完全仿照讨论区中 qsy 大佬的思路,结合我少得可怜的 Python & Linux 知识,不懂就百度,花了一整天时间写出了一个评测机。效果还是有的,找到了我两个直接向map中插入键值对导致原值被覆盖的问题。但悲哀的是,我忽视了“二八原则”,在FewPolish中,另有一处同样的 bug 需要很巧合的数据才能发现(还是评测机太弱了),强测无事,互测直接 GG。(见下图,仅截取部分,原代码中未加 if 判断语句)
    • 这一次的互测我先大体扫了一遍代码,然后直接丢进评测机。虽说找到了别人三个符号连一起就输出混乱的错误,但是稍显遗憾的是,一位老兄指数等于 10000 时报错,另一位老兄前导零过多时出错,评测机无法得到对应数据,而我自己针对性地构造是有可能 hack 成功的。

    2.4 感想与收获

    • 代码架构真的很重要!由于第一次作业毫无扩展性可言,我第二次作业只能完完全全地重构,好在这一次作业面向对象的思想也有所体现,自底向上一步步完成编写,为第三次作业也贡献了不少代码;
    • 辩证地看待代码优化和评测机。本人写评测机花了一整天,代码优化又花了一整天,结果性能分几乎没涨,还引进一个评测机没发现的 bug(归根结底菜是原罪,写的评测机过于简陋以致无法产生特定数据,优化也仅仅停留在表面,没法像那些大佬一样递归优化到极致)。但这两天收获颇丰,逼着自己跳出舒适区学一点不熟悉的东西,bug 的产生让我对 Java 的特性又有了新的理解。
    • 面向过程的痕迹依然存在,但罗马不是一天建成的,一步一个脚印地领悟 OO 精髓;

    3. 第三次作业

    3.1 思路分析

    压轴好戏名不虚传,嵌套求导差点把我吓傻,曾经一度觉得自己没法在 ddl 前理清思路。讨论区看了个遍,什么有限状态机,递归下降直接劝退(还是菜啊),百度搜了个遍,大脑依然空空如也,没办法,回来钻研指导书,发现文末有一些微妙的提醒,遂慢慢有了想法:

    • 先针对其他字符的 wf,空白字符位置的 wf 进行判断,而后去空白字符;
    • 为完成嵌套,将多项式看成因子,按照 polytermfactor 递归解析,直至遇到仅由幂函数或者常数构成的项(我在这里将三角函数看做上述的嵌套);
    • 采用工厂模式,根据传入的字符串特征进行解析;
    • 逐层求导,将返回值以字符串形式返回至上一层;
    • 去零项,简单化简。

    3.2 结构分析

    UML 图如下:

    本课程所需的设计思想逐渐有所体现,每一种函数、项以及多项式的类中完成各自特定方法,另有工厂类、异常类、求导法则类各司其职,“高内聚,低耦合”初见端倪;
    复杂度分析如下:


    好嘛,红数据又辣么多。回看代码发现,由于上下层间过于紧密,导致模块的耦合度偏高,模块设计复杂度等指标自然会飙升。这也启发我在日后写代码时要更加注意层次间关系的梳理,模块间的调用尽量清晰简洁,避免无谓的 debug。

    3.3 bug 分析

    • 由于第三次作业理出思路加上写代码确实占了太多时间,再加上我并未做过多化简以及这次的评测机确实不好写,我参考了一位学长的博客,简单进行了评测。还是同样的问题,出的 bug 是评测机兼顾不到的,强测中(- 1)的 wf 没有特判出现 bug;ddl 前的一个小时看到群里在讨论 tle 的事,自己试了试发现果然中招,慌忙捕虫但却回天乏术。不出所料,互测中招,tostring 方法递归过深导致超时,以及去零的化简出现漏洞导致类似 sin(1)+x 这样的求导直接变成 cos(1)+1,互测中被 hack 了 13 下,甚至有个哥们交了很多次类似的卡我递归的数据,有点不爽;
    • 吸取了上次的教训,我这次采用手工为主,评测为辅的方法进行找 bug。可别人也吸取教训了呀,边界条件出错一个没有,化简出错一个没有,递归过深还是一个没有(倒是自己玩砸了),遂无奈,将目光放在代码上,发现一化简极佳的兄弟处理 (sin(x)+sin(x))sin(1) 这样的数据时会出现 cos(x)+cos(x))sin(1 的括号匹配的错误,另找出一位兄弟一处低级错误,不需多说。

    3.4 感想与收获

    • 设计模式真香!继 pre 工厂模式小试牛刀后,这一次正儿八经地用工厂模式来处理数据,对多态这一特点理解更深了,但学无止境,有用的创建模式、设计模式还需花时间钻研;
    • 折服于别人化整为零的框架结构以及精妙的化简技巧,潜移默化中能力有所提升;
    • 类中的方法从臃肿变得更加精简,结构层次逐渐清晰;
    • 以自己的惨痛经历对程序鲁棒性有了不一样的体会。

    4. 总结与展望

    第一单元悄然结束,整体来看,虽完成得不算多好,但还算差强人意。更重要的是,感谢老师和助教的细心引导,让我就此打开了面向对象的大门,门内五彩缤纷的世界还需要我静下心来欣赏。希望第二单元从一开始就要把模块化、可扩展的思想落到实处,可别再像第一单元那样让重构成为常态了;希望日后的代码之路能越来越顺畅,学到真正实用的知识,让“码力”内化成自身重要的竞争力。
    而从本课程或许又能看到人性百态。讨论区内友好相助,ddl 前疯狂至近乎绝望,互测屋里“勾心斗角”,“内卷大系”所有人为了一两分的斤斤计较,可谓淋漓尽致。
    以上一段纯属胡诌,第一次写博客,如有不当之处,还望拨冗指正。

  • 相关阅读:
    Node.js+express 4.x 入门笔记
    排序系列 之 堆排序算法 —— Java实现
    排序系列 之 归并排序算法 —— Java实现
    javascript必须知道的知识要点(二)
    XGBoost安装
    ubuntu16.04查看哪些软件可更新
    禁止ubuntu更新内核
    ubuntu安装nvidia显卡驱动问题
    禁用ubuntu16.04的guest账户
    远程登录jupyter notebook
  • 原文地址:https://www.cnblogs.com/bjhkhtdx/p/12521508.html
Copyright © 2020-2023  润新知