BUAA_OO第一单元作业总结
BUAA_OO第一单元作业总结
单元任务
第一单元的任务为实现表达式的求导,其中第一次作业是对简单多项式的求导,第二次作业是对包含简单幂函数和简单正余弦函数的多项式的求导,第三次作业是对包含简单幂函数和简单正余弦函数同时存在嵌套情况的多项式的求导。
一、基于度量的程序结构分析
第一次作业
1. 设计思路
第一次作业给出的多项式每一项之间仅包含加减运算,并且每一项都有固定的格式,即为系数*x^指数,因此可以创建两个ArrayList链表,一个为系数,另一个为指数。首先通过正则表达式将关于空白符与符号错误的情况进行识别过滤,之后将字符串中省略的部分进行替换,使每一项都符合标准格式,即系数*x^指数,通过遍历字符串,识别每一项的系数和指数。通过这两个链表实现求导功能。
优化部分包括合并同类型、省略系数和指数和正项提前。如果指数部分相同,则将系数相加合并为一项;如果系数为零,删除这一项,如果系数为1或-1,省略1和乘号,如果指数为1,省略^1,将所有的+-替换为-;将第一个系数为正的项提前,可以减少一个符号。
2. 类图

3. 程序结构分析
首先解释一下每一项的含义:
LOC: Lines of Code 代码行数
NCLOC: Non-comment Lines of Code 没有注释的代码行数
ev(G): Essential Complexity 基本复杂度:用来表示一个方法的结构化程度。
iv(G): Module Design Complexity 模块设计复杂度:用来表示一个方法和他所调用的其他方法的紧密程度。
v(G): Cyclomatic Complexity 圈复杂度:圈复杂度用来衡量一个模块判定结构的复杂程度,数量上表现为线性无关的路径条数,即合理的预防错误所需测试的最少路径条数。圈复杂度大说明程序代码可能质量低且难于测试和维护。


从上述数据可以看出程序的复杂程度比较高,结构化程度不高,说明这次的程序主要还是面向过程的思路,没有通过面向对象的思路来实现。类的创建也不是很合理,虽然创建了一个类,但与其说是类,不如说只是一些方法的集合,并没有体现出类与类之间的逻辑结构,以及类的封装特性。同时,因为第一次编写java程序不太熟悉,程序中是通过遍历来实现每一项的区分,并没有使用字符串的split操作,导致程序比较复杂,代码行数也比较多,同时程序也不具有可扩展性,不能应用于第二次和第三次作业。
第二次作业
1. 设计思路
第二次作业相较于第一次作业相对复杂了一些,加入了三角函数,但与第一次作业相同的是,每一项依旧有固定的格式,即系数*x^指数*sin(x)^指数*cos(x)^指数,因此每一项可以通过系数、x的指数、sin(x)的指数、cos(x)的指数这四个属性来表示。本次作业创建了三个类,Main类用于控制输入输出,Poly类表示多项式,用于管理和创建每一个项,其中包含多项式求导以及多项式优化的方法,Term类即为描述项的类,其中包含属性和实现求导的方法。其余部分的设计思路与第一次类似。
优化部分相较于第一次的优化,还多出了sin(x)^2+cos(x)^2=1的优化可能,因此多出了许多种优化的可能,有些优化会减少结果的长度,有些优化反而会增加结果的长度,因此在程序中对于sin(x)^2+cos(x)^2=1的情况,只进行了一定会减少长度的优化,并没有实现所有的优化。
2. 类图

3. 程序结构分析


从上述可以看出,相较于第一次作业,这次作业程序的模块化更为明确,类之间的逻辑关系也更加清晰。从复杂度数据来看,程序的平均复杂度有所下降,每个方法的复杂度也有所下降,说明面向程序的思想有所减弱。这次程序的主要缺点在于优化部分没有完全实现,忽略了一些可以优化的情况。
第三次作业
1. 设计思路
第三次作业在第二次作业的基础上加上了嵌套的情况,因为有递归嵌套的可能性,本次的程序主要采用了递归下降子程序的结构。
输入的表达式由多个项通过加减进行组合,因此表达式Expr类的结构为

对表达式通过+进行分割,得到一个个项,项由多个因子相乘,因子包括表达式因子、常数因子、幂函数因子、三角函数因子,因此Term类的结构为

此时,在构造的过程中就出现了递归嵌套的结构,在通过字符串构造表达式Expr时,需要构造项Term,而在构造Term的时候有可能需要构造Expr,体现了递归子程序的思想。
幂函数Power类的结构与之前类似,包括系数和指数,此处的系数主要是为了处理像-x和+x这样省略系数的情况。
三角函数SinCos类相对比较复杂一些,结构为

