面向对象——前三次PTA作业集总结
前言
本阶段共完成了三个题目集,分别是航空器配载与货运管理系统1、2、3;即是对航空器配载与货运管理系统进行了初始设计,并且随着学习知识点增多、要求增多而进行了循序渐进的改进、优化。
三次作业各有异同,分别以不同形式展开,以下是三次作业集的知识点、题量、难度等情况。
| 航空器配载与货运管理系统 | 知识点及分析 | 题量 | 难度 |
| 一代 | 基础类设计(类的封装、构造方法等)、数组操作、排序算法的简单实现 | 要求较少,题量代码约100行 | 低 |
| 二代 | 集合框架、列表操作、业务逻辑分离、ArrayList集合框架,多种判断逻辑共同实现 | 要求适中,题量代码约200行 | 中 |
| 三代 | 多模块协作、数据校验、重心计算。处理旅客行李、前后货舱、重心计算等更复杂的业务场景 | 要求较多,题量代码约300行 | 中上 |
本文将结合三次作业源代码、类图结构、MetricsReloaded、代码运行测试情况对三次作业分别进行系统性总结,分析复杂度循序渐进的变化、代码设计、踩坑心得、学习收获等。
设计与分析
第一次作业
类图

复杂度分析(使用MetricsReloaded)

可以看到,绝大多数方法:v(G)(圈复杂度) = 1
而CargoSorter.sort(Cargo[], int):v(G) = 4(全文件最复杂的方法排序方法里有 3 个分支 / 循环)但v(G)仍<10的安全阀值(PS.作业要求的是选择排序,复杂度高不可避免)。
总的来说,整体复杂度极低,方法职责高度单一,结构化程度很高(所有方法的 iv(G) ≤ 3)
小结(一)
第一次作业是典型的入门级面向对象练习,代码简单,通俗易懂。本题让初学的我理解了各个类之间的关系与职责的精细划分,让我学会了类的设计,整体而言收获许多,初次设计让我脑海里真正有了面向对象设计程序的框架,也让我对本系统后面的改进更加方便,更加快速,更加舒服。
(PS.由于先前有过C语言经验,各类算法对我而言不是问题)
第二次作业
类图

依赖关系:Main 类依赖 Flight、CargoCompartment、LoadDispatcher、InputValidator;Flight 依赖 CargoCompartment;CargoCompartment 依赖 Position、Cargo;LoadDispatcher 依赖 Cargo、CargoCompartment;InputValidator 无任何依赖,属于独立工具类。
复杂度分析

小结(二)
第三次作业:
类图

复杂度分析

小结(三)
采坑心得
第一次作业踩坑记录
![]()
在未修正的原始代码中,我使用了 nextLine()nextDouble() 、nextDouble() 、nextInt() 混合输入的方式:
String flightNo = sc.nextLine();
double maxWeight = sc.nextDouble();
int n = sc.nextInt();
sc.nextLine();
在货物录入循环中,又加入了条件判断的换行处理:
if(i<n-1) sc.nextLine();
这种写法会导致输入流读取错乱。当输入数据格式严格、无多余换行时,程序会出现读取不到数据、跳过输入、数组越界等问题,最终触发非零返回。
第二次作业踩坑记录

一、排序后使用 indexOf 导致货舱匹配错误
在未修正的原始代码中,我先对货物集合进行排序,再通过 indexOf 获取原始下标:
int index = cargos.indexOf(cargo);
String targetId = targetCompIds.get(index);
这一写法存在严重逻辑错误。排序后的货物顺序已经改变,indexOf 获取到的下标不再是原始输入顺序的下标,导致货物与目标货舱完全不匹配,出现货物装错舱位的问题。
二、输出格式多余文字导致判题错误
System.out.printf("货物[%s 重量:%.1fkg] → 装入货舱[%s] 失败 (超载)\n");
原题输出格式表述:装载失败:货物[名称 重量:重量值kg] → 装入货舱[货舱ID] 失败 (超载)。非得把(超载)删掉才给过,何意味,这个坑谁都得踩一脚😠!并不是自身问题。
第三次作业踩坑记录

一、输入范围校验错误,导致合法数据被误判拦截
throw new IllegalArgumentException("输入必须在 " + 1 + " 到 " + high + " 之间!");
依旧何意味,本应该是最小到最大之间,题目也没有给失败的案例,只能自己猜哪里有问题,搞心态,搞红温😡。
二、输出格式多余文字导致判题错误
System.out.printf("!!! 警告:[1]剩余容量不足(当前载重%.1fkg/最大载重量%.1fkg),请重新分配或减轻重量!\n");
首先,当前载重后面的kg不要,最大载重量这几个字不要,没有读懂题目给的输出格式,算是我自己的问题。
三、LoadDispatcher 排序逻辑错误且完全未使用
if (list.get(j).getId() > list.get(j + 1).getId())
Main函数中我使用的是增强for循环,没意识到这个排序根本没有用到,按理来说题目没有给明确要求,那么我就按装载顺序输出了,这个排序循环相当于是冗余了。
踩坑小结
踩坑挺多的,也不止列出来的这么多,代码仍有瑕疵,除了第一次一些nextline()的使用外,基本上是逻辑与格式的错误。在学习了Integer等类,parseInt等方法后基本没有输入方面的问题。
踩坑感觉是很正常的,极少情况下代码是一次写对的,难免有bug要修改,难免有逻辑要优化,在三次作业中循序渐进地去完善这个系统,我认为是编写这个系统的正确方式,要慢慢来,一次性不要想太多方面,要严谨的来,按计划得来,出错不要紧,要有一个纠错的心态,踩完坑爬上来,自己的收获会是巨大的。
改进建议
代码结构改进
三份代码中Main主方法普遍偏长,特别是第三次main方法代码行数超过120行,不符合单一职责原则。可以将输入模块、打印模块、计算模块拆分至独立工具类,减少主方法臃肿程度。
第一次、第二次排序方法为手写简单排序,算法效率低,数据量大时排序速度慢。可以使用JDK自带工具类Collections.sort结合比较器完成排序,减少手写循环出错概率,降低圈复杂度。(但是题目要求不让用😖)
健壮性改进
目前代码仅对输入数值做非负判断,未对空字符串、特殊字符、null值进行校验。后期可以增加字符串校验、对象非空判断,防止空指针异常。浮点数可以比较统一采用误差范围判断,杜绝精度丢失问题。
扩展性改进
第三次作业重心范围硬编码写在代码中,应当提取为静态常量,便于后期修改。飞机空机重量、力臂、货舱力臂全部常量化,提高代码可维护性。未来若新增货舱、新增机型,仅需修改常量无需改动业务逻辑。(其实写代码的时候省懒了)
总结
教师、课程、作业、实验、课上及课下组织方式等方面做的非常好,教师有问必答,群里回复及时,作业很有创新,三次作业循序渐进,业务连贯,非常适合入门者学习,实验非常有实验精神,课上老师讲课激情,也会进行bug调试,排查流程,修改思路,带写代码,课下与同学们打成一片。
建议后期作业继续沿用同一业务场景迭代升级,让学生体会软件迭代开发流程。建议课堂增加代码度量、代码优化、类图绘制教学,让学生不仅会写代码,更会分析代码质量。

浙公网安备 33010602011771号