pta作业集 1~3 的总结性 Blog

航空器配载与货运管理系统 作业集1~3 阶段性总结报告

一、前言

PTA 作业集的第一部分结束了,我认为主要是考察类设计中的类间关系设计。

三次作业整体情况:

1. 知识点
面向对象封装、单一职责原则、类职责划分、组合 / 聚合关系、ArrayList 集合、冒泡排序、输入校验、力矩与重心计算等等。

2. 题量
代码量逐步增加,类数量从 5 个加到 10 个左右。
(1)第一次:题量不大,4 个类和 1 个 Main 类,不带空行的话代码量也就 120 多行。
(2)第二次:在第一次的基础上增加了多货舱管理、货舱位置网格,类的数量到了 7 个,不带空行的代码量将近300行,还增加了货舱查找、装载校验、多条件状态输出等,比第一次复杂了不少。
(3)第三次:在前两次的基础上,加入了旅客和行李类、载重平衡与重心计算,同时增加了输入校验,类的数量达到了10个左右,代码量也扩展到了300行以上,各个类之间关系更复杂,要考虑的东西也比较多。

3. 难度
整体呈阶梯式上升。
(1)第一次作业:难度较低,根据题目给出的类图,理清类与类直接的关系差不多就能完成,主要难点是第一次遇到 Scanner 输入的空行处理。
(2)第二次作业:难度中等,重点是多货舱管理,还有货舱查找、装载校验、货舱状态与航班整体状态的双重判断,对单一职责原则的要求更高,这一次的Scanner 输入对我来说也是一个问题,因为和第一次并不是完全相同。
(3)第三次作业:难度较高。一方面需要处理旅客、行李、双货舱的许多数据,另一方面要按照公式一步步算很多数据,同时还要对所有输入做合法性校验,非法输入要直接终止程序,对代码的完整性要求很高,一个地方写错可能整个程序都会出错。
第三次作业主要就是其中的两三个测试点的边界情况对我来说很难发现,找了很久试了很久(大概两三天)才通过全部测试点。

我认为最好是先画好类图和时序图,理清类与类之间的关系再开始写代码,不然很容易越写越乱。
单论写代码可能主要是耗时,理清所有关系和逻辑后也不算特别特别难,通过所有测试点对我来说才是最难的一步。

4. 收获
说实话,在还没做这个大作业之前,我对类之间的关系不是很熟悉,尤其是组合和聚合,这两个关系在写构造方法 /get/set 方法上的区别我之前一直不太清楚,再涉及 ArrayList 我就更搞不清楚了。
而这次迭代式大作业确实让我对这方面清晰了不少,因为如果不彻底搞懂这个,设计类与写代码时就很容易乱乱的。
同时我也理解了为什么老师一直强调 SRP,比如作业 3 里,把输入校验、计算、输出、业务逻辑分开,每个类只做一件事,不仅写的时候思路清晰,后面调试和修改的时候也方便很多。

二、设计与分析

本部分对三次作业的代码质量、类结构设计、程序运行流程进行完整分析,结合 SourceMonitor 报表UML 类图时序图展开说明。

(一)作业1:基础航班货运配载系统设计与分析

1. 代码质量分析(SourceMonitor)

image

作业 1 是 124 行有效代码,包含 5 个核心类:
平均每个类有 4.8 个方法,说明类的职责划分还可以,没有上帝类。
最大圈复杂度为 4,是三次作业里较低的水平,说明当时写的方法里分支判断不多,逻辑相对简单,也没有把复杂逻辑都堆在 Main 里。
平均每个方法的语句数为 2.08,说明方法都控制得比较短,没有写很长的大方法,基本做到了单一职责。
不过当时写的时候,我没养成写注释的习惯,所以 Comments 占比为 0,而且一开始把输入和输出逻辑直接写在 Main 里,后来才意识到要拆分,这也是后面作业改进的方向。


2. UML 类图分析

diagram-14915696152393662848