因为正弦函数和余弦函数的格式类似,在程序中将两者合并为一个类,通过String类型的type来进行区分。因为允许嵌套,三角函数括号内部通过表达式Expr来进行描述,index为三角函数的指数,coeff是为了处理出现系数省略的情况。
每一个类中都有相应的求导方法,例如Expr类中的求导是通过对链表中所有的Term进行求导,再将结果加起来,而Term中的求导则是按照求导公式,分别求导再相加。
本次作业为了保证正确性,只进行了特殊系数和特殊指数的优化,并没有进行其他优化。
2. 类图

3. 程序结构分析


从上述数据可以看出,平均复杂度相较于第二次作业有所下降,但却出现了一些复杂度比较高的方法,说明依然没有实现高内聚低耦合的结构。本次作业的优点在于程序更加结构化了,代码行数也变较少,相较于第二次作业,虽然功能增加了很多,但代码行数却没增加多少,缺点在于本次作业并没有采用课堂上讲解的继承和接口和没有实现优化。本次作业可以将不同类型的项汇总成一个接口,而表达式Expr则是一个接口组成的链表,每个类中定义不同的求导和转换字符串方法,在对表达式求导的时候,也就是对每一个接口进行求导,因为接口的特性,在对项求导时,调用的求导方法是每个项对应类的求导方法,这样实现可以减少很多在求导时的判断,将所有的项看作一个整体,转换为字符串时也是同样。这样可以有效地减少程序的递归次数,在最终转换为字符串和优化时也会减少很多麻烦。像我之前的代码,在生成求导结果的时候就会产生多重嵌套,原本只是一个常数系数也会被看作一个表达式处理,在优化的时候造成了很大的麻烦。
二、程序bug
1. bug特征与所在的类和方法
第一次作业的功能比较简单,可能出现bug的地方只要是错误情况的判断。为了便于对字符串进行模块化的处理,需要将输入的表达式的每一项转换为标准格式,为此需要将一些符号,例如++,--,x进行替换,此时可能会将一些错误的输入变成可以识别的输入,无法实现鲁棒性。
第二次作业的bug主要是在优化部分,在使用正则表达式对结果字符串进行替换的过程中,没有测试到^1后面是数字的情况,因此在替换之后出现错误的结果表达式。
第三次作业的bug可能是会忽略对于-1系数的处理,还有就是对于错误情况的判断。因为我的程序使用的是split方法,因此对于最后一个*后面没有输入的情况是不会判断其为错误输入的。
2. bug位置与设计结构之间的相关性
从这三次作业来看,bug的位置一般都是处于需要对情况进行分类的位置,例如很多if语句的位置或者if语句的判断条件极为复杂的位置。因为需要分类,就难免会出现考虑不全面的问题,一旦出现考虑范围之外的输入,程序立刻就会出现错误。其次就是对于不同情况划分不明确,这样会导致程序的鲁棒性不高,也可能出现调用的方法不对应。
3. 从分类树角度分析程序在设计上的问题
分类树可以将输入根据特定的条件进行划分,其叶子节点为输入的各种可能情况,将所有叶子节点的可能情况进行排列组合就可以尽可能覆盖所有的输入情况。而将程序与分类树进行对比,能相对容易地发现程序在设计上的问题。当程序的分类情况少于分类树的叶子节点时,说明有情况是程序设计没有考虑到的,会在缺少的情况输入时出现bug。
三、Applying Creational Pattern
第一次和第二次作业中因为功能比较简单,因此不太需要使用创建模式。
第三次作业可以使用工厂方法模式,简单的工厂模式,就是去创建一个创建对象的工具类,具体到第三次作业,就是创建一个类用于根据字符串创建不同的类,调用类中不同的创建方法。而我目前的程序是将对象初始化的方法放在了构造函数中。之后再创建一个接口,将所有类的求导方法通过这个接口连接在一起。
如果要重构的话,首先需要创建一个创建的工具类create,根据字符串不同的开头情况,调用相应的创建方法,其次需要创建一个接口的类Node,将常数类、三角函数类、幂函数类、项类、表达式类通过这个接口连接在一起,在每一个类中实现对应的求导方法。
四、总结
通过这三次的作业,我逐渐脱离了之前面向过程的思想,开始向面向对象的思路转换,同时也熟悉了一些java编程时的技巧,比如使用正则表达式以及一些已经写好的方法。通过对需求的扩展,使我们明白了一个程序架构的重要性,如果在写代码之前先进行设计,在实现的时候就可以规避很多麻烦,而一个良好的设计可以为程序带来很好的扩展性,在面对扩展的需求时,也不需要进行重构。
BUAA_OO第一单元作业总结的更多相关文章
- 【BUAA-OO】第一单元作业总结
#OO第一单元作业总结 #确认存活,爱学习,爱北航,爱OO 一.三次作业分析 1.第一次作业 1.1 程序结构 对方法的度量: 类的内聚和相互间的耦合情况: 类图: 优缺点: 优点大概没什么优点,毕竟 ...
- 【OO学习】OO第一单元作业总结
OO第一单元作业总结 在第一单元作业中,我们只做了一件事情:求导,对多项式求导,对带三角函数的表达式求导,对有括号嵌套的表达式求导.作业难度依次递增,让我们熟悉面向对象编程方法,开始从面向过程向面向对 ...
- 2019OO第一单元作业总结
OO第一单元作业的主题是求导,下面将分三次作业分别总结一下. --------------------------------------------------------------------- ...
- BUAA OO 2019 第一单元作业总结
目录 总 架构 Controller Model 输入处理 代码静态分析 行数 方法复杂度 UML 类图 优点 缺点 坑 输入 非法的空白字符 输入的简并处理 运算 浅拷贝 可变类型与不可变类型 ...
- 【作业1.0】OO第一单元作业总结
OO第一单元作业已全部完成,为了使这一单元的作业能够收获更多一点,我回忆起我曾经在计算机组成课设中,经常我们会写一些实验报告,经常以此对实验内容反思总结.在我们开始下一单元的作业之前,我在此对OO第一 ...
- OO第一单元作业总结——表达式求导
OO第一单元作业总结 第一次作业 基于度量分析代码结构 基本算法 第一次作业是简单多项式导函数求解,不需要对输入数据的合法性进行判定, 基本思想是用 (coeff, expo)表示二元组 coeff* ...
- OO第一单元作业小结
前言 第一单元的主题是表达式求导,第一次作业是只带有常数和幂函数的求导,第二次作业加入了正余弦函数,第三次作业又加入了表达式嵌套,难度逐渐提升.总体来说前两次作业还易于应对,而第三次作业做得相对有些艰 ...
- OO第一单元作业总结
oo第一单元的作业是对多项式的求导.下面就是对三次作业分别进行分析. 第一次作业 分析 第一次作业相对来讲比较简单,甚至不用面向对象的思想都能十分轻松的完成(实际上自己就没有使用),包含的内容只有常数 ...
- BUAA_OO第二单元作业总结——多线程
OO第二单元作业总结——多线程 单元任务 本单元主要的内容是通过模拟电梯的运行来熟悉多线程的实现,从简单的单部FAFS电梯开始,ALS电梯,到最后的多部ALS电梯. 一.设计策略分析总结 1.1 多线 ...
随机推荐
- html5 css练习,弹性三栏布局
*{ margin: 0; padding: 0;} body,html{ width: 100%; height: 100%; font: bold 24px ...
- 非常不错的svg教程
介绍的非常详细,也很有调理,内容很详细 适合于初学者学习 http://www.softwhy.com/qiduan/SVG_source/
- 【SparkStreaming学习之三】 SparkStreaming和kafka整合
环境 虚拟机:VMware 10 Linux版本:CentOS-6.5-x86_64 客户端:Xshell4 FTP:Xftp4 jdk1.8 scala-2.10.4(依赖jdk1.8) spark ...
- Spring Boot中使用Swagger2构建RESTful APIs
关于 Swagger Swagger能成为最受欢迎的REST APIs文档生成工具之一,有以下几个原因: Swagger 可以生成一个具有互动性的API控制台,开发者可以用来快速学习和尝试API. S ...
- CCF CSP 201503-2 数字排序 (map+自定义排序)
题目链接:http://118.190.20.162/view.page?gpid=T26 返回试题列表 问题描述 试题编号: 201503-2 试题名称: 数字排序 时间限制: 1.0s 内存限制: ...
- cnetos7设置中文显示及中文输入法
Centos7安装的时候即使选择了中文安装,因为安装后并没有GUI,即使后来安装GUI后默认依旧是英文显示. 输入locale后显示的是 永久修改成中文:编辑/etc/profile.d/lang.s ...
- ABP入门系列之2——ABP模板项目
进入官网下载模板项目 依次按下图选择: 输入验证码开始下载 下载提示: 二.启动项目 使用VS2017打开项目,还原Nuget包: 设置以Web结尾的项目,设置为启动项目: 打开Web.config, ...
- JavaScript--鼠标滚动改变图片大小
鼠标滚动改变图片的大小: 原理:当鼠标滚动时改变了zoom的值: <!DOCTYPE HTML> <html> <head> <title>通过鼠标滚轮 ...
- callable函数 stride的意义 Math.round(),Math.ceil(),Math.floor()用法
callable()函数检查一个函数是否可以调用 如果返回True,object仍然可能调用失败:但如果返回False,调用对象ojbect绝对不会成功. 对于函数, 方法, lambda 函式, 类 ...
- 防止sql注入(简单)
(1)mysql_real_escape_string -- 转义 SQL 语句中使用的字符串中的特殊字符,并考虑到连接的当前字符集 使用方法如下: $sql = "select count ...