多项式求导系列——OO Unit1分析和总结
一、摘要
本文是BUAA OO课程Unit1在课程讲授、三次作业完成、自测和互测时发现的问题,以及倾听别人的思路分享所引起个人的一些思考的总结性博客。本文第二部分介绍三次作业的设计思路,主要以类图的形式展现,并有简单的优劣分析;第三部分为程序代码复杂度的分析(二、三两部分为基于度量的对自己程序结构的分析);第四部分为对自己、对他人程序的测试、DEBUG、Hack的思考;第五部分是分析作业中可以应用对象创建模式的可能性,和重构的思考。
二、开发设计思路
1.程序类图展示
第一次作业

第二次作业

第三次作业

2.简单分析
这三次作业我基本上采用了完全不同的方法,感觉到其实非常有趣并且很有收获。
第一次作业的时候我的所有代码都在一个.class文件内,设计了一个没有什么意义的主类Derivation,包含了一个多项式类和一个单项式类。这种设计除了在文件管理上不容易丢失文件以外基本没有什么好处。第二次和第三次作业中代码才越来越面向对象。第三次中有一些体现抽象工厂的设计,使用了Factor接口和Item抽象类,显然第三次作业的程序更具有可扩展性。实际上我在第二次作业中就有意识地在降低模块的耦合以方便单元测试。
第二次和第三次的作业实际上采用了不同的设计思路,主要在于第二次是为了提高对输出优化处理的可扩展性,第三次是为了提高支持输入的项的类型的可扩展性。第二次中的对象保存的是对一个多项式的各种处理方法,而第三次的对象保存的是多项式的各种组成成分。这两个程序一个在怎么处理产品的方法上有较好扩展性,一个在能处理的产品种类上有较好扩展性。此外,第三次作业我尝试直接使用字符串来保存数据,无意中使用了Creative Pattern。前两次作业中,会牵涉到对象的拷贝等,容易发生错误,某些对象的方法可能不具有可再现性,引入不安全性并且不利于单元测试;第三次作业中,由于没有计划做详细的优化,使用了直接进行字符串操作的简化设计,但非常不利于优化。此外,前两次作业使用的容器还较为传统(定长数组),不利于利用现有的包进行合并同类项优化而自己写了优化的方法,虽然实现简单,但是也浪费了空间资源。
三、程序结构分析
1.度量分析
第一次作业


第二次作业



第三次作业