LoadManifest类专门管理货物清单和总重量计算,CargoSorter类只负责冒泡排序,我当时一开始想把排序逻辑直接写在LoadManifest里,后来想到老师说的 “一个类只做一件事”,就单独拆成了排序类,这样后面要改排序规则的话,不用动清单类,这也是我第一次深刻体会到 SRP 的好处。
类之间的关系也很明确,Flight和LoadManifest是一对一关联,LoadManifest和Cargo是聚合关系(一个清单可以有多个货物),LoadManifest依赖CargoSorter完成排序,没有多余的耦合。


3. 时序图分析

diagram-15823323225188191654

当时写代码时,我踩过一个 Scanner 的坑:输入完货物数量后,直接用nextLine()读货物名称,结果读到了空字符串,时序图里的输入顺序提醒了我,必须在读取数字后用scanner.nextLine()吸收回车。


(二)作业2:多货舱配载管理系统设计与分析

1. 代码质量分析(SourceMonitor)

image

随着功能扩展,作业 2 的代码量增加到了 273 行,类数也扩展到了 8 个。
平均每个类的方法数为 5.63,比作业 1 略高,但我还是尽量一个类只做一件事,新增了CargoCompartment、InputValidator、Input、Output这些类,把输入、校验、输出都单独拆分了。
最大圈复杂度依然是 4,和作业 1 差不多,说明虽然功能变复杂了,但我并没有把东西都堆在一个方法里。


2. UML 类图分析

diagram-3424261099342286234

这张类图是我对组合、聚合关系理解最深刻的一次:
CargoCompartment和Position是组合关系:我一开始不太清楚组合要怎么写,后来想到老师讲的“整体和部分同生共死”,才明白要在CargoCompartment的构造方法里new Position。
CargoCompartment和Cargo是聚合关系:货物可以独立存在,作为参数传入货舱类的构造方法。


3. 时序图分析

diagram-3437741260135701914

作业2流程比作业1复杂很多,时序图对梳理逻辑顺序就比较有用了。


(三)作业3:航空器载重平衡与重心计算系统设计与分析

1. 代码质量分析(SourceMonitor)

image

作业 3 是三次里功能最复杂的,代码量到了 331 行,类数也增加到了 11 个,但整体的代码质量反而更优了:
平均每个类的方法数降到了 3.82,是三次里最低的,说明类的职责划分更细了。
最大圈复杂度降到了 3,也是三次里最低的,核心原因是我把所有计算逻辑都放到了WeightBalanceCalculator里,Main 类里几乎没有复杂的分支判断。


2. UML 类图分析

diagram-13357936960570678294

这次比第二次主要添加了以下类:
Passenger和Luggage是组合关系:旅客创建时会在内部new Luggage。
WeightBalanceCalculator是纯工具类:没有成员变量,所有计算方法都是静态的,依赖Flight对象传入数据。
InputValidator类把所有输入校验都统一了:负数校验、范围校验都放在这里,输入的时候直接调用。


3. 时序图分析

diagram-14177888747610251222

作业 3 的流程是三次里最复杂的,时序图帮我理清了关键的校验和计算顺序:
输入校验要放在最前面,读每个数据的时候都要先调用InputValidator校验,发现负数或超出范围就直接退出。我一开始是等所有数据输入完再校验,结果就发现前舱装不下得重新输入。
载重平衡计算一定要按步骤来,先算旅客总重,再算货舱总重,再算总力矩、重心、% MAC,顺序错了肯定不行。


三、踩坑心得

这个当时做pta的时候忘记截屏记录了,但是大致还记得遇到了哪些问题和坑。

(一)作业1踩坑心得

这次作业比较简单,而且测试点也没太为难人,所以主要问题也是主要花时间的地方就是Scanner 换行吸收问题。
刚开始用单独的一行scanner.nextLine()吸收回车,后来发现我容易忘记写,就上网查了一下,找到一个略显麻烦但是可以避免遗忘的方法,就是直接无论什么输入,外层都套个nextLine(),再用parseInt和parseDouble。
在第一次作业中输入部分全都是一行一个数据的情况下,这个方法是可以解决问题的。

