博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
面向对象第一单元总结
阅读量:5954 次
发布时间:2019-06-19

本文共 3758 字,大约阅读时间需要 12 分钟。

面向对象第一单元总结

概述

紧张刺激的OO之旅第一站,交给我们的任务是看起来“枯燥”的求导。最开始,我拿到作业后我的内心OS是:“这和面向对象有什么关系?应该就是让我们熟悉一下Java语言的用法吧。”但是随着一次一次作业的递进,我开始深刻的体会到了这第一单元作业设计的精妙。第一次作业让我们真正开始上手了Java,第二次作业让面向对象的思想开始初步萌芽,而第三次作业则是面向对象基础知识的全面铺展。也许有很多同学和我一样基本每次作业都需要重构,但是对于我们初学者来说,一次次重构正是自己对于面向对象思维和设计构造理解的不断进步。

第一次作业

第一次作业一眼看去就像当初写C语言字符串处理题,而相信我们大部分人写出来的代码,与其说是Java程序,倒不如说是“披着Java外套的C程序”,写出来的程序很C Style,这也是困扰很多同学的问题,诚然,我们之前学习C语言养成的思维习惯在短时间内扭转过来是比较难的,但我们需要在现在开始改变,去接受新的思维方法。通过这次作业,我们开始了掌握正则表达式,掌握Java的字符串处理。有人说,计算机科学的学习过程就是和字符串打交道的过程,而我们开始面向对象学习之旅也从字符串开始是再合适不过了。

