面向对象程序设计PTA作业集1~3总结
一、写在前面
本学期面向对象程序设计课程的三次PTA作业,以航空器配载与货运管理系统为核心,采用迭代开发模式逐步推进。从第一次作业的基础货物录入与重量统计,到第二次作业的双货舱管理与手写冒泡排序,再到第三次作业的旅客行李管理与航空重心配平计算,完整模拟了小型工程项目从需求分析到代码实现、调试优化的全过程。三次作业难度循序渐进,知识点覆盖类与对象、封装、组合聚合关系、静态成员、算法实现、数据校验等面向对象核心内容,让我在实践中逐步建立起面向对象的设计思维,也深刻体会到工程代码严谨性的重要性。
在本次总结中,我将从代码规模、类结构设计、复杂度分析、bug复盘等多个维度,对三次作业进行全面梳理,总结开发过程中的经验教训,提出后续的改进方向。所有统计数据均通过SourceMonitor工具生成,类图使用PowerDesigner绘制,完全符合课程作业总结的规范要求。
二、第一次作业:基础货物配载系统
2.1 作业要求与实现方式
本次作业要求实现基础的航空货物配载功能,包括货物信息录入、总重量统计以及简易配载清单的生成。我采用最基础的面向对象结构,将货物抽象为独立的实体类,通过航班类统一管理所有货物,最后由主程序完成输入输出流程。整体设计遵循单一职责原则,每个类只负责自己的核心功能,没有多余的耦合逻辑。
2.2 代码规模
第一次作业整体代码体量较小,结构简单清晰,完整代码规模统计如下:
从统计结果可以看出,本次作业总代码行数147行,有效代码122行,注释占比7%,空行占比10%,代码结构十分紧凑,没有冗余内容。
2.3 类图设计
本次作业的类结构十分简洁,仅包含三个核心类,完整类图如下:
其中,Cargo类负责存储货物的编号和重量信息,提供对应的getter方法;Flight类内部维护一个货物列表,实现货物的添加、总重量计算以及配载清单打印功能;Main类作为程序入口,负责处理控制台输入,创建对象并调用相关方法。
2.4 复杂度分析
使用SourceMonitor工具对本次作业代码进行复杂度分析,生成的方法复杂度报表如下:
从分析结果可以看出,所有方法的复杂度都处于较低水平,平均圈复杂度仅为1.88,没有复杂的嵌套判断和循环结构。这是因为第一次作业功能单一,业务逻辑简单,主要目的是让我们熟悉类的定义和对象的基本使用。
2.5 Bug分析
本次作业我仅提交一次就顺利通过了所有测试点,没有出现功能性错误。唯一需要注意的细节是浮点数的输出格式,最初我没有对输出的重量数值进行小数位数限制,导致部分测试点因为格式不匹配被扣分。修改为统一保留一位小数输出后,所有测试点全部通过。这次经历让我第一次意识到,线上评测对于输出格式的要求极其严格,任何细微的偏差都会导致评测失败。
三、第二次作业:多货舱货物管理系统
3.1 作业要求与实现方式
在第一次作业的基础上,本次作业新增了前后两个独立货舱的划分,每个货舱都有自己的最大载重限制和货架行列属性。同时要求手动实现冒泡排序算法,按照货物重量对货物进行升序排列,禁止使用系统自带的排序方法。
我新增了CargoCompartment货舱类来管理单个货舱的货物和载重信息,在Flight类中聚合前后两个货舱对象。新增LoadDispatcher工具类,专门负责实现冒泡排序算法,保证每个类的职责单一。这种设计方式既保留了第一次作业的原有代码结构,又实现了新功能的无缝扩展,体现了迭代开发的优势。
3.2 代码规模
随着功能的增加,本次作业的代码规模明显扩大,完整代码行数统计如下:
本次作业总代码行数334行,有效代码276行,相比第一次作业增长了一倍多,注释占比保持在7%左右,代码结构依然清晰。
3.3 类图设计
本次作业的类图在第一次的基础上进行了扩展,新增了货舱类和排序工具类,完整类图如下:
CargoCompartment类内部维护一个货物列表和当前载重变量,提供货物添加、载重检查和货物排序功能;LoadDispatcher类作为纯工具类,只包含静态的冒泡排序方法,不维护任何成员变量;Flight类持有前后两个CargoCompartment对象,统一管理两个货舱的操作。
3.4 复杂度分析
本次作业的方法复杂度分析报表如下:
可以看出,LoadDispatcher.bubbleSort方法和Main.main方法的复杂度相对较高。冒泡排序方法因为包含双层循环,复杂度有所上升;主方法因为需要处理大量的输入逻辑和流程控制,复杂度也略高于其他方法。整体来看,代码复杂度仍然处于合理范围,平均圈复杂度为2.25,没有出现逻辑过于复杂的方法。
3.5 Bug分析
本次作业我前后提交了三次才通过所有测试点,主要遇到了两个问题:
第一个问题是冒泡排序的边界条件错误。最初我将内层循环的终止条件写为arr.length - 1,而没有减去外层循环已经执行的次数,导致排序过程中出现数组越界异常,并且末尾的货物数据会丢失。修改为arr.length - 1 - i后,排序功能恢复正常。
第二个问题是货舱载重统计错误。最开始我每次计算总重量时都会重新遍历整个货物列表,在货物数量较多时会出现重复计算的问题,导致载重数值偏大。后来我在货舱类中新增了一个currentWeight成员变量,每次添加货物时实时更新该变量,彻底解决了统计错误的问题。
四、第三次作业:完整航空配载平衡系统
4.1 作业要求与实现方式
本次作业是前两次作业的最终升级版本,新增了旅客和随身行李管理模块,同时引入了航空专业的配平计算公式,需要计算飞机的空机重量、旅客总重量、货物力矩、整体重心以及重心百分比,并自动判定配载状态是否安全。此外,还要求实现严格的输入数据校验,对负数、非法类型和超出范围的数据进行拦截。
我新增了Passenger旅客类和Luggage行李类,实现旅客与行李的组合关系;新增InputValidator输入校验类,统一处理所有输入数据的合法性检查;新增WeightBalanceCalculator配平计算类,专门负责航空力学相关的数值计算。所有新增类都严格遵循封装原则,成员变量全部私有化,通过getter方法对外暴露数据。
4.2 代码规模
本次作业是三次作业中功能最完整、逻辑最复杂的一次,代码规模也达到了最大值,完整代码行数统计如下:
本次作业总代码行数701行,有效代码576行,相比第二次作业又增长了一倍多,注释占比8%,空行占比10%,代码结构依然保持清晰。
4.3 类图设计
本次作业的最终类图包含了所有实体类和工具类,完整展示了系统的结构和类之间的关系:
Passenger类内部组合一个Luggage对象,行李不能脱离旅客单独存在;InputValidator类提供静态的输入校验方法,对所有输入数据进行统一检查;WeightBalanceCalculator类使用静态常量定义所有航空标准参数,严格按照公式计算配平数据;Flight类聚合货舱和旅客列表,整合所有数据供配平计算使用。
4.4 复杂度分析
本次作业的方法复杂度分析报表如下:
从分析结果可以看出,WeightBalanceCalculator类的计算方法和Main.main方法的复杂度相对较高,平均圈复杂度为2.50。这是因为配平计算方法需要处理大量的数值运算和格式输出,主方法需要整合所有模块的功能,流程较长。整体来看,代码复杂度仍然在可接受范围内,没有出现逻辑过于臃肿的方法。
4.5 Bug分析
本次作业我前后提交了四次才通过所有测试点,是三次作业中调试次数最多的一次,主要遇到了以下几个问题:
第一个问题是Scanner重复创建导致输入流错乱。最开始我在每个输入方法中都新建了一个Scanner对象,本地运行正常,但提交到平台后会无故提示输入负数。经过排查发现,多次创建Scanner会导致输入缓冲区混乱,将Scanner改为全局静态唯一对象后,问题彻底解决。
第二个问题是printf百分号转义错误。在输出重心百分比时,我直接书写了%MAC,导致程序抛出格式转换异常。查阅资料后得知,printf中百分号需要用两个百分号转义,修改为%%MAC后,输出正常。
第三个问题是对象引用不一致。创建旅客对象后,忘记将其添加到航班的旅客集合中,导致统计旅客人数时始终为0。修正后,新增旅客时同步添加到航班集合,保证了数据的一致性。
五、采坑心得与改进建议
5.1 采坑心得
回顾三次作业的开发过程,我累计提交了8次,遇到的问题大多不是核心逻辑难以实现,而是细节上的疏忽和不规范。比如输入流的使用、格式化输出的转义、循环边界的控制、对象引用的一致性等,这些看似不起眼的小问题,却往往是导致评测失败的主要原因。
线上平台的评测机制十分严格,对于输出格式、数据精度、符号使用都有明确的要求,任何一点偏差都会导致测试点不通过。这让我深刻体会到,工程代码的编写不仅要实现功能,更要注重规范和细节。一个优秀的程序员,不仅要能写出正确的代码,还要能写出严谨、规范、易维护的代码。
5.2 改进建议
针对三次作业中暴露出来的问题,我总结了以下几点改进方向:
首先是代码结构方面,目前工具类全部使用静态方法,虽然调用方便,但扩展性较差。后续可以将部分工具类改为实例化方式,提高代码的可扩展性。同时,代码中存在大量重复的输出语句,可以封装为通用的打印方法,减少代码冗余。
其次是算法性能方面,本次使用的冒泡排序效率较低,后续可以优化为双向冒泡排序,减少无效循环次数。查找操作目前使用遍历方式,时间复杂度较高,可以改用哈希表存储,提高查找效率。
最后是异常处理方面,目前程序遇到错误直接退出,处理方式比较粗暴。后续可以自定义异常类,区分不同类型的错误,给出更友好的提示信息,提高程序的容错能力。
六、总结
通过三次迭代式的航空配载作业,我系统掌握了Java面向对象的核心知识,彻底理解了封装、组合、聚合等概念的含义和使用方法。我学会了如何将现实中的事物抽象为程序中的类,如何合理划分类的职责,如何通过对象之间的引用关系实现业务逻辑。同时,我也掌握了使用SourceMonitor分析代码复杂度、使用PowerDesigner绘制类图的方法,提高了自己的工程实践能力。
在学习过程中,我也发现了自己的不足之处,比如代码规范性不够、调试能力较弱、细节把控不严等。在今后的学习中,我会针对性地进行改进,多写多练,不断提高自己的代码质量和编程能力。同时,我也会更加注重代码的可维护性和扩展性,培养自己的工程思维,为今后的软件开发工作打下坚实的基础。
最后,感谢老师的悉心教导,三次迭代式的作业设计让我受益匪浅。希望后续的课程能够继续保持这种理论与实践相结合的教学方式,让我们在实践中不断成长。