2019-北航面向对象-求导作业总结
(一)基于度量来分析自己的程序结构
由于平时使用了NetBrains出品的IDEA作为IDE,在分析程序的时候我使用了IDEA的插件Metrics Reloaded。然而在使用时发现不懂得很多分析项目的含义,因此花费了一些时间了解,并在这里总结。
Complexity Metrics(复杂度分析)
这部分我们需要使用的主要是方法和类的复杂度分析。
方法的复杂度分析主要基于循环复杂度的计算。循环复杂度是一种表示程序复杂度的软件度量,由程序流程图中的“基础路径”数量得来。
(1)ev(G):即Essentail Complexity,用来表示一个方法的结构化程度,范围在$[1,v(G)]$之间,值越大则程序的结构越“病态”,其计算过程和图的“缩点”有关。
(2)iv(G):即Design Complexity,用来表示一个方法和他所调用的其他方法的紧密程度,范围也在$[1,v(G)]$之间,值越大联系越紧密。
(3)v(G):即循环复杂度,可以理解为穷尽程序流程每一条路径所需要的试验次数。
对于类,有OCavg和WMC两个项目,分别代表类的方法的平均循环复杂度和总循环复杂度。
Dependency Metrics(依赖度分析)
依赖度分析度量了类之间的依赖程度。有如下几种项目:
(1)Cyclic:指和类直接或间接相互依赖的类的数量。这样的相互依赖可能导致代码难以理解和测试。
(2)Dcy和Dcy:计算了该类直接依赖的类的数量,带表示包括了间接依赖的类。
(3)Dpt和Dpt:计算了直接依赖该类的类的数量,带表示包括了间接依赖的类。
第一次作业类图及度量:
第二次作业类图及度量:
第三次作业类图即度量:
(二)分析自己程序的bug
第一次作业:第一次作业我通过了所有强测的测试点,在互测中也没有被hack,我也没有找到自己程序的bug。
第二次作业:第二次作业中,细致来说,程序有两个bug。第一个是在判断字符串合法性时,我忘记去掉字符串前后的空格了,导致合法的情况被误判为非法形式了。第二个是在对输出的字符串进行优化时,我没有考虑清楚所有可能出现的情况,将所有的“+1*”全部替换成了“+”、将所有的“-1*”全部替换成了“-”,这就导致当求出的式子中存在指数未-1且后面与其他因子相乘时被误删掉,导致程序出现了bug。
第三次作业:在第三次作业中我犯了一个很低级的错误,在x的幂函数求导时,为了输出能简洁一些,我将x^1单独考虑了,结果手误打错了,本想打“1”,结果打成了“x“,结果导致输入x^1时,导数输出x而不是1。
(三)分析自己发现别人程序bug所采用的策略
(1)在测试自己程序时,我会编一些数据来验证自己程序的正确性,在这个过程中,我会把自己编的数据记录下来,在测试他人程序时,我会先用这些数据进行一番测试,若发现错误,我会根据错误信息到代码中定位错误点、找到错误原因,方便进一步查找bug。
(2)在试过自己编写的程序之后,我会逐一地阅读房间中同学的代码,通过理解对方的思路来寻找漏洞。在发现有疑问的地方时,我会针对问题点编造一些特殊的数据,在验证对方代码的正确性的同时,也验证自己的想法的正误。
(3)在以上操作进行完毕的情况下,我会与朋友进行交流分享,询问她们是否测到了什么bug、输入了什么数据,同时也将自己组中发现的问题分享给她们,实现合作共赢。
(四)Applying Creational Pattern
三次作业我都在一定程度上进行了新的构建。
第一次是用面向对象的形式、以面向过程的思想来写的代码,所以复用性很差。设置了两个类,一个类中进行输入输出,另一个类中包含所有处理过程。
第二次作业,我在第一次的基础上,重新进行了架构,设置了一个Poly类,这个类中抽象出系数、x的指数、sin(x)的指数、cos(x)的指数这四个对象,并利用ArrayList构建动态数组,在Dispose(字符串处理类)中进行调用和处理,最终通过toString得到输出的字符串,并在Test类中进行输入和输出。
第三次作业,我共设置了8个类,分别是Test类(负责输入输出)、Dispose类(负责字符串合法性判断)、Addorsub类(负责对加减的形式进行处理)、Multi类(负责对乘的形式进行处理)、Nest类(负责对嵌套的形式进行处理)、Direct类(负责对可以直接处理的形式进行处理,即最基本情况的处理)、Method类(负责判断用哪种方式进行处理,即Addorsub、Multi、Nest、Direct中的一种)、Dofunc类(一个功能接口)。通过递归思想和树的构建来一层一层获得求导的情况,直至全部到达最基本形式,然后一层层返回,拼凑成最终形式。
(五)总结与反思
在这一单元的学习过程中,我积极思考、认真完成,同时我及时与同学交流想法、共同研究、分享思路,这让我在写代码的过程之中少了很多不必要的麻烦,在遇到了一些挑战和困难的同时,也收获良多。这三次作业使我对面向对象有了基本的理解,也在一定程度上区分了面向对象和面向过程,在编程思路上也有所转变。下面我对我的三次作业做出如下总结:
第一次作业:所谓万事开头难,第一次作业就让我一头雾水、不知从何入手。这是我第一次接触面向对象的思想,并没有弄清楚面向对象和面向过程的区别是什么,这让我很苦恼。由于时间紧任务重,在没有很好理解面向对象的基础上,我便匆匆忙忙开始写我的第一次作业。可以说,第一次的作业我还是按照C语言的思路来完成的,大体上就是通过划分过程从而写出若干个子函数,最终实现功能。虽然作业通过了强测所有的测试点,但是代码复用性并不好,题目一旦增加其他需求,便需要重新进行构建。总的来说,第一次的作业带给了我很多思路,也让我开始去理解面向对象的思想,虽然有不完善的地方,但我个人还是挺满意的。
第二次作业:相比于第一次作业,第二次作业增加了三角函数的求导和连乘。由于第一次作业架构不是很合理,我不得不重新进行构建。不过这一次我思路开始转变,类的划分也比上一次清晰很多,这让我完成地相对顺利。唯一遗憾的是自己在优化时没有考虑到所有可能出现的情况,导致程序出现了明显的bug。
第三次作业:相比于前两次求导的作业,第三次作业的难度又提升了一个等级,看完指导书后完全没有思路,因此我与几个同学决定大家一起共同理解题意,试图寻找思路。同时,我也询问了任课老师,老师也给了我们很多指点,这让我们的思路逐渐清晰。这次作业我们运用了接口来实现功能,并运用递归的思想完成求导的任务,最终按时完成了任务。只是让我很懊恼的是,我再次犯了很低级的错误,处理特殊情况时不小心打错了,导致程序出现了非常低级的bug,还是自测过程中不够细致造成的。