image


(二)作业2踩坑心得

1. Scanner 读取输入问题
最开始我还是用第一次作业中研究出来的方法(无论什么输入,外层都套个nextLine(),再用parseInt和parseDouble),结果不管用了,我又花了不少时间研究,发现是因为第二次作业的输入部分中一行有多个数据(用空格分隔开),而第一次作业输入全是一行一个数据,那么就不能一劳永逸了,需要有新的方法。
于是我又花了不少时间来找对应的新方法,最后找到了(虽然不知道以后遇到新的情况还能不能通用),目前我总结了这两种情况对应的方法:

image

2. 题目给的输出格式和真实的测试点中有些不一样
题目给的输出是“失败 (超载)”,但是实际测试中是“失败”。

image

这个可能是题目出了一点小错误?或者是老师特意留的小巧思?
第二次作业主要就是在这个上面花了很多时间,我一直以为是有什么逻辑错误,改来改去就是过不了,最后才发现是题目给的输出有点问题,确实很难发现。。。

3. 输出格式不匹配

  • 问题:空格、小数位数、提示文字与样例不一致
  • 原因:主要就是要输出的东西太多了,很容易漏个空格什么的,但是格式错误还是比较容易发现,这个坑已经是家常便饭了。

(三)作业3采坑心得

1. 输入的同时就必须要校验数据合法性
我一开始是等所有数据输入完再校验,结果好几个测试点都过不了。
后来又仔细分析了一下题目里对数据输入有误的处理的相关描述,才明白是一边输入一边校验。

2. 前/后舱货物容量不足的两个测试点总是不对

  • 问题1:我最开始是等所有货物装完再判断容量不足,这两个测试点就一直过不了。

image

其实这很明显不对,装货的for循环都结束了,才开始判断容量,这个if判断竟然在for循环外面,但是我最开始就是一直没发现。

image

  • 解决1:找了好久问题,最终还是发现了,应该是每装入一个货都要判断一下容量还够不够,如果不够直接结束整个程序。
    但是令人沮丧的是,我把这个地方改了之后,这两个测试点还是没通过。那么说明这个地方还有其他问题,又是花了很多时间来找,最后发现了问题2。

  • 问题2:装入货物和判断如果装入该货物之后容量还够不够这两个顺序弄反了。

  • 解决2:要先判断装入这个货容量还够不够,如果容量够,再正式装入货物。而不是已经把货装进去了,再判断容量。

3. 第一个和第十个测试点总是不过

image
image

刚开始一直以为是配平判断要先按一位小数处理,再判断安全/危险,实际上并非这方面的问题,所以改来改去花了很多时间但是一直不对。
后来和其他同学一起研究了很久,发现想通过这两个测试点就不能排序,或者把排序放在最后。说实话还不是完全明白这是为什么。


四、改进建议

基于三次作业的设计与实现,提出可持续改进方案。

  1. 抽取工具类
    将输入、输出、重量计算封装为独立工具类,进一步降低 Main 类复杂度,而不是全放在Main类里,导致又臭又长。

  2. 适当增加必要注释
    我写pta的题目一直没有写注释的习惯,代码量少的时候还没什么问题,像第三次作业这样代码量长了一点,就容易忘记之前写的代码是什么作用。

  3. 命名要规范,至少保证易懂
    这一点不仅是为了写更好更规范的代码,也是为了自己写代码到后面还能记得前面写的是什么东西,血泪教训。

  4. 优化货舱分配逻辑
    目前的作业2和作业3都是用户指定目标货舱,其实可以增加自动分配货舱的逻辑,优先把重的货物装到还有剩余容量的货舱里,这样能充分利用货舱空间。

  5. 进一步拆分类,严格遵循单一职责原则
    虽然三次作业我都按SRP拆了类,但还是有些类的职责不够单一,比如:

  • 作业2里的Input类,既负责读航班信息,又负责读货舱和货物信息,后续可以拆成FlightInputReader、CargoCompartmentInputReader、CargoInputReader三个类,每个类只负责读一种数据。
  • 作业3里的WeightBalanceCalculator,虽然是纯计算类,但里面同时处理了旅客力矩、货舱力矩、重心计算,后续可以拆成PassengerMomentCalculator、CargoMomentCalculator、CGPercentCalculator三个小工具类,每个类只做一步计算。

