OO第一单元总结——求导
一.基于度量分析程序结构
(一)第一次作业
(1)设计思路
本次作业只涉及到简单幂函数通过加减运算而复合而成的函数,因此笔者自然的把函数分成了函数本体以及单个的项两个部分,在笔者的设计中两个类的功能如下:
Poly:存储函数本体、将函数的各个项分解出来
Item:存储单个的项、单个项的求导、输出
(2)UML类图
本次设计主要的采用了Poly和Item两个类,分别代表函数表达式和单个的幂函数因子,本次设计中存在的问题在于,主类中包含不必要的方法init()用以对字符串进行预处理,通过研讨课,笔者意识到在主类中只应该暴露给出用户直接使用的方法以确保程序的安全性,比如在该系列作业中,主类只需要调用求导方法即可。
(3)复杂度分析
从复杂度看出此次作业中,poly.print()方法的iv(G)被标红,设计复杂度高意味模块耦合度高,这将导致模块难于隔离、维护和复用。由于在进行第一次作业时笔者还未认识到通过重写toString()方法可以实现直接通过调用System.out.println()进行输出,因此在此次作业中花费了大量的条件语句笨拙的实现了字符串的输出。
(4)bug分析
此次作业笔者未出现bug。
(二)第二次作业
(1)思路分析
相比第一次作业,第二次作业新增了三角函数以及乘法的复合形式。针对第二次作业新增的要求,笔者将单个的项看作的形式,将乘积形式复合的求导转化到单个项的求导中(事实证明这并不是一个好的方法,暂且按下不表)。类的设计与第一次大同小异,不再重复叙述。
(2)UML类图
此次作业相比第一次作业,主类做到了简洁,只调用了必要的方法。但是Poly类中包含了高达9个方法,也就是说大部分的工作都是由Poly类完成的,该类即承担了存储的功能还承担了对表达式的各种复杂处理的功能,功能过于臃肿。
(3)复杂度分析
Item.printItem()和Poly.getItem()又被标红,前者的原因与第一次作业相同,为了简化输出做了很多的特判;后者的原因是该方法独立的承担了从项中分离出指数、因数等必要数据并完成存储的功能,笔者认为该方法的功能十分独立,为了完成功能的要求牺牲了复杂度是可以接受的。
(4)bug分析
本次作业笔者出现了bug,原因是对指导书的内容理解有误。具体如下:指导书规定指数的绝对值不超过10000,但是笔者误以为是化简结果的指数,比如x**10000*x**1,实际是正确的表达式,但是在化简后的结果为x**10001,于是被笔者的程序判定为WRONG FORMAT。这次bug也提醒笔者,对指导书的内容要充分理解,避免出错。
(三)第三次作业
(1)思路分析
第三次作业增加了嵌套规则,待函数复杂度瞬间大幅提升,导致在第二次作业的基础上几乎无法进行功能上的添加(这就是前文中提到的四元组不是好的方法的原因),于是在代码上几乎进行了重组,类的数量也大幅增加。在表达式的处理上采取了树形结构,建立表达式树以后从根节点开始向下求导。各个类的简介如下:
Sin , Cos , Exp , Const:构成函数的最简单的因子。
Add , Mul , Nest:加法、乘法、嵌套三种规则
Split:对表达式进行处理的函数类
Format:格式判断的函数类
(2)UML类图
本次作业的主要功能的完成集中与Split类中,即数据分离,其他类的功能都比较简单。
和函数类都实现了Func接口,使得在求导过程中充分利用了多态的特性,笔者也认为这是本次作业中对笔者帮助最大的特性。
(3)复杂度分析
由于方法比较多,笔者只截取了标红的方法。在第三次作业中,笔者终于学会了重写toString()方法,在输出上的复杂度终于大幅下降。主要分析一下前三个方法,getFunc()方法是分离最基本因子(Exp,Sin,Cos,Const),check()方法是用于判断嵌套因子是否合法,addsplite()方法是分离表达式中通过加减相连的各项,这三个方法在构建表达式树的时候被频繁调用,因此iv(G)十分的高,这里我认为有很大的改进空间。
(4)bug分析
由于笔者的本次作业无效,因此没有参加强测和互测。于是笔者分析一下程序无效的原因。在乘法法则的求导规则是:(f(x)g(x))' = f(x)'g(x) + f(x)g(x)',由于笔者在建立表达式树的时候只保存了求导后的结构,为保存原函数,于是笔者的乘法法则变为了:(f(x)g(x))' = f(x)'g(x) + f(x)'g(x)',已经求过导的项在表达式中只会出现其导数的形式,导致了错误的发生。
二.探测bug策略
step1:在对自己的程序进行测试时,保存的样例。这部分主要是对程序的功能性的覆盖,但是一般很难通过这里找出bug。
step2:构造边界数据、特殊数据等,在本次作业中主要是指数的范围、特殊的指数(0、1、-1)、大量重复数据(如:x*x*x*x*x*x*x*x-x+x-x+x);这些数据有可能找出bug。
step3:阅读代码,重点关注个人认为容易出错的地方,比如字符串的预处理和分离以及输出。
三.应用对象创建模式进行重构
三次作业笔者都是遵循,函数-表达项-因子的结构创建对象,但是对象的创建过程往往集中于函数类中,导致函数类中大量的实例化表达项类、因子类,使得函数类具有较高的复杂度。在对比优秀代码后,我发现在此次作业中工厂模式是十分有效的对象创建模式,在之后的设计中也应该多加注意对设计模式的应用。
四.心得和体会
(1)不足:1.关于三次作业中拓展性的考虑不够,进行了多次重构。现在回过头来思考三次作业,笔者认为其实就对应这相加、相乘、嵌套三个复合规则。如果在一开始就注意到这一点,在迭代开发的过程中依次实现相关的复合规则求导必然可以减少不必要的重构,同时也更加符合逻辑。
2.类的功能不清晰,在设计过程中出现了一个类中包含很多的方法,承担了过于多的功能的情况。在之后的设计中,如何抽象出类以及类的方法设计需要投入更加多的思考。
3.方法设置不合理,在设计过程中经常出现checkstyle时提醒方法过长,为了通过checkstyle而强行将一个方法进行拆分的情况。笔者认为一个方法的行数限制在60行是为了限制方法的复杂度,减少出错,同时从笔者阅读代码的实际情况来看,如果一个方法过长的话,阅读体验也会直线下降。刚开始笔者也在质疑一个方法限制60行是否合理,但是经过三次作业的实践我也认同了方法长度的限制。
4.与优秀代码进行对比之后,我发现优秀代码的共同特点是对功能的拆分做的十分细致和自然,一个类的长度往往不会很长。而笔者的代码就会出现1个类包含5个以上的方法的情况。除此,优秀代码往往也采用了合理的设计模式,比如工厂模式。在笔者的代码中基本上都是一种随性的生成模式,缺少优秀的设计模式,这是笔者亟待加强的部分。
(2)体会:首先,作为一个Java小白,通过pre系列的作业,笔者对Java有了初步的了解,但是笔者发现仅仅掌握初步的入门知识往往不足够,笔者认为对java语法的了解和设计思想的深入是相辅相成的,比如:java具有的多态特性使得我们可以通过工厂模式实例化不同的类,而在使用这些对象的相同方法时而不担心我们是否调用了正确的方法。其次,对面向对象的设计思想的理解和运用,目前笔者对对象的抽象仅停留在直观的层面,这是需要多加思考和交流的。最后,对时间的把控,在最后一次作业中,由于周五才开始进行,导致在最后测试时发现了设计上的重大错误,但是时间不足以支持修改完成的情况致使作业无效,这一点令笔者十分懊悔。通过总结我得出的几点经验是:尽早开始动手!尽早开始动手!尽早开始动手!;开始之前对程序的结构进行充分的思考,不要一边写一边思考(笔者的经验是这样很有可能造成写的到一半发现有问题又进行大规模的重写);多参与讨论区的讨论,在讨论区有很多优秀的思路,本次的作业中讨论区也帮了笔者很大的忙。
OO第一单元总结——求导的更多相关文章
- OO第一单元表达式求导作业总结
第一次作业 功能描述: 对输入的表达式进行求导计算和格式正误判断 思路: 一开始的想法是想写一个大正则找到一个通项式,通过这个多项式来判断WRONG FORMAT,结果发现正则写的总是不完善,会漏 ...
- OO随笔之魔鬼的第一单元——多项式求导
OO是个借助Java交我们面向对象的课,可是萌新们总是喜欢带着面向过程的脑子去写求导,然后就是各种一面(main)到底.各种方法杂糅,然后就是被hack的很惨. 第一次作业:萌新入门面向对象 题目分析 ...
- BUAA-OO-第一单元表达式求导作业总结
figure:first-child { margin-top: -20px; } #write ol, #write ul { position: relative; } img { max-wid ...
- OO第一单元(求导)单元总结
OO第一单元(求导)单元总结 这是我们oo课程的第一个单元,也是意在让我们接触了解掌握oo思想的一个单元,这个单元的作业以求导为主题,从一开始的加减多项式求导再到最后的嵌套多项式求导,难度逐渐提高,编 ...
- 2020 OO 第一单元总结 表达式求导
title: BUAA-OO 第一单元总结 date: 2020-03-19 20:53:41 tags: OO categories: 学习 OO第一单元通过三次递进式的作业让我们实现表达式求导,在 ...
- OO第一单元作业总结——表达式求导
OO第一单元作业总结 第一次作业 基于度量分析代码结构 基本算法 第一次作业是简单多项式导函数求解,不需要对输入数据的合法性进行判定, 基本思想是用 (coeff, expo)表示二元组 coeff* ...
- OO第一单元总结-多项式求导
OO第一单元总结-多项式求导 一.第一.第二次作业总结 因为前两次作业设计复杂度差别不大,因而放在这里统一总结. 基于度量分析程序结构: 前两次作业确实存在缺乏可拓展设计的构想,基本还是面向过程的思维 ...
- 2019年北航OO第1单元(表达式求导)总结
2019年北航OO第1单元(表达式求导)总结 1 基于度量的程序结构分析 量化指标及分析 以下是三次作业的量化指标统计: 关于图中指标在这里简要介绍一下: ev(G):基本复杂度,用来衡量程序非结构化 ...
- OO第一单元作业总结
oo第一单元的作业是对多项式的求导.下面就是对三次作业分别进行分析. 第一次作业 分析 第一次作业相对来讲比较简单,甚至不用面向对象的思想都能十分轻松的完成(实际上自己就没有使用),包含的内容只有常数 ...
随机推荐
- 第44天学习打卡(JUC 线程和进程 并发和并行 Lock锁 生产者和消费者问题 如何判断锁(8锁问题) 集合类不安全)
什么是JUC 1.java.util工具包 包 分类 业务:普通的线程代码 Thread Runnable 没有返回值.效率相比Callable相对较低 2.线程和进程 进程:一个程序.QQ.exe, ...
- 第41天学习打卡(死锁 Lock synchronized与Lock的对比 线程协作 使用线程池)
死锁 多个线程各自占有一些共享资源,并且互相等待其他线程占有的资源才能运行,而导致两个或者多个线程都在等待对方释放资源,都停止执行的情形.某一个同步块同时拥有"两个以上对象的锁"时 ...
- 500GJava/Hadoop/Spark/机器学习...视频教程免费分享 百度云持续更新
参加工作这么长时间了,工作中遇到了不少技能都是看视频教程学习的,相比较看书而言看视频确实比较容易理解.分享一下自己看过的和收集的视频教程. 资源包括: 大数据方面的Hadoop(云帆,小象学院,八斗学 ...
- 微信小程序日期时间选择器(精确到秒)
<picker mode="multiSelector" value="{{dateTime1}}" bindchange="changeDat ...
- Mybatis系列全解(七):全息视角看Dao层两种实现方式之传统方式与代理方式
封面:洛小汐 作者:潘潘 一直以来 他们都说为了生活 便追求所谓成功 顶级薪水.名牌包包 还有学区房 · 不过 总有人丢了生活 仍一无所获 · 我比较随遇而安 有些事懒得明白 平日里问心无愧 感兴趣的 ...
- pytorch(02)tensor的概念以及创建
二.张量的简介与创建 2.1张量的概念 张量的概念:Tensor 张量是一个多维数组,它是标量.向量.矩阵的高维拓展 Tensor与Variable Variable是torch.autograd(t ...
- sql之对top语句理解
起因 事情的起因是在群里和大佬讨论问题,讨论select top x后加*的问题,这时突发奇想,想搞清楚这个看起来在sql中略显突兀的语句结构,就有了这篇文 先看例子 select * from 表 ...
- 使用函数式语言实践DDD
长期以来我都在实践OOP,进而通过OOP来实现DDD,特别是如何通过面向对象的技巧来建立一个领域模型.OO的一些特性在建立领域模型时显得恰如其分,能否掌握OO的技巧,对创建领域模型有着至关重要的作用. ...
- 在ASP.NET Core中用HttpClient(二)——发送POST, PUT和DELETE请求
在上一篇文章中,我们已经学习了如何在ASP.NET Core中使用HttpClient从Web API获取数据.此外,我们还学习了如何使用GetAsync方法和HttpRequestMessage类发 ...
- 如何学习python爬虫
分享网易云课堂上一个不错的视频教学:http://study.163.com/course/courseMain.htm?courseId=1003285002