OO第五、六次大作业总结

news/2024/10/14 8:24:16

一、前言

  在经过了第一阶段的迭代大作业之后,我们迎来了新的迭代大作业-智能电器模拟系统。

在这个阶段的大作业中,我们需要编写模拟家用电器与电路的程序。

二、设计与分析

  在经过了第一次迭代大作业的折磨之后,我总结之前出现的问题,在之前的大作业中,我在类的设计方面做的并不好,每当更新一次大作业之后,我总是要做不少的改动,甚至几次直接重写整个项目,这给我带来了不小的麻烦,同时花费了我很多的学习时间,然而结果却总是不如意,几次和满分就相差那么几分,但是却始终得不到。并且在之前的大作业中,我发现每当我过几天再看程序的时候,往往会不记得写的是什么意思,这导致我总需要花一定的时间去阅读之前写的代码,这一点同样花费了我不少的时间,这些即吃里又不讨好,而吸取了上次大作业迭代的经验之后,我在写这次迭代大作业之前先是花了更多的时间去思考如何构建类,并且明晰了类与类之间的关系之后我才真正开始写代码,并且在写代码的过程中,我还时常在代码后面添加注释,以方便后续的阅读和修改,而这次类的设计较为万山也带来了巨大的好处,在写第二次的迭代的时候,相比起第一次迭代,我的代码相比于第一次迭代时提交的代码只多出了30行左右,从第一次迭代的650行到第二次迭代的680行,这也让我体会到了类设计在大项目中的重要性。

这是我在开始写之前大致写的类图

在这个时候我一共设计了12个类,虽然存在一定的问题,但是已经偏向于完整的了,首先我是想着先做一个最大的父类 设备类(把所有电路中的电器元件都视作设备),这样有利于使用多态,不过过多使用继承容易导致一旦父类修改了,子类就很容易需要大改的情况。所以当时我在写这个类的时候花了很多时间进行思考,当然结果是好的,在之后的编写中,这个类基本没有什么修改的。其下面分为了控制器类,例如电压调速器和开关等等。而另一个即是电器抽象类,作为所有电器的父类,而在这个父类之下我又将不同种类的电器的类别分类做了各自的抽象父类,便于后续添加一些同种类的电器,就比如第一次迭代就有的日光灯和白炽灯的区别,不过当然这里其实没必要分得这么细,我这么写其实是考虑到加入之后加入一些比较特殊的电器的情况,所需要设置的属性就不太一样了。除此之外,我在设备抽象类下还写了另一个子类,引脚类,作为每个电路元件的引脚。而右上角的两个类分别为控制类和链接类,前者控制电路的操作,比如指挥链接类将电路中的各个元件进行连接,以及根据输入信息对元件进行修改,比如开关的开关或者连续调速器设置参数。

下面这张图是我在写完了第二次迭代之后的类图

我在其中加入了电路抽象类,其下为串联电路类,并联电路类。并且我把原来设计类图中的设备类之上添加了电子元件类,这考虑到添加的电路类并不算是一个设备,而且将引脚划分为电子元件类会合理一些,同时设备类在程序最后都要输出各自的信息,就可以直接使用多态输出信息了。

比如下面这个输出方法。在设备类中设置一个抽象方法display(),而其子类的所有的控制器以及设备都会输出相关的信息。

public static void show(LinkedList<CircuitMember> members){for(CircuitMember member : members) if (member instanceof Equipment) ((Equipment) member).display();
}

在这个类图中也可以看到我添加了一个电源类,设计这个类的时候我是考虑到假如输入电压不是220v的时候那要根据不同的电源输出不同的电压,虽然这几次迭代大作业中看老师的题目描述感觉不太可能出现这种情况,但是设计了这个之后我觉得这一套类的设计更加合理了一些,并且在设计这个电源类其实有利于我所编写的程序运行,因为我所编写的程序其实最重要的部分就在于不同电子元件的连接上,我的思路是把所有的电路元件连接好之后只要从初始端口输入电压之后,整个程序就会真的跟一条电路一样自行根据设计好的运行方法运行。因此我需要一个电源类作为整个电路的初始输出端口。