从三次作业来看,代码结构的基本复杂度、模块复杂度和圈复杂度呈现明显的逐次下降趋,体现出我的程序更加结构化、模块化,这有利于代码的理解和结构化、模块化的维护、测试和功能扩展;各模块之间耦合度降低,有利于模块的隔离、维护和复用;程序独立路径的数量也在减少,则出现错误的几率会降低,亦有利于测试和维护。
四、测试、DEBUG与互评
1.个人BUG分析
第一次作业:
- 引发错误的数据:“+x+x+x...”(大量“+x”构成的长输入)
- 引发的错误:正则表达式匹配栈溢出错误
- 没有测出的原因:本地使用JDK版本比评测机高,该版本正则表达式并不会发生这样的匹配导致栈溢出的错误,所以虽然本地也测试过这种数据,但是并不会引发错误
- 错误的代码:
"|\\d+)[ \t]*)*[ \t]*";
- 修改后的代码:
123 "|\\d+)[ \t]*)*+[ \t]*";
- 分析:使用在匹配中使用独占模式即可使得程序在对整个输入进行匹配后不进行回溯,从而避免栈溢出的错误。
第二次作业:
- 引发错误的数据:“x^2*cos(x)^6*sin(x)^7+x*cos(x)^6*sin(x)^7”
- 引发的错误:优化时引入了计算错误
- 没有测出错误的原因:测试不充分
- 错误的代码:
boolean canOptimizeWith(Monomial m) {
return ((this.power.equals(m.power) &&
(this.sinPower.equals(
m.sinPower.add(new BigInteger("2")))
&& m.cosPower.equals(
this.cosPower.add(new BigInteger("2"))))
|| (this.cosPower.equals(
m.cosPower.add(new BigInteger("2")))
&& m.sinPower.equals(this.sinPower.add(new BigInteger("2")))))));
}
- 修改后的代码:
48 return (this.power.equals(m.power) &&
55 this.cosPower.add(new BigInteger("2")))
- 分析:判断两项是否满足优化条件的方法错误,逻辑太复杂导致的括号错误。
第三次作业:
- 引发错误的数据:cos((-x^+7*x^7))^+1
- 引发的错误:对象调用了自己的方法导致循环调用,引发栈溢出错误
- 没有测试出的原因:测试不充分
- 错误的代码:
public void optimize() {
if (super.getData().matches(".*\\^0*1")) {
setData(getData().replaceAll("\\^0*1", ""));
} else if (super.getData().matches(".*\\^0*")) {
setData("1");
}
}
- 正确的代码:
public void optimize() {
if (super.getData().matches(".*\\^0*1")) {
setData(super.getData().replaceAll("\\^0*1", ""));
} else if (super.getData().matches(".*\\^0*")) {
setData("1");
}
}
- 分析:我的设计中getData时要优化,优化的时候要调用父类的getData,如果调用自己的,则会循环调用。
2.互测BUG分析和Hack技巧
我互测中遇到的BUG主要是对数据的输入处理的问题,例如未判断正负号使用是否正确就先去除了重复的正负号,或者在正则表达式中使用“\s”从而引入了不允许的特殊字符的可能性,或者某些位置应该允许输入多个空格只允许了单个。还有对不完整的输入,比如“+x+”,"45*"等没有进行判断。第三次作业中,还有同学没有使用BigInteger处理数据,或者对指数为000000000000000000001的输入进行了报错,说明这方面没有处理得当。还有对于如“x*+1”的乘法内含有带符号整数因子处理错误的情况。
主要通过阅读代码针对性测试和构造测试数据盲测结合进行测试。JUnit的Series能够排列组合生成一些数据,同学分享的随机生成字符串也能生成数据,但主要还是人工设计的边界条件数据或者特殊情况数据更容易测出错误。在时间允许的情况下,阅读代码是最有效的找到别人BUG的方法。当然,自己设计时积攒或出错过的测试数据也有使用的价值。
3.对提高DEBUG效率的思考
|
What Information |
More Information | Less Information |
|
Trail |
Step by step |
Conditional Breakpoints |
|
Code |
The whole code |
Coverage |
|
Value of variables |
Variables |
Watches/Evaluation |
|
Exception |
Throw an exception |
... |
|
Anything |
Hiearchy + |
Hiearchy - |
我认为DEBUG也是值得思考的事情。DEBUG是根据提供的信息寻找所写代码中错误并改正的过程。通过IDEA和Eclipse所支持的丰富的功能,我们可以轻易的获得包括代码覆盖、变量值、代码轨迹等信息,通过增加和减少信息结合自己程序的设计结构,可以大大减少锁定bug的时间。利用条件断点实现分级的DEBUG信息输出也是有价值的DEBUG方法。
五、对象创建模式的应用思考
第一次作业中,我没有实现多项式类,将多项式当做多个单项式存储在数组中进行处理,并编写相应的各种方法。可以重构,设计多项式类,仅包含HashMap类,而且由于多项式求导后还是多项式,求导方法可以使用new的方法返回一个多项式。
第二次作业中,也没有实现多项式类。仍可设计多项式类,各种多项式处理器与主函数的数据交流也可以重构为对象创建的方法,每次返回一个new多项式,可以使得各种求导、优化、合并同类项、根据三角函数公式优化等方法可以独立地开发和测试。
第三次作业我已经有使用工厂模式的影子,仍有很多可以改进的地方。可以完成部分优化工作,这里就需要注意equals方法的重写以支持合并同类项。此外,在我设计中使用了替换字符以屏蔽括号内正负号和乘号的处理方法来应对多层嵌套,分割后再将字符换回,这个有很大的不安全性,也可以重构,将这种乘积和单项式匹配方法(即递归地根据+、*分割输入)改为expression tree对象的处理,改为工厂模式,可以减少正则表达式的使用和避免对输入数据的改动引起的不安全性。
多项式求导系列——OO Unit1分析和总结的更多相关文章
- OO第一单元总结-多项式求导
OO第一单元总结-多项式求导 一.第一.第二次作业总结 因为前两次作业设计复杂度差别不大,因而放在这里统一总结. 基于度量分析程序结构: 前两次作业确实存在缺乏可拓展设计的构想,基本还是面向过程的思维 ...
- BUAA_OO Summary——多项式求导问题
从C.DS.计组一路折磨过来, 几乎都在采用过程化.函数式的编程思想.初接触面向对象的项目开发,经过了三周的对多项式求导问题的迭代开发,经历了设计.coding.测评环节,算是对面向对象有了一定的认识 ...
- OO_多项式求导_单元总结
概述: 面向对象第一单元的作业是三次难度依次递增的多项式求导.第一次作业是仅包含带符号整数和幂函数的多项式求导,例如:-1+xˆ233-xˆ06:第二次是在前面的基础上增加了三角函数的求导,例如:-1 ...
- OO第一单元总结__多项式求导问题
作业一.含幂函数的简单多项式的求导 (1)基于度量的程序结构分析 1. 统计信息图: 2. 结构信息图: 3. 复杂度分析 基本复杂度(Essential Complexity (ev(G)).模块设 ...
- OO第一单元总结——多项式求导
第一次作业分析 1.程序结构分析 类图: 好吧,这一次基本上完全是在面向过程编程,没有看出来任何的面向对象的特性. 复杂度: 可以看到模块间的相互耦合度很高,PolyDerive方法的非结构化程度也不 ...
- 多项式与三角函数求导——BUAA OO 第一单元作业总结
第一次作业 需求简要说明 针对符合规定的多项式表达式输出其符合格式规定的导函数多项式,格式错误输出WRONG FORMAT! 带符号整数 支持前导0的带符号整数,符号可省略,如: +02.-16> ...
- OO随笔之魔鬼的第一单元——多项式求导
OO是个借助Java交我们面向对象的课,可是萌新们总是喜欢带着面向过程的脑子去写求导,然后就是各种一面(main)到底.各种方法杂糅,然后就是被hack的很惨. 第一次作业:萌新入门面向对象 题目分析 ...
- BUAA_OO_homworkone包含三角函数的多项式求导
第一次作业 基于x的简单多项式相加求导 带符号整数 支持前导0的带符号整数,符号可省略,如: +02.-16>.19260817等. 幂函数 一般形式 由自变量x和指数组成,指数为一个带符号整数 ...
- UML系列——OO Unit4分析和学期总结
一.本单元的架构设计 1.类图 第一次 第二次 2.关键方法和架构简述 总体而言是读取图的时候就完成大部分计算(完成缓存),调用查询方法时只是展示计算的结果,少部分直接计算.主要是设计了各种自己定义的 ...
随机推荐
- handsontable的基础应用
handsontable是一款页面端的表格式交互插件,可以通过她加载显示表格内容,能够支持合并项.统计.行列拖动等. 同时,支持对加载后的表格页面的处理:添加/删除行/列,合并单元格等操作. 我在项目 ...
- DotNetCore 3.0 助力 WPF 开发
DotNetCore Is AnyWhere. 前言 Visual Studio 2019 已经正式发布了,DotNetCore 3.0 的正式版也指日可待.在之前的版本中,作为一名基于微软生态的传统 ...
- 随心测试_软测基础_004<测试人员工作职责>
接上篇续,依据_软测基础体系:<依据不同的测试对象,选取适合的方法,按照设计的流程完成测试工作,检验整个过程是否达到测试的目的>.“学以致用”,实践于工作职责 常见面试题: —— 诸如以下 ...
- dede织梦 arclist标签完美支持currentstyle属性
由于客户需求,所以进行对文章的arclist标签进行设置当前样式(currentstyle),修改前记得备份. dede版本v5.7sp 找到PHP修改: include/taglib/arclist ...
- Springboot+mybatis中整合过程访问Mysql数据库时报错
报错原因如下:com.mysql.cj.core.exceptions.InvalidConnectionAttributeException: The server time zone.. 产生这个 ...
- 使用redis可能出现的问题
1)缓存与数据库双写不一致 2)缓存雪崩 3)缓存穿透 由于缓存中不存在某个key,所有的请求都会落到数据库上,会对数据库造成很大压力,甚至崩溃 一个简单的方案是将不存在的数据也缓存起来(value值 ...
- Docker 核心技术之数据管理
Docker 数据卷简介 为什么用数据卷 宿主机无法直接访问容器中的文件 容器中的文件没有持久化,导致容器删除后,文件数据也随之消失 容器之间也无法直接访问互相的文件 为解决这些问题,docker加入 ...
- dataTables 插件学习整理
在项目中使用了dataTables 插件,学习整理一下. dataTables 的官方中文网站 http://www.datatables.club 引入文件: 所有的都要引入 jq文件 1. dat ...
- 一次单体测试的采坑--MatcherAssert.assertThat---org.hamcrest 和org.mockito
单体测试测试环境ci上报这个错, 本地没问题. org.hamcrest.Matcher.describeMismatch(Ljava/lang/Object;Lorg/hamcrest/Descri ...
- 深度学习结合SLAM研究总结
博客转载自:https://blog.csdn.net/u010821666/article/details/78793225 原文标题:深度学习结合SLAM的研究思路/成果整理之 1. 深度学习跟S ...