OO第一单元总结与反思

摘要

本单元作业分为三次

HW1:本次作业,需要完成的任务为简单多项式导函数的求解。

HW2:本次作业,需要完成的任务为包含简单幂函数和简单正余弦函数的导函数的求解。

HW3:本次作业,需要完成的任务为包含简单幂函数和简单正余弦函数的导函数及其组合的求解。

第一次作业

OO第一次作业来得比预想的要悄无声息,

带着脑中早已相好的思路当天晚上就完成了基本功能(没有WF属实很爽!)

由于只有多项式,根据a*x**b的基本形式,

很容易就可以想到用HashMap

以指数为key,系数为value存储每一项,

如此一来既能轻松求导又便于合并同类项。

关于输入,由于没有WF,因此直接处理成标准形式以便解析:

  • 首先,直接去掉空白符,排除干扰。

  • 其次,处理符号,使得项与项之间仅被+分隔,特别注意-的处理。

  • 然后,利用String对象的replace方法处理每一项为a*x**b的基本形式。

  • 最后利用正则表达式提取系数和指数便万事大吉。

本次作业性能分仅取决于输出的正确字符串的长度,因此必须关注以下几点

  • 合并同类项

  • 系数1不输出,-1*仅保留-号

  • 指数为1不输出

  • 0项直接跳过

  • 正项先输出(毕竟负项会在最开始多个负号)

(第一次作业性能分简直白给!)

本次作业UML类图

一main到底如今看来实在丑陋

本次作业度量分析

本次作业一共码了145行,完全没有脱离C语言程序设计的思路,

直接拿static方法当函数,洋洋洒洒100多行,敲得倒是舒爽

一点也不OO!!

Project Name Package Name Type Name Method Name LOC CC PC
OO_Unit1_work1 (default package) MainClass StrToMap 25 4 0
OO_Unit1_work1 (default package) MainClass getResult 18 4 1
OO_Unit1_work1 (default package) MainClass output 65 14 1
OO_Unit1_work1 (default package) MainClass inputHandle 22 4 0
OO_Unit1_work1 (default package) MainClass main 9 2 1

本次作业的复杂度均来源于output方法,此方法为了实现优化,

用了多重if-else,而且实现的功能繁多,也是bug出现的高频地段!

Class OCavg WMC
MainClass 5.6 28

简单粗暴,方法多复杂,整个项目就多复杂 -_- 一main到底真的没什么好说的

第二次作业

此次作业在上次作业的基础上增加了三角函数,由于上次作业采用的是a*x**b的架构,

因此此次考虑采用a*x**b*sin(x)**c*cos(x)**d并用单独一个item类储存四元组的架构,

本次作业的checkformat部分采用了部分正则+自动机的模式,

用各个因子的正则表达式一段一段逐步匹配表达式,

用于分隔的符号则用自动机来识别,

checkformat无误之后的操作与第一次作业相同。

本次作业的UML类图

本次作业的度量分析

本次作业一共码了440行,3个类以及25个方法。

Project Name Package Name Type Name Method Name LOC CC PC
HW2 com.lkl.oo Item Item 5 1 3
HW2 com.lkl.oo Item Item 6 1 4
HW2 com.lkl.oo Item setCnst 3 1 1
HW2 com.lkl.oo Item getCnst 3 1 0
HW2 com.lkl.oo Item getString 36 10 0
HW2 com.lkl.oo Item getDiff 20 5 2
HW2 com.lkl.oo Item equals 12 4 1
HW2 com.lkl.oo Item hashCode 3 1 0
HW2 com.lkl.oo Item caseAll 5 1 3
HW2 com.lkl.oo Item case1 18 4 2
HW2 com.lkl.oo Item case2 9 3 2
HW2 com.lkl.oo Item case3 9 3 2
HW2 com.lkl.oo Item simplify 5 1 2
HW2 com.lkl.oo Judge Judge 8 1 2
HW2 com.lkl.oo Judge exitWF 4 1 0
HW2 com.lkl.oo Judge nextStart 30 8 3
HW2 com.lkl.oo Judge func 9 2 2
HW2 com.lkl.oo Judge judge 32 9 0
HW2 com.lkl.oo Main StrToMap 38 8 0
HW2 com.lkl.oo Main merge 14 5 2
HW2 com.lkl.oo Main simple 17 5 1
HW2 com.lkl.oo Main getResult 13 3 1
HW2 com.lkl.oo Main output 57 13 1
HW2 com.lkl.oo Main inputHandle 29 3 0
HW2 com.lkl.oo Main main 25 2 1

