Part 0: 前言

令人闻风丧胆的OO还是来了。并没有像名字的外表一样可爱,简直就是恶魔。

疯狂压榨OS的时间,周末无法休息,互测狼人机制

虽然网上骂声很多,就算改进到9012年还是有很多不足的地方,但和往年相比,已经有很大进步,也更加人性化了,我们并不能力求在我们这一届做到完美,这毕竟是一个长期长期长期长期又漫长的过程。既来之,则安之,既然无法改变规则,就让自己适应规则吧。

Part 1: 量度分析

接下来将细分开每一个板块来对我自己的三次作业来进行分析

DesigniteJava

DesigniteJava是一款专门分析代码质量的静态评估工具,并且识别潜在的质量问题。它会检查代码的架构,设计和代码的异味并且以csv的格式给出详细的度量分析。

对与分析Java这种面对对象的语言,我们这次主要看这几个参数:

  1. CC 圈复杂度

    用来衡量一个模块判定结构的复杂程度,圈复杂度越大说明程序代码质量低,难以测试和维护

  2. LCOM 方法的内聚缺乏度 值越大说明类内聚合越小

  3. FANIN 类的扇入 扇入表示调用该模块的上级模块的个数,扇入越大,表示该模块的复用性好。

  4. FANOUT 类的扇出 扇出表示该模块的直接调用的下级模块的个数,扇出大表明模块内复杂度高,但扇出过小也不好。

    总结就是,一个好的JAVA代码,设计要求是高内聚低耦合的,所以LCOM值要小,FANIN的值要大,FANOUT值合理。

    那么用这个方法看三次的度量结果:

    第一次作业:

    第二次作业:

    第三次作业:

可以发现,在Main函数中我们的圈复杂度都是相对较高的,这是因为我在Main中放了存放和预处理字符串的代码,这导致圈复杂度增高,而且确实大量的正则表达式和字符串替换难以后续阅读和维护,这是毋庸置疑的。看了其他同学的优秀代码,比如17373331的代码,Main中几乎没有什么实际的执行代码,只是在调用其他方法和处理异常,看优秀的代码给我的感觉就是非常清晰,在主函数中就明确告诉我了这个project是在什么的,合理的类的命名,简单易懂的返回值设定和处理异常的语句,符合OOP的设计。

果然,没有对比就没有伤害:17373331的静态分析:

    明显可以看出参数饱满了很多,不像我生成的几乎都是0,较小的LCOM和较大的FANIN和合理的FANOUT,果然花花的代码能被称作标杆范文。
 
此外,可以看到我的代码分析后的FANIN是几乎没有的,说明我的代码的复用效率低下,可能存在很多重复的代码,反观我的代码确实在这几次作业中,确实有很多服用的代码,就比如字符串为了防止被查WF,反复用正则表达式检查变换几次,甚至用上了 while (matcher.find())这样的循环查找,不仅复用率低下,其实代码的执行效率也非常低下。

  反思自己的代码质量,几乎惨不忍睹,甚至感觉用来查c等面对过程的语言得到的结果也相差无几,主要是以下几点原因:
  1. 阅读面对对象的代码太少,学习了理论但是无法自己亲手时间,可能具备了阅读不同的代码说出是不是符合面对对象的设计,但是自己却无法写出。

  2. 对质量的盲目追求。在分数的利益驱动下,自然地用面对过程的语言,也就是自己熟悉的语言来处理字符串,这样虽然代码不是很好看,甚至在第三次作业中为了判断各种WF情况而写了冗杂的正则表达式查询代码,导致主函数内方法函数超60行,代码风格质量严重降低,这时又只能通过分开建立不同的方法来分担正则式的长度,恶性循环导致风格逐渐下降,但是分数可以很好,别人几乎不能攻击我的WF,这也是对自己的代码风格和分数之间的trade-off之间,分数占了上风吧。

  3. 还没有形成剥离抽象层的思维,像zsa学长在讨论区的接口讲解非常清晰,举出了生动的例子——手机的充电接口来让我们理解。 但是总是在自己构思的时候就无法剥离出sin cos 和x 和constant 之间的共性特征和共性方法,所以也很少使用继承或者借口了,在最后一次的作业中强制要求使用后才尝试用接口的方法来解决求导的问题。

接下来查看自己的UML图,由idea自动生成:

第二次作业UML   



第三次作业UML 

第一次作业似乎无法生成UML,可能是因为太面向过程了一点,但我还可以看到第二次和第三次的,但是要我评价自己的类图,我十分羞愧,因为这完全是一个没有上过OO理论课的人都能写出来的东西,所以我大概讲一下我的类图在写代码时的构造吧:

在第二次的代码中我才用了四元数的方式,所以自己构建了两个class,分别是Trig 三元组储存x 和 sin 和 cos,还有Term 四元数在三元数的基础上增加了前面的常数项,由这两个class我们就可以对相同的相进行合并。并且尝试了多态的方法;在第三次的代码中采用了接口的方式,对所有项的求导进行了归一化,但是其实可以更加优化,那就是将所有的项归并到抽象类中,因为他们都有共同的属性比如内部的表达式(指sin和cos内部的值)还有幂次都是共通的,用抽象类的方法可以将他们更加内聚在一起,所以我也打算重新写一遍第三次的代码了,当然是建立在阅读第二次优秀的代码基础之上。

在第三次作业中,我也对static和final有了更进一步的了解。之前看到java的代码中很多的static所以没有融入自己的思考盲目static,这直接导致我第二次作业开始,开的类多了之后出现致命的错误,创建多个对象之后共同修改一个属性,导致了大片的错误输出,所以说还是实践出真知。

Part 2: bug分析

第一次作业:

第一次作业比较简单,当然自己用面对过程的语言做所以没有出什么问题,最后是数据点全过+0hacked,但是当然还有美中不足的地方,那就是性能分没有拿到满分,具体在于自己运用HashMap的方式存储结果,查询不到HashMap如何查找到特定value的值,即正数的值放到第一位,所以最后性能分未满,但是如果现在要我再交的话,我会利用先存进ArrayList的形式来做一个简单的排序,从而将正项第一个输出。

第二次作业:

第二次作业在强测中出了一个BUG,导致被分配到了C组中去,因为自己优化太过于匆忙,疏忽了HashMap在puts之前要先检查是否存在,导致相同的Key值出现了覆盖Value的情况,最后失分。其实自己写了一个专门puts进HashMap的方法,在方法中检查了Key值并进行合并,但是由于是ddl前的早上优化所以没有进行太多的测试,过了弱测和中测就没有多想,这个案例说明 侥幸心理 是万万不可取的。

在互测屋中还被发现了一个特殊的bug,在输入以运算符结尾的时候我不能判断出格式错误,导致被人狂刀,这也是和自己的测试策略有关,自己在自测的过程中偏向于对正确性进行检验,而忽略了错误形式的表达式的构建,导致失分。

第三次作业:

吸取了第二次作业被WF杀害的经验教训之后,几乎最后一天都在对格式判断进行改动,但是没有注意到助教的置顶帖中已经说明移除了WF的数据,有一点时间没有用到刀刃上的感觉,甚至有点把自己给误伤了。过多的特殊WF情况的判断导致自己对代码的结构已经无法理解,结果在强测中对正确的输入报了WF,痛失去一个强测点。此外,对括号内的处理也不够仔细,忽略了幂次也能带有负号的问题,导致表达式提取出现问题,结果丢分。

在第一单元最后一次的研讨课上,有位同学给予了我们一个开始工程的思路——先构建数据集(测试集),再下手打代码,起到打代码的时候有的放矢的高效。开始的时候我是有点不理解的,但是在反思自己的作业的过程中,发现第三次作业中我所犯下的错误完全是可以由一开始构建一个较为完备的测试集而规避的,而且纪老师说在后续的工程化代码中,提前构造测试集是一种非常有效防止严重漏洞的手段,所以我也考虑在重写第三次作业的时候也尝试这种方式。

Part 3: hack

对于查找别人的漏洞的方式,主要在于以下几点:

  1. 自己在打代码的时候,测试自己的代码时所出错的数据点都一一保留,这应该是算弱测。

  2. 寻找特殊的表达式的特征,具体可能是x-x或者多个+-号的形式。

  3. py或者java自动生成代码加上mma的带入测试。

  4. 寻找同学进行求助,每个人对同一问题的思考角度不同,hack别人的点一般有很大区别,所以是一个补全的很好的策略。

Part 4:重构的说明

重构其实不是一件丢人的事情,自从上学期计组以来,发现其实解决自己bug的最好最快的方式就是重构。重构可以帮助我们在原有的基础上进行改善,一方面验证我们对现有知识体系的更加深层的理解是否正确,另一方面也是对未来增添功能时候提供一种方便。在初学的阶段,我认为重构代码时非常常见的,也是一种高效的学习方式,虽然时间会花费很多,所以在第二次作业中我就采取了重构的方式,改掉了原有的面向过程的写法,采用了初级入门的面向对象,并且在第三次作业中也复用了第二次作业的体系逻辑,虽然增添删改了许多内容但其实也减轻了我挺大的工作量的。

以上便是本人对于前三次OO作业的博客总结,后续可能会贴上自己第二次作业甚至第三次作业的优化的方法的思考。