powersourse.Run();

所有的电路元件只需要这一行输入电压之后就会自行运行好,所以这个电源类的设计其实会使程序更加合理。

上面这张图是使用SourceMonitor后的检测结果,在这张图中,可以看到LinkCenter类的行数最多,达到了113行,语句数量也达到了97行,因为其中连接电路的部分占了大头,但是其中的注释占比还是不够高,只有10.6%,这也是其中的一个缺陷,其中方法的最大的复杂度达到了9,这个最大的复杂度就出现在了下图的findAllMembers方法中,因为这个方法是通过输入电路信息创建所有电路元件的,其中使用了switch语句根据元件名称的首字母创建对象,因为有9种元件所以复杂度为零,这个地方在之后也应该进行修改降低其圈复杂度。

而其实从整个统计图上来看,最为复杂的地方就是LinkCenter类,其中连接电路部分使用了不少的循环语句和if语句,在日后写的过程中有必要对其进行修改,做出进一步的优化。

其次再看其注释占比例,其实虽然平均下来只有8.6%,但是相比第一阶段的大作业迭代要好了很多了,至少在大部分比较复杂的方法后加上了注释,这至少帮助我在写第二次迭代的时候要方便不少了,至少不至于像之前那样阅读大量源码才能想起来之前的写法了。

三、踩坑心得

  1.在第一次迭代之前设计类的时候没有考虑到串联电路和并联电路这种可能,所以在第一次提交的时候遇上了电路种开关在电器之后的情况的时候出了错误,因为我的设计思路是电路从输入端自行运行到最后,当断路开关在电器前面的时候电路就不会往后输入电压了,但是当断路开关在电器后面的时候就无法侦测到这种情况了,就好比一个人走在一条单行道上,当前面有一堵墙(断路开关)的时候,他就往前走不了了,墙之后的蛋糕(电器)他就吃不到了。而如果这堵墙(断路开关)在蛋糕(电器)后面呢,他能先吃到蛋糕之后再遇到墙,对比到电路种这就导致了再电路断开的情况下电器却成功运行了。所幸在我自己设置测试点的情况下,发现了这个问题,于是添加了一个串联电路类处理电路中的电子元件的断路情况,就好比有一个人A是一条路的管理者知道路中的各种情况,一个人B走在这条路上,A会在B走进这条路之前替他看看这条路能不能走,能走B就可以经过这条路上的所有电器,不能走A就阻止B进入这条电路,这样B就不会接触到这些电器,自然就不会出现断路情况下电器运行的情况了。

  2.在这套题目的要求情况下,最后程序要按照顺序输出电器的信息,但是这套题目中的电器种类非常多,一共7种,我想通过实现Comparable接口中的compareTo方法实现排序方法,但是如果按照循环的方法写,其复杂程度一定会很高。而且代码行数肯定也不会少,所以我在思考后想到了一种方法

public int compareTo(CircuitMember e) {final String EquipmentName = "KFLBRDA";int index1 = EquipmentName.indexOf(getName().charAt(0));int index2 = EquipmentName.indexOf(e.getName().charAt(0));int result = index1 - index2;if(result == 0) result = getName().compareTo(e.getName());return result > 0 ? 1 : -1;
}