可以看到,最复杂方法有两个,一个是item类的toString

还有一个是output方法(代码行数57),

这两个方法有一个共同点就是if-else结构很多,这也是出于优化考虑,

当然也确实没能在优化和架构之间达到完美的协调。

Class OCavg WMC
com.lkl.oo.Item 2.77 36
com.lkl.oo.Judge 4.2 21
com.lkl.oo.Main 5.57 39

本次作业依然做的不是很OO,虽然不像第一次作业那么极端(一main到底),

但说实话,我只是进行了刻意的封装,

即便这样,处理起来确实感受到了相比于第一次作业来说的一些便利。

另外,MainClass类承担太多功能的设计属实让我觉得不舒服了,不仅仅是美观的问题,

还总是给我一种面向过程编程的残念,过多的static方法真的不是个好习惯。

因此,我决定结合实验课、研讨课所学,在第三次作业上彻底OO一把。

第三次作业

此次作业在上次作业的基础上增加了表达式嵌套,由于上次作业采用的是:

a*x**b*sin(x)**c*cos(x)**d的用单独一个item类储存四元组的架构,

显然已经无法支持嵌套的递归解析了。故本次进行和预想的一样进行了大重构。

在开始作业之前其实就已经想好了本次的架构:

自顶向下分析,逐层解析表达式,根据加减、乘、复合求导规则构建起一棵表达式树。

如此,表达式树的叶节点将会是基本因子。

因此求导仅需实现各个求导规则以及基本因子的求导模式即可递归完成整个表达式的求导。

另外,本次作业的checkformat部分依旧采用了部分正则+自动机的模式,

仅需在遇到左括号时多一步递归操作即可。

本次作业的UML类图:

因为每种求导规则以及基本因子都具有求导功能,因此统一实现求导接口,创建表达式的工作就交由抽象工厂来完成。

本次作业的度量分析

本次作业一共码了672行,包括5个包,11个类和46个方法

Project Name Package Name Type Name Method Name LOC CC PC
OO_Unit1_work3 exception WrongFormatException WrongFormatException 2 1 0
OO_Unit1_work3 exception WrongFormatException WrongFormatException 3 1 1
OO_Unit1_work3 factory ExpFactory ExpFactory 4 1 2
OO_Unit1_work3 factory ExpFactory addSimplify 18 6 2
OO_Unit1_work3 factory ExpFactory Add 29 9 0
OO_Unit1_work3 factory ExpFactory Mult 39 12 0
OO_Unit1_work3 factory ExpFactory Compound 11 3 0
OO_Unit1_work3 factory ExpFactory findtype 9 3 2
OO_Unit1_work3 factory ExpFactory combine 10 2 2
OO_Unit1_work3 factory ExpFactory nextItem 10 2 2
OO_Unit1_work3 factory ExpFactory createExpr 56 10 1
OO_Unit1_work3 factory Factory Add 0 1 0
OO_Unit1_work3 factory Factory Mult 0 1 0
OO_Unit1_work3 factory Factory Compound 0 1 0
OO_Unit1_work3 inputhandler InputHandler checkbrace 11 2 1
OO_Unit1_work3 inputhandler InputHandler inputHandle 29 3 1
OO_Unit1_work3 inputhandler InputHandler braceMatching 17 5 3
OO_Unit1_work3 inputhandler Judge exitWF 3 1 0
OO_Unit1_work3 inputhandler Judge nextStart 36 10 4
OO_Unit1_work3 inputhandler Judge func 9 2 6
OO_Unit1_work3 inputhandler Judge braceCheck 18 4 1
OO_Unit1_work3 inputhandler Judge checkTheRoot 24 6 4
OO_Unit1_work3 inputhandler Judge checkIndex 6 2 1
OO_Unit1_work3 inputhandler Judge judge 57 14 1
OO_Unit1_work3 item Add Add 4 1 2
OO_Unit1_work3 item Add getDiff 3 1 0
OO_Unit1_work3 item Add toString 26 8 0
OO_Unit1_work3 item Compound Compound 4 1 2
OO_Unit1_work3 item Compound isConst 3 1 1
OO_Unit1_work3 item Compound isX 3 1 1
OO_Unit1_work3 item Compound getDiff 14 3 0
OO_Unit1_work3 item Compound toString 18 4 0
OO_Unit1_work3 item Expression getDiff 0 1 0
OO_Unit1_work3 item Factor zero 3 1 0
OO_Unit1_work3 item Factor one 3 1 0
OO_Unit1_work3 item Factor Factor 4 1 2
OO_Unit1_work3 item Factor getType 3 1 0
OO_Unit1_work3 item Factor getNum 3 1 0
OO_Unit1_work3 item Factor getDiff 42 11 0
OO_Unit1_work3 item Factor toString 38 11 0
OO_Unit1_work3 item Mutiply Mutiply 4 1 2
OO_Unit1_work3 item Mutiply getE2 3 1 0
OO_Unit1_work3 item Mutiply getE1 3 1 0
OO_Unit1_work3 item Mutiply getDiff 5 1 0
OO_Unit1_work3 item Mutiply toString 9 3 0
OO_Unit1_work3 (default package) MainClass main 21 2 1

