大作业总结

Xgyy176184 / 2024-04-21 / 原文

前言:这三次大作业包含了许多基础知识点(包括类与对象的使用,类与类之间的关系与调用,以及许多基础方法的创建与使用),题量上来说出了几道锻炼基础的小题,并不很影响大作业的完成,难度方面可以明显看出在逐步上升,但总体来说并不是为难我们,相对时间而言比较适中。
设计与分析:

第一次大作业的编码构思,类的创建都是根据题目中给出的设计建议来做的,从类图中也可以看得出,这次大作业的基本构思是由输入的数据储存到问题类中,再将问题类集中在试卷类中,最后在答卷类中进行对于试卷类中的题目的正误判断。因为这次大作业的数据复杂度并不高并且题目中给出了设计参考,所以我个人认为本次编码的调用关系还算合理,毕竟比较简单。

由于第二次大作业与第一次大作业的总体框架大致相同,所以很大程度上我保留了第一次大作业中的类的结构,再根据第二次大作业相较于第一次大作业中增加的要求在试卷类中增加了分数这个属性,同时增加了判断试卷总分是否为100的方法。相较于第一次大作业,第二次大作业的编码中还有一处改动较大的地方是将题号,试卷号等数据的类型从String改为了Int,这样做的好处在我处理题目编号的查找以及数据处理时非常明显地体现了出来,在类图中体现的比较明显的就是我删除了试卷类中的排序方法,因为将题号等数据的类型改为int后可以直接根据题号大小进行检索,可以说这一改变给我第二次大作业带来了很大的便利。

第三次大作业的整体框架依旧是根据前两次大作业的框架进行修改的,在之前的基础上加上了学生和删除类,并且在主函数的输入部分加上了数据格式判断方法,因为和第二次大作业的大体部分相同,所以本应该在此次编码中的调用关系不会过于复杂,但是因为我的一个非常错误的决定使得这次的代码关系非常难以理顺,这个决定就是将错误格式判断以及题目试卷的检索全都一股脑堆砌在了主函数中,以至于连我本人隔了不到一天的时间去重新梳理自己的代码结构都非常费力。在这次大作业的编码过程中我在痛苦的梳理修改代码结构的体验中体会到了合理安排各个功能之间的关系以及构造整体功能框架的重要性,也实际感受到了面向对象与面向过程的区别,深刻地认识到了面向对象思维的重要性,我认为这是这次大作业中很深刻的一次教训。
踩坑心得:在这三次大作业的完成过程当中必然不可能是一帆风顺的,我在这几次大作业中和各类测试点间进行了无数次的博弈,下面简单分享一下印象最深的几次:
public void rechange(){
for(int i=1;i<quesnum;i++){
if(this.ques[i].qnum.compareTo(this.ques[i+1].qnum)>0){
Question a=this.ques[i];
this.ques[i]=this.ques[i+1];
this.ques[i+1]=a;
}
}
}
这是第一次大作业我用来解决题目乱序输入问题的排序函数,第一眼看上去是不是没有半点问题,非常传统的冒泡排序,我在查最后两个未通过的测试点时也是这么想的,以至于我在排查各个方法时都没怀疑过这个函数一次,但在我测试了超过十组问题数据的输入时,我马上就发现了问题,10号问题紧紧的排在了1号问题的后面,那么错误在哪就非常明显了,是的,我居然没有考虑序号的字符长度问题!将其改正后立即就通过了最后两个测试点,这是改正后的排序方法:
public void rechange(){
for(int p=1;p<quesnum;p++){
for(int i=1;i<quesnum+1-p;i++){
if(this.ques[i].qnum.length()>this.ques[i+1].qnum.length()){
Question a=this.ques[i];
this.ques[i]=this.ques[i+1];
this.ques[i+1]=a;
}
else if(this.ques[i].qnum.length()==this.ques[i+1].qnum.length()){
if(this.ques[i].qnum.compareTo(this.ques[i+1].qnum)>0){
Question a=this.ques[i];
this.ques[i]=this.ques[i+1];
this.ques[i+1]=a;
}
}
}
}
}
第二次大作业中记忆比较深刻的坎还是问题数据提取,当时还有两个测试点没过,并且那已经是最后一天了,实在想不到问题出在哪情况下我去第一次大作业中找了找灵感,结果这一找立马让我发现了问题所在,让我发现问题的是第一次大作业中的一个测试样例:

很明显了,第二次大作业中因为测试样例中并没有出现这样带空格的问题,所以我在将输入的问题数据提取出题目序号,问题内容和答案时选择了检测空格进行分离提取:
if(s.substring(1,2).compareTo("N")0){
String[] q=s.split(" ");
int qnum=Integer.parseInt(q[0].substring(3).trim());
String Q=q[1].substring(3).trim();
String ranswer=q[2].substring(3).trim();
question[i]=new Question(qnum,Q,ranswer);
i++;
}
很明显这样遇到上面那种情况会提取出错误的题目以及答案信息,在改成根据#分离信息并提取后果然通过了测试点
if(s.substring(1,2).compareTo("N")
0){
String[] q=s.split("#");
int qnum=Integer.parseInt(q[1].substring(2).trim());
String Q=q[2].substring(2).trim();
String ranswer=q[3].substring(2).trim();
question[i]=new Question(qnum,Q,ranswer);
i++;
}
第三次遇到的印象深刻的问题就有点明显了,一开始我非常遵循着测试样例的引导,成功的进入了题目的圈套,在每一种数据的输入中都安排了检测函数,但我竟然忽略了,错误输入可以不属于任何一种数据,在反应过来后果断加上了广泛错误检测
if(!s.substring(0,3).matches("#[N|T|X|S|D]😊&&s.compareTo("end")!=0){
System.out.println("wrong format:"+s);
}
改进建议:在第一次大作业中,作为对面向对象理念毫不了解的新人,可以说是完全在按照C语言的思路在做题了

就如图片中这样,甚至连类中数据的封装都没有考虑,所以对于第一次大作业的改进我觉得最重要的是基础面向对象思维的改进,而这一点在第二,三次大作业中也体现了出来,吸取了第一次大作业的经验,在第二次大作业中在考虑了数据封装,类的使用与联系后,各种类中方法的相互调用明显比之前清晰了许多,但另一个问题却随着编程难度的增加愈发明显,随着难度的上升,每次代码中类的行数并没有增加很多,相反,主函数的代码行数却每次以百为单位在增加,以至于在第三次大作业中的类只占了140行,而主函数却高达260行。并且因此还产生了一个很大的问题,在第二次大作业中我曾测试在第一次大作业的基础上对功能进行增加与修改,但因为主函数的功能过多过杂导致我很长时间都没能够将新功能成功融入到第一次大作业的代码之中,所以对于之后编码最大的改进建议我个人认为是将不同的函数方法放在相应功能的类中集中在主函数中进行调节调用,以主函数为中心将不同的功能向各个类中分布出去。这几次大作业中其实还共同体现出了一个问题,那便是我会过于急于进行编程而忽略了在此之前对于题目需求的分析,导致很多次我都会为一个小问题大刀阔斧地修改自己的代码,这也导致其实很多时间我都花在了本很容易解决的问题上,所以我认为对于之后遇到的问题,我非常需要先静下心冷静分析题目需求再进行编程。还有一点改进建议其实是在我写完代码后别人参考我代码看不懂询问我时才考虑到的,那就是注释!注释!一定要加注释!因为隔了一点时间看自己的代码,就会发现你的代码是只属于写代码时的你的,在这之后即使代码是你写的,你也会感觉非常陌生。这一点其实在写代码时也已经有所感受了,在后续修改代码中经常需要去重新读懂自己写的方法,但那时可能刚写完没多久还能比较轻松地看懂,但其实在我写这篇博客重新翻看这几次的大作业的代码时已经很难快速看懂自己在写什么了。所以在之后编码时一定需要在比较复杂的方法中加入一些注释提醒。
总结:总的来说,这三次大作业的练习让我对Java这门计算机语言有了一个基础的认知,了解了许多在C语言学习过程中未能接触过的语法与处理问题的方法,同时也让我学习到了许多Java的基础知识(比如类的使用,方法调用,数据的封装等等)。更重要的是这几次大作业的练习让我感受到了我们现在所学的面向对象的思维方式与C语言学习中面向过程的思维方式之间的区别与各自的优缺点,也清楚地认知到自己的思维是完全没有从面向过程转化为面向对象的,面对这几次大作业时还习惯性的用着处理C语言作业时的方法去思路去解决问题,这一点也伴随着大作业难度的增加越发明显的体现了出来。所以很明显,对于之后的学习方向,我的一大侧重点必定是思维的转变。而另一大侧重点则是提高自己对于需求分析的重视,以减少自己在后续修改代码中可能遇到的麻烦。最后再谈谈我目前对于这门课程的个人感受,其实刚开始对于面向对象这门课程的教学方式我并没能快速地接受,毕竟与之前接受的教学方法截然不同。而在听了这段时间的课程以及完成了这几次大作业之后也慢慢开始能够接受这种教学方式。不过课堂上的教学,我还是希望能多加入一些对于一些新接触到的概念,方法等的实际应用样例,可以多参杂一些涵盖在网络课堂上提及到的新知识点的应用解析以及主要用途,能让我们更实际地感受这些新事物的用法,在之后的大作业中也希望能够针对性地加入一些让我们能够实际应用这些新知识的小题目,让我们更深切去体会这些知识点。