Object-Oriented Programming Summary Ⅰ的更多相关文章

  1. Object Oriented Programming python

    Object Oriented Programming python new concepts of the object oriented programming : class encapsula ...

  2. JavaScript: Constructor and Object Oriented Programming

    Constructor :  Grammar: object.constructor Example: Javascript code: 1 function obj1() { this.number ...

  3. 面对对象编程(OOP, Object Oriented Programming)及其三个基本特性

    一千个读者,一千个哈姆雷特.对于面对对象编程,书上都会告诉我们它有三个基本特性,封装,继承,多态,但谈起对这三点的见解,又是仁者见仁智者见智,感觉还是得多去编程中体验把 . 面向对象编程(OOP, O ...

  4. Python 面向導向語言 Object Oriented Programming Language

    Pytho 是面向對象的程式語言,舉凡 Literals 值都是 Object.例如: >>> id(38)8791423739696 與 >>> id('ABC' ...

  5. leetcode@ [355] Design Twitter (Object Oriented Programming)

    https://leetcode.com/problems/design-twitter/ Design a simplified version of Twitter where users can ...

  6. opp(Object Oriented Programming)

    嗯,昨天忙了一天没来及发,过年啊,打扫啊,什么搽窗户啊,拖地啊,整理柜子啊,什么乱七八糟的都有,就是一个字,忙. 好了,废话也不多说,把自己学到的放上来吧.嗯,说什么好呢,就说原型链啊 原型对象 每个 ...

  7. oop(Object Oriented Programming)

    嗯,昨天忙了一天没来及发,过年啊,打扫啊,什么搽窗户啊,拖地啊,整理柜子啊,什么乱七八糟的都有,就是一个字,忙. 好了,废话也不多说,把自己学到的放上来吧.嗯,说什么好呢,就说原型链啊 原型对象 每个 ...

  8. Week 5: Object Oriented Programming 9. Classes and Inheritance Exercise: int set

    class intSet(object): """An intSet is a set of integers The value is represented by a ...

  9. python, 面向对象编程Object Oriented Programming(OOP)

    把对象作为程序的基本单元,一个对象包含了数据和操作数据的函数. 面向过程的程序设计把计算机程序视为一系列的命令集合,即一组函数的顺序执行.为了简化程序设计,面向过程把函数继续切分为子函数,即把大块函数 ...

  10. JS面向对象程序设计(OOP:Object Oriented Programming)

    你是如何理解编程语言中的面向对象的? 我们研究JS和使用JS编程本身就是基于面向对象的思想来开发的,JS中的一切内容都可以统称为要研究的“对象”,我们按照功能特点把所有内容划分成“几个大类,还可以基于 ...

随机推荐

  1. 吴裕雄--天生自然python学习笔记:python 用pyInstaller模块打包文件

    要想在没有安装 Python 集成环境的电脑上运行开发的 Python 程序,必须把 Python 文件打包成 .exe 格式的可执行 文件. Python 的打包工作 PyInstaller 提供了 ...

  2. Git ubuntu 升级

    外文文档 This team will distribute the most current stable package of Git for Ubuntu. Stable releases: h ...

  3. nmon监控指标

    一.NMON中的各项参数指标: SYS_SUMM:显示当前服务器的总体性能情况 Total System I/OStatistics: Avg tps during an interval:显示采集间 ...

  4. zabbix 扩展脚本

    #!/usr/bin/env python #encoding:utf8 # desc: self-inspection # args: # reboot : reboot AP # check : ...

  5. Python: Socket网络编程,多线程处理小Demo

    一个简单的例子,深入研究一下socket的多线程处理任务 Server端: #!/usr/bin/env python #encoding:utf8 # # 注意:定义encoding时必须在第二行 ...

  6. ./config\make\make install命令详解

    这些都是典型的使用GNU的AUTOCONF和AUTOMAKE产生的程序的安装步骤 一.基本信息 1../configure 是用来检测你的安装平台的目标特征的.比如它会检测你是不是有CC或GCC,并不 ...

  7. NopCommerce上二次开发 触发器记录

    最近要在NopCommerce上二次开发. 开发也就算了,该项目的架构设计很好,但性能不可谓不低. 扯远了,为了保持项目以后升级顺利,开次开发不允许在原项目基础上大改,只能以插件形式开发…… 因一个功 ...

  8. 用nexus搭建maven2内部服务器

    由于项目组需要,要搭建内部的Maven仓库,借鉴项目组内部及外部同事的经验选用nexus来搭建内部仓库.下面描述一下具体的步骤.  一.安装配置过程  1.下载nexus,地址http://www.s ...

  9. manacher算法 详解+模板

    manacher算法可以解决字符串的回文子串长度问题. 个人感觉szy学长讲的非常好,讲过之后基本上就理解了. 那就讲一下个人的理解.(参考了szy学长的ppt) 如果一个回文子串的长度是偶数,对称轴 ...

  10. Java Design Patterns(2)

    1.Factory Design pattern 工厂设计模式的优点 (1)工厂设计模式提供了接口而不是实现的代码方法. (2)工厂模式从客户端代码中删除实际实现类的实例化.工厂模式使我们的代码更健壮 ...