从以上参数可以看出复杂的方法主要是toString(因为有许多if-else做浅优化)、

checkformat的judge(57行)和nextstart(一个方法功能过多/自动机if-else太多)以及

createExpr(56行,也是功能太多,一个方法创造所有类型因子以及最终整合成一个表达式)。

Class OCavg WMC
MainClass 2 2
exception.WrongFormatException 1 2
factory.ExpFactory 5.33 48
inputhandler.InputHandler 3.33 10
inputhandler.Judge 5.57 39
item.Add 3.33 10
item.Compound 2 10
item.Factor 4.14 29
item.Mutiply 1.4 7

上升到类的高度可以看出难度主要集中在表达式的输入解析处理,求导反而是较轻松的一部分。

本次作业疏忽了对于WF的检查,导致强测wa了一个点,互测未被hack。

说是疏忽了,其实还是因为judge方法写的太过于冗杂,导致一个很明显的错误未被发现。

这提醒我今后要分散功能,尽量避免长方法,另外在细节方面必须做足测试,切忌轻敌。

测试及bug杀虫

本次作业仅被第三次强测hack了一个点,总体还算满意

本次作业的测试方面主要是利用python的xeger库使用正则表达式生成数据

为了尽量做到可能性全覆盖,需要仔细研究指导书的形式化描述以构造正确的正则表达式

不足的一点是WF方面不是做的特别好,险些造成第二次作业无效,

也导致了第三次作业wa了一个点。

对于互测,我采取的策略是首先对屋内其他人的代码进行覆盖性测试,

此时或多或少能得到一些错误数据,但还不清楚对方bug在哪

此时转移到出错的代码上,不断削减出错数据的复杂度,同时做到此代码仍然复现bug

最终定位出错部分并进行调试,同时阅读代码,取其精华去其糟粕,

最后把此bug修复继续压力测试以期发现非同质bug。

我不是,我只是在友好的帮忙debug

心得与体会

可以看到,我在三次作业的迭代过程中,OO思想越来越深入代码,

第三次可以说是我最OO的一次了

通过这三次作业以及两次实验加一次研讨,我确实学习到了许多

git操作、工厂方法、行为抽象和数据抽象已经明确了其相应概念且能付诸实践

代码风格、设计理念也已经有了初步的认识,特别是高内聚低耦合的思想已经根深蒂固了

另外不得不提的是markdown语言的使用也不知不觉地精通了!!

唯一遗憾的是,出于多方面考虑懒、怕出bug,我在优化方面做的不是很好

都是做了浅优化,浅尝辄止,终归还是设计能力的不足,不敢保证自己的代码在多方面做到最好。

对比了优秀代码,我真是自愧不如,看来我该做的努力还是很多的,不仅仅是为了应付作业。

希望在下一单元不要留下什么遗憾,多学多看多问!重新做人