通过设计一个字符串,其中包含所有电器的首字母然后对比两个对象的首字母在字符串中的下标,然后通过比较下标的前后,然后返回1,-1 ,0,当首字母相等的时候,就使用原字符串的compareTo方法返回值,这是为了处理对于当两个对象为同一种设备的情况(设备名字首字母相同,但编号不同.在这种方法下,设备的排序方法就会简单很多,并且只使用到了一个if语句(当下标相同时),同时相比较大量的循环语句而言,这样的代码运行方法会更快,在后续的迭代种如果添加了一些新的设备的时候,就只需要在字符串最后添加新设备的首写字母就可以了,而不是像循环语句中的那种还要添加新的循环语句,从可拓展性而言,远比采用循环方法更好。这一点虽然不算是踩坑点,但是作为一个心得更好。

 

四、改进建议

  我认为可以添加电器短路的情况设计,设置电器短路,当电器短路,电器本身不工作,但电流会通过电器。

五、总结

设计类的时候要考虑更加全面周到:设计类的过程十分重要,这个阶段为后续程序的运行打下基础的部分,所以在设计类的时候,要考虑周到,从自己的思路角度思考代码运行的时候会遇到什么问题,并且该如果在设计类的过程将这个问题给避免掉,就比如踩坑心得中第一点说的忽略了串联电路中开关在设备后面并且断路的情况。

要继续养成添加注释的习惯:持续养成添加注释的习惯,这不仅是在面对大项目的情况下使代码更加通俗易懂的方法,也是对代码进行修改时候的利器

面对一些大循环代码时要思考能不能用另外一种更高效的方法替代:就如心得中第二点中的一样,当面对一些需要多重循环的代码时,要勇于思考一些新的方法去避免这种大循环。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ryyt.cn/news/41990.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

【转载】GDB高级技巧:边Debug边修复BUG,无需修改代码,无需重新编译

调试是每个程序员都逃不过的宿命! 程序调试是一件非常考验耐心的事情,因为调试过程中经常会需要反复的修改源码,重新编译、重新部署、重新运行,这个过程通常是非常枯燥和繁琐的。尤其对于大型项目,光是编译可能需要几十分钟,甚至几个小时,部署过程则可能更为复杂漫长! …

【转载】C 语言有什么奇技淫巧

快速范围判断 经常要批量判断某些值在不在范围内,如果 int 检测是 [0, N) 的话: if (x >= 0 && x < N) ...众所周知,现代 CPU 优化,减分支是重要手段,上述两次判断可以简写为: if (((unsigned int)x) < N) ...减少判断次数。如果 int 检测范围是 [minx,…

出现java.lang.NoSuchMethodError: xxx.xxx.xxx.xxxDto.getxxx()Ljava/lang/String

参考博客:https://blog.csdn.net/weixin_43530696/article/details/115732807 修改字段后JPA自动生成的代码未及时更新。删除JPA相关jar包后,重启项目。 直接rebuild项目 重启 ,如果没有用的话,先invalid Chches清缓存之后,再重启动项目一般即可解决您的资助是我最大的动力…

客户价值观分析

客户价值分析 一、实验目的与要求 1、掌握使用numpy和pandas库处理数据的基本方法。 2、掌握使用RFM分析模型对客户信息进行特征提取的基本方法。 3、掌握对特征数据进行标准化处理的基本方法。 4、掌握使用Sklearn库对K-Means聚类算法的实现及其评价方法。 5、掌握使用matplot…

当接口出现404问题时,可能出现问题的原因如下

当我们在进行网络应用开发或者使用API时,经常会遇到后端接口返回404(Not Found)错误的情况。这种错误通常意味着客户端请求了服务器上不存在的资源,可能由多种原因造成。下面将详细介绍这些原因,并给出相应的解决方法。 1. 资源路径错误一个常见的原因是客户端请求的资源路…

我的大学

不断发问 在走进大学,时不时问一问自己诸位在校,有两个问题应该自己问问,第一,到浙大来做什么?第二,将来毕业后要做什么样的人?科学的方法,公正的态度,果断的决心我们的心中一定另有答案,或清楚或模糊。 每个人都应该想一想才不会虚度自己在大学中的时光。 关于学习骐…

如何应对缺失值带来的分布变化?探索填充缺失值的最佳插补算法

本文将探讨了缺失值插补的不同方法,并比较了它们在复原数据真实分布方面的效果,处理插补是一个不确定性的问题,尤其是在样本量较小或数据复杂性高时的挑战,应选择能够适应数据分布变化并准确插补缺失值的方法。 我们假设存在一个潜在的分布P,从中得出观察值X。此外,还绘制…