首先对几个概念作解释
在分析结果中可以看到ev, iv, v这几栏,分别代指基本复杂度(Essential Complexity (ev(G))、模块设计复杂度(Module Design Complexity (iv(G)))、Cyclomatic Complexity (v(G))圈复杂度。

ev(G)基本复杂度是用来衡量程序非结构化程度的,非结构成分降低了程序的质量,增加了代码的维护难度,使程序难于理解。因此,基本复杂度高意味着非结构化程度高,难以模块化和维护。实际上,消除了一个错误有时会引起其他的错误。

Iv(G)模块设计复杂度是用来衡量模块判定结构,即模块和其他模块的调用关系。软件模块设计复杂度高意味模块耦合度高,这将导致模块难于隔离、维护和复用。模块设计复杂度是从模块流程图中移去那些不包含调用子模块的判定和循环结构后得出的圈复杂度,因此模块设计复杂度不能大于圈复杂度,通常是远小于圈复杂度。

v(G)是用来衡量一个模块判定结构的复杂程度,数量上表现为独立路径的条数,即合理的预防错误所需测试的最少路径条数,圈复杂度大说明程序代码可能质量低且难于测试和维护,经验表明,程序的可能错误和高的圈复杂度有着很大关系。

①代码结构与分析

第一次作业,我毫无悬念的按照C Style完成了所有的代码。原因其一是对面向对象思维还没有形成概念,其二是赶紧应付任务的心理,我觉得如果在第一周知道后面的作业要做什么,一定会有更多同学从第一次作业就开始考虑更多的设计问题,而不是拿到作业就一股脑的往一个类里面加代码。

程序UML图

1615961-20190327172623296-981050760.png

代码数据

1615961-20190327172629778-1727136814.png

1615961-20190327172642469-913568577.png

分析

通过UML图可以看出,我在第一次作业中基本没有体现面向对象,主类和表达式类是典型的一个“傻子类”和一个“上帝类”。”傻子类“只负责了输入而在充当“上帝类”的expression类中,代码风格又是典型的C Style,各个方法相互调用,导致耦合度非常高。这些设计需要引以为戒,这也是为什么在后面的作业中我几乎每次都需要重构。

②BUG分析

这次作业虽然在设计上非常不可取,但是比较值得庆幸的是把BUG数量控制的比较好,在通过了所有公测样例的同时在互测中也没有被发现问题。

③互测分析

测试策略

在第一次测试中大部分同学都使用到了正则表达式来判断输入的合法性,而本次作业绝大多数的BUG也出现在这里。首先一般出现了使用一整个长正则表达式来匹配整个字符串的,在输入极限长度的字符串之后很大几率都会出现栈溢出或者运行时间过长的问题;其次在正则表达式中使用了\\s*而没有对空字符进行判断的、允许出现多种变量名字的也很显然存在问题。

最后便是求导计算时的逻辑错误,在第一次作业中有些同学使用了状态机式的程序,在使用状态机而没有特别判断空串的情况下输入空串则会出现没有输出的现象。同时,在做优化时候如果一视同仁地将值为0的项删去,如果只存在0,那么也会出现空串的输出结果。

第二次作业

从第二次作业开始面向对象的特征变得更加明显。加入三角函数后式子的复杂度明显提升,再使用一股脑处理的方法显得愈发笨拙。

①代码结构与分析

重构分析

第二次作业中,我注意到所有项都可以写成

$$ax^bsin(x)^c*cos(x)^d$$
而这个式子的求导显然可以通过手算得出,所以从计算层面来说上述项就是基本单位,而整个表达式就是若干项连接后的结果,对所有基本项建立类,只需将每项求导之后作化简拼接即可。

程序UML图

1615961-20190327172704707-1235005677.png

代码数据

1615961-20190327172720286-230259630.png

分析

本次作业相比于第一次作业,稍稍体现了那么一点点面向对象的思维,对项建立类,单独设置求导方法,虽然一个类里面的方法耦合度比较高,但是类和类之间的耦合度较低。不过还是可以看出,项的分类还可以更加细致,更加细致的分类意味着更低的耦合度和更加灵活的组合,由于第二次作业分类不够精细,我第三次作业又做了很多修改。

②BUG分析

第二次作业通过了所有的强测点,在互测中也没有被找出错误,但比较遗憾的是没有做更多的优化,对结果表达式只做了简单合并同类项处理,而很多地方可以用到提公因式化简,这导致了性能分不是特别高。

③互测分析

在第二次作业中由于将字符长度限制在了一个比较小的范围,所以用长正则表达式处理的也几乎不会出现栈溢出或者超时的现象。在表达式正确性判断上大家都没有出现太多问题,所以关注的重点就是求导过程和最后优化过程的问题。在互测中遇到更多的还是优化上的问题。有同学优化了结果开头的“1”,但是这会出现一个有趣的现象,如果没有特别判断而直接去除的话就会出现比如

$$22sin(x)^{21}cos(x) -> 22sin(x)^2cos(x)$$

这种错误的结果。

其次,在第二次作业中我也使用到了对拍器。很多同学对造数据都比较有心得。这里推荐。

第三次作业

相比于前两次作业,第三次作业开始真正体现了层次和对象设计,如果说前两次作业可以直接列出所有可能的情况暴力算,那么第三次作业就是“防不胜防”的存在。嵌套完了还能再嵌套,处理的复杂程度和前两次作业完全不是一个级别,而在第三次作业如果对象层次混乱,没有一个合理的设计架构,那么将会出现非常多难以预料的错误。

①代码结构与分析

重构分析

前面说到,在第二次作业中我对于项没有做更细致的划分,这就导致了第二次作业中的项没法直接应用到第三次作业中。所以在第三次作业我对每个种类的项都做了细致明确的划分,带符号整数、x项、三角函数项为基本项。

而具体层次结构如下,结构层次参考自。

  • 因子 = 带符号整数 | x幂| 三角函数幂| (表达式)
  • 项 = [-|+]因子(*因子)*
  • 表达式= [-|+]项([-|+]I项)*

其中[]表示其中的字符存在或不存在皆可;()*表示可选重复0至任意次;|表示或

对每个基本项建立类,对每个因子、项、表达式建立类。按照上述层次拼接在一起即可形成一个完整的表达树,在每个层次实现求导,从表达式层到因子层需要用到链式法则,从因子层到项层需要用到求导乘法法则,从项到表达式层要用到加法法则。这样处理第三次作业的结构就显得清晰易懂。

程序UML图

1615961-20190327172750135-735445078.png

代码数据

1615961-20190327172758670-491656859.png

1615961-20190327172804664-1045352433.png

代码分析

相比于前两次作业比较混乱的层次设计,第三次作业在设计层面提出了更高的要求,如果没有足够清晰的设计,在处理大量繁琐的表达式是非常困难的,在第三次作业中除了类内部的一些处理方法需要反复使用导致方法耦合度较高,类与类之间基本做到了低耦合,而且较为细致的划分层次也具备可扩展性。缺点是这些类内部的处理方法其实可以单独划为一个类,另外在本次作业中我没有使用到继承,如果能合理使用必然会使得代码结构更加合理。

②BUG分析

在求导过程中由于链式法则和乘法法则的存在,我把每个层次的求导结果都用括号括起来,这就导致了结果看起来非常冗长,而且我在一处由于不经意间的疏忽忘记了补上了匹配的右括号,导致结果出现错误。其次在输出结果的因子与因子间,除了第一项可以带符号,其他项前导不能带上符号,这点我在输出处理时没有注意到,导致WA很多。比如如下输出结果

1615961-20190327173653167-38135665.png
起初是本着不优化就不会出BUG的想法(其实是时间不够了),没有对程序作太多优化工作,但是以上错误足以致命。

结语

经过第一单元三次作业的洗礼,我也算是真正开始上手了Java语言,开始能完整的运用面向对象设计构造的方法。不过在欣赏了几位同学设计的代码之后我感到自己还有比较大的差距,记得助教说过,决定你走的有多远的是稳定可靠的架构设计,公布的几位同学的代码乍一眼看上似乎代码量很大,但是却有着强大的延展性。第一次作业也许我的C Style代码量会少一点,但是从长远看,如果从第一次作业开始就深思熟虑过自己的设计,第一次作业就可以让后面的工作事半功倍。这些设计方法都是需要在以后的作业、实验中慢慢掌握的。只希望在掌握的过程中少扣点分QAQ。

转载于:https://www.cnblogs.com/NoobKingCWR/p/10609090.html

你可能感兴趣的文章
绘制折线图
查看>>
django项目基础
查看>>
Linux 基本权限管理
查看>>
用css去除chrome、safari等webikt内核浏览器对控件默认样式
查看>>
PHP —— 识别运算符实现逻辑比较
查看>>
Powershell都有哪些好用的技能?
查看>>
【软工】第一次阅读作业
查看>>
权限管理系统 mysql 数据脚本
查看>>
Javascript中对空string调用split返回不是空数组
查看>>
用CSS设置Table的细边框的最好用的方法
查看>>
My SQL外键约束
查看>>
CSS实现返回网页顶部
查看>>
Queue 输出数据
查看>>
模拟Windows任务管理器CPU使用率的动态折线图-农夫山泉
查看>>
floyd
查看>>
列表操作2
查看>>
Django例子-出版社
查看>>
第2章 变量和基本类型 附3---底层const和顶层const
查看>>
一次完整的HTTP请求响应过程(很详细)
查看>>
[UIKit学习]03.关于UILable
查看>>