五、总结与反思

通过这三次航空器配载与货运管理系统的迭代作业,我算是真正把面向对象程序设计从听懂了变成会用了。从最开始只会照着类图写代码,到后来能自己找类间关系、排查测试点,整个过程虽然踩了很多坑,但也收获了很多东西。

首先,我最大的收获就是彻底搞懂了类之间的关系。
以前我对组合、聚合分不太清,甚至觉得不完全弄懂也无所谓,但这几次作业让我明白:类与类之间怎么关联、对象在哪里创建,直接决定代码能不能写对。特别是货舱与位置、旅客与行李这种组合关系,必须在内部创建,我现在已经能熟练地写出来,也知道为什么要这么写。

其次,我真正理解了单一职责原则 SRP 不是死板的规矩,而是真的有用。
一开始我总喜欢把逻辑往 Main 里塞,后来拆成输入类、输出类、校验类、计算类之后,代码明显清晰很多,找 bug 也快很多。尤其是第三次作业,计算逻辑那么复杂,如果不把各种计算单独抽到计算类里,我不敢想象有多难写。

第三,我的输入输出、调试、找 bug 能力提升不少。
三次作业最难、最花时间的部分,几乎都在 Scanner 输入、格式问题、测试点不通过上。从作业 1 的换行吸收问题,到作业 2 的一行多数据处理,再到作业 3 的实时校验、容量判断,我从一开始完全懵,到后来也能自己总结一点方法。

下一步我还需要提高的地方

代码习惯还要继续改
我经常不写注释、命名不够规范,代码量一大就容易看不懂自己写的东西。以后必须养成写注释、规范命名、拆小方法的习惯,这是最基础也最重要的。

画图能力还要加强
我现在画类图、时序图还是不够熟练,经常要边写代码边补图。其实先画图再写代码会快很多,我后面会多练习先设计再写代码,而不是一上来就开始写。

对边界情况、异常处理考虑不足
作业 3 的好几个测试点都是因为我没考虑边界、没有提前校验才不过。以后写程序要养成先想异常、再想正常的习惯。

改进建议及意见

希望作业能更循序渐进
这三次迭代作业我觉得已经挺好的了,能让人一步步理解面向对象。如果能在作业开始前,先给一小节类间关系小练习,比如专门练组合、聚合、输入处理,可能会更好。

希望多讲一点调试技巧
我这次大部分时间都花在找 bug 上和过测试点上,老师上课如果不仅仅讲知识点和写代码,也讲讲怎么找bug怎么找边界情况,就更好了。

希望输入输出格式能更统一
像作业 2 里题目描述和实际测试点格式不一致,真的很耗时间。如果题目样例、格式描述能和测试点完全一致,我们能把精力放在逻辑上,而不是猜格式。

希望能有一些 “作业总结交流”
比如大家都遇到了什么坑、怎么解决的,互相分享一下,会比自己一个人闷头调两三天有效得多。

最后整体总结

这三次作业虽然难、虽然坑多、虽然调试很折磨人,但目前来看确实是我这学期收获最大的一部分内容。
我从不太会设计类,到现在能完成一套完整的题目,能自己设计能自己调试,我觉得也算有进步了。
未来我会继续多思考设计、多注意细节,把这几次作业学到的东西真正用在以后的学习和项目里。

posted @ 2026-05-18 14:05  byingzi  阅读(14)  评论(0)    收藏  举报