PTA8-9总结:航空货运管理系统的简易实现

一、前言

两次题目集均是围绕“航空货运管理系统及其迭代”展开。题目集8、9重点考核面向对象设计原则中的单一职责原则、里氏代换原则、开
闭原则以及合成复用原则。题目8是构建了基础框架,而题目集9则是在此基础上添加了客户类型,货物类型和支付方式。难度很适合,虽然有难度但是努力还是能够做出来。

二、设计与分析

第一次航空货运管理系统题目的设计与分析

设计:

设计的类图如下:

image

1.基础实体类(People 及其子类):
People(抽象类):定义所有人物角色的公共属性(姓名、电话、地址),有构造方法初始化属性,以及属性的 getter/setter 方法。
Consumer(消费者:表示客户信息,继承自 People。有code(客户编号)。关联订单(cargoOrder),记录下单客户的身份信息。
Sender(发件人):表示货物的发件人信息,继承自 People,无新增属性。在 deliveryInformation(订单信息)中记录发件人详情。
Recipient(收件人):表示货物的收件人信息,继承自 People,无新增属性。在 deliveryInformation(订单信息)中记录收件人详情。
2.核心业务类
Cargo(货物):表示单个货物的信息,包括实际重量和体积重量,并计算计费重量和运费。
Flight(航班):表示航班信息,记录航班的基本信息和最大载重量。在 deliveryInformation 中关联订单和航班,验证订单总重量是否超过航班载重。
cargoOrder(货物订单):表示一个货物订单,包含客户信息和多个货物条目,计算订单总重量和总运费。
deliveryInformation(订单信息):封装完整的运输订单信息,包括发件人、收件人、航班、货物订单等。用于展示和验证运输可行性。
3.系统管理类
transportationSystem(运输系统,抽象类):作为运输系统的抽象基类,便于扩展。
airTransportationSystem(航空运输系统):表示航空运输系统,负责展示订单信息,并隐含验证航班载重的能力,打印订单详情、货物明细及运费信息。
4.工具类与常量类
Constant(常量类):存储运费计算的固定费率(35、30、25、15 元 /kg),使用 static final 修饰,全局可访问,提高可维护性。
5.支付相关类(抽象与实现)
Payment(支付抽象类):定义支付行为的抽象方法 Pay(),规范支付逻辑的接口。
实现类:
WechatPay:微信支付实现。
AliPay:支付宝支付实现。

sourceMonitor分析如下:

image

自我分析:
  • 方法复杂度不均衡:“Maximum Complexity” 为 7 ,“Average Complexity” 仅 1.16。说明代码中方法复杂度差异大,复杂方法可能难以理解和维护。
  • 类与方法数量关系:“Classes and Interfaces” 有 15 个 ,“Methods per Class” 平均 4.53 ,类中方法数量较多。可能导致类的职责不够单一,增加类的维护难度。
  • 总结:代码结构与复杂度、可读性上均存在不足,需重构复杂方法、优化类设计,增加注释。

第二次航空货运管理系统题目的设计与分析

设计:

设计的类图如下:

image

  1. deliveryInformation(配送信息类):聚合订单相关的所有信息,作为核心数据载体。:通过构造函数和Getter/Setter管理订单的关联信息。
  2. Flight(航班信息类):存储航班的详细信息及运力限制。:提供航班基础数据,可能用于后续的货物载重校验。
  3. Payment及子类(支付类):抽象支付方式,支持多策略支付。
  4. 子类:WechatPay(微信支付)、AliPay(支付宝)、CashPay(现金支付)。
  5. cargoOrder(货物订单类):管理订单中的货物列表及运费计算。计算总重量(getTotalWeight)和总运费(getTotalFreight)。根据货物类型、重量区间和客户类型(个人/企业)动态计算费率及折扣。依赖Constant类中的费率,通过getRateTableByWeight匹配不同重量区间的费率。
  6. Constant(常量配置类):集中管理费率常量:普通货物(Normal)、危险品(Dangerous)、加急货物(Expedite)在不同重量区间的费率。
  7. ConsumerType及People相关类(人员管理类)。
  8. ConsumerType枚举:定义客户类型(Individual个人 / Corporate企业)。
  9. People抽象类:基类,包含姓名、电话、地址等通用属性。
    子类:
    Consumer(客户):添加客户编号(code)和类型(consumerType)。
    Sender(发件人) / Recipient(收件人):继承People,无额外属性。
  10. airTransportationSystem(运输系统展示类):格式化输出订单详情。通过Show方法打印客户信息、航班等。
  11. Cargo(货物类):管理货物属性,体积计算及计费规则。

sourceMonitor分析如下:

image

自我分析:
  1. 代码复杂度方面
  • 方法复杂度不均衡:最大复杂度 Maximum Complexity 为 6 ,平均复杂度 Average Complexity 为 1.22 ,差距较大。这表明代码中存在部分方法逻辑极为复杂,包含大量条件判断、循环嵌套或方法调用,不利于理解、测试和维护。
  • 代码块深度问题:最大代码块深度 Maximum Block Depth 为 4 ,平均代码块深度 Average Block Depth 为 1.59 。较深的代码块意味着代码逻辑嵌套层次多,理解和调试难度增大,容易出现逻辑错误,需要审视代码结构,优化嵌套逻辑。
  1. 代码可读性方面
  • 注释比例较低:含注释代码行百分比 Percent Lines with Comments 仅为 3.6 ,说明代码注释严重不足。需及时补充注释,提升代码可读性。
  1. 代码结构方面
  • 分支语句占比较高:分支语句百分比 Percent Branch Statements 为 7.0 ,意味着代码中条件判断语句较多,这可能使代码逻辑结构不够清晰,增加了代码理解和维护的难度,应该简化代码结构。
  • 类与方法数量关系:类和接口数量 Classes and Interfaces 为 18 ,平均每个类的方法数 Methods per Class 为 3.83 ,整体类和方法数量较多,应该进一步梳理类的职责,优化代码结构。
  1. 总结:代码复杂度、可读性和结构方面存在不足。后续需对高复杂度方法进行重构,降低代码块深度;增加注释以提高可读性;优化分支语句和类的设计,使代码结构更加清晰合理。

三、踩坑心得

  • 应在写代码之前先把类间关系和每个类的功能决定,不然等到写代码时才会发现有些类的作用并不单一,而且可能有所疏漏,后续迭代也会很困难。像Cargo中的getFreight(),getRate()方法,一开始放进其他类里,发现在使用时无法调用,于是放进Cargo中,结果迭代时因为要打折,导致还需要将这两个方法移除Cargo中。
  • 写代码的时候要细心。无论是客户的类型还是货物的类型,我都在使用equals()时因为大小字符不同而导致结果出错,而且有些地方因为遗漏了一些数据时也导致最后计算运费时出错。

四、改进建议

  • cargoOrder 类既负责管理货物列表、计算总重量和总运费,又处理不同客户类型的运费折扣及根据货物类型和重量获取费率等,职责过多。可将运费计算逻辑(含折扣计算、费率获取 )拆分到独立的运费计算类中,使 cargoOrder 专注货物列表管理和基本订单信息处理。
  • 目前在 cargoOrder 类中根据不同条件(客户类型、货物类型、重量 )计算运费,代码较为冗余。将不同类型货物的运费计算规则封装成具体类,根据货物类型和客户类型选择对应策略计算运费,提高代码可维护性和扩展性。
  • 代码中未对可能出现的空指针情况进行处理。如在获取 deliveryInformation 及其关联对象(如 cargoOrder、Flight 等 )的属性时,若相关对象未正确初始化,可能导致空指针异常。

五、总结

此次作业的迭代让我明白了不遵守设计原则的话,后期的迭代会十分困难,也学会了正确使用继承和多态的使用能节省一部分时间和减少冗余代码。

posted @ 2025-05-23 17:57  写不来MATH  阅读(31)  评论(0)    收藏  举报