OO第一单元总结与反思的更多相关文章

  1. 【OO学习】OO第一单元作业总结

    OO第一单元作业总结 在第一单元作业中,我们只做了一件事情:求导,对多项式求导,对带三角函数的表达式求导,对有括号嵌套的表达式求导.作业难度依次递增,让我们熟悉面向对象编程方法,开始从面向过程向面向对 ...

  2. 【作业1.0】OO第一单元作业总结

    OO第一单元作业已全部完成,为了使这一单元的作业能够收获更多一点,我回忆起我曾经在计算机组成课设中,经常我们会写一些实验报告,经常以此对实验内容反思总结.在我们开始下一单元的作业之前,我在此对OO第一 ...

  3. 北航OO第一单元作业总结(1.1~1.3)

    经过了三次作业之后,OO第一单元告一段落,作为一个蒟蒻,我初步了解了面向对象的编程思想,并将所学内容用于实践. 一.第一次作业 1.架构分析 本次作业需要完成的任务为简单多项式导函数的求解.表达式仅支 ...

  4. 2020 OO 第一单元总结 表达式求导

    title: BUAA-OO 第一单元总结 date: 2020-03-19 20:53:41 tags: OO categories: 学习 OO第一单元通过三次递进式的作业让我们实现表达式求导,在 ...

  5. OO第一单元作业总结

    oo第一单元的作业是对多项式的求导.下面就是对三次作业分别进行分析. 第一次作业 分析 第一次作业相对来讲比较简单,甚至不用面向对象的思想都能十分轻松的完成(实际上自己就没有使用),包含的内容只有常数 ...

  6. OO第一单元总结

    OO第一单元作业总结 一.前言 开学四周,不知不觉已经做了三次OO作业.事实上,每一次作业对我来说都是很大的挑战,需要花费大量的时间和精力来学习. 虽然学得很艰苦,但最后还是连滚带爬地完成了.(好惨一 ...

  7. OO第一单元优化博客

    OO第一单元优化博客 第一次作业: 合并同类项+提正系数项+优化系数指数0/1=满分 第二次作业: 初始想法 一开始是想以\(sin(x)​\)和\(cos(x)​\)的指数作为坐标,在图上画出来就可 ...

  8. OO第一单元(求导)单元总结

    OO第一单元(求导)单元总结 这是我们oo课程的第一个单元,也是意在让我们接触了解掌握oo思想的一个单元,这个单元的作业以求导为主题,从一开始的加减多项式求导再到最后的嵌套多项式求导,难度逐渐提高,编 ...

  9. OO第一单元(前四周)作业总结

    OO第一单元(前四周)作业总结 OO第一单元(前四周)作业总结要求(第四次作业) 0.前言 本次博客针对的是本人学习Java的第一阶段的三次作业的作业总结 第一次作业的内容是:7-1 计算税率 (20 ...

随机推荐

  1. windwos创建和删除服务

    创建 >sc create <service name> type=kernel binpath="C:\hsys.sys" 删除 win+r 输出 regedi ...

  2. 1. VUE介绍

    今天开始系统学习vue前端框架. 我是有前端基础的, 刚工作那会, 哪里分那么清楚啊, 前后端我都得做, 所以, css, js, jquery, bootstrap都会点, 还系统学过ext, 哈哈 ...

  3. oracle中的in参数超过1000的解决方案

    在oracle中,使用in方法查询记录的时候,如果in后面的参数个数超过1000个,那么会发生错误,JDBC会抛出"java.sql.SQLException: ORA-01795: 列表中 ...

  4. django学习-8.django模板继承(block和extends)

    1.前言 django模板继承的作用:模板可以用继承的方式来实现复用,减少冗余内容. 一般来说,一个网站里一般存在多个网页的头部和尾部内容都是一致的,我们就可以通过模板继承来实现复用. 父模板用于放置 ...

  5. redis缓存穿透穿透解决方案-布隆过滤器

    redis缓存穿透穿透解决方案-布隆过滤器 我们先来看一段代码 cache_key = "id:1" cache_value = GetValueFromRedis(cache_k ...

  6. 08.手写KNN算法测试

    导入库 import numpy as np from sklearn import datasets import matplotlib.pyplot as plt 导入数据 iris = data ...

  7. Python算法_三种斐波那契数列算法

    斐波那契数列(Fibonacci sequence),又称黄金分割数列.因数学家列昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为"兔子数列&qu ...

  8. where & having 关键字

    where和having都是做条件筛选的 where执行的时间比having要早 where后面不能出现组函数 having后面可以出现组函数 where语句要跟在from后面 ,where 不能单独 ...

  9. HTTP头Content-Type类型记录

    默认发POST格式 Content-Type: application/x-www-form-urlencoded Content-Type: application/x-www-form-urlen ...

  10. selenium之元素定位的方法(一)

    WebDriver 对象有多种方法用于在页面中寻找元素.他们被分成find_element_*和find_elements_*方法.find_element_*方法返回一个WebElement对象,代 ...