NoRA123

导航

关于题目集8~9的总结性Blog

一,前言
关于第八到第九次题目集,两次题目集共有6道题目,每个题目集中都有三道题目,第八题目集中前两道题目为之前题目集的题目的一个强化版本,让我们对继承和多态进行一个初步练手,然后是两次题目集的重头“航空货运管理系统”题目,第九题目集中首先来了一道魔方题目然后来了一道前面题目集的pro版本,然后就是“航空货运管理系统”题目pro版,,同样是采取一个递进式的模式进行一个测试
二,设计与分析
第一次分析

Main 类
包含 main 方法,是程序的入口点。
负责创建和使用其他类的对象。
Flight 类
属性:
flightNumber: 航班号(字符串)
departureCity: 出发城市(字符串)
arrivalCity: 到达城市(字符串)
flightDate: 航班日期(字符串)
maxPayload: 最大载重(双精度浮点数)
方法:
Flight: 构造函数,初始化航班信息。
toString: 返回航班信息的字符串表示。
Cargo 类
属性:
name: 货物名称(字符串)
length: 长度(双精度浮点数)
width: 宽度(双精度浮点数)
height: 高度(双精度浮点数)
actualWeight: 实际重量(双精度浮点数)
方法:
Cargo: 构造函数,初始化货物信息。
calculateVolumeWeight: 计算体积重量。
calculateChargeableWeight: 计算计费重量。
toString: 返回货物信息的字符串表示。
Customer 类
属性:
name: 客户姓名(字符串)
phone: 电话号码(字符串)
方法:
Customer: 构造函数,初始化客户信息。
toString: 返回客户信息的字符串表示。
FreightCalculator 类
属性:
rateTable: 费率表(双精度浮点数数组)
方法:
calculateFreight: 根据货物计算运费。
Shipment 类
属性:
sender: 发件人(客户)
receiver: 收件人(客户)
flightNumber: 航班号(字符串)
orderDate: 订单日期(字符串)
paymentMethod: 支付方式(字符串)
cargos: 货物列表
方法:
Shipment: 构造函数,初始化运输信息。
acceptCargo: 添加货物。
calculateTotalFreight: 计算总运费。
toString: 返回运输信息的字符串表示。
类之间的关系:
Main 类创建并使用 Flight、Cargo、Customer、FreightCalculator 和 Shipment 类的对象。
Shipment 类包含多个 Cargo 对象,并与 Flight、Customer 和 FreightCalculator 类有关联。
Customer 类与 Shipment 类有关联,表示发件人和收件人。

主要问题分析
检查点:Baseline
总行数:101
有效语句数:71(占21.1%)
方法调用次数:36
注释比例:2.0%(极低)
类/接口数:1
方法数量:5(平均每个方法10.80条语句)
方法复杂度高,逻辑分支过多
最复杂方法:BrokenElevator.run()(位于第48行)
最大复杂度:8(通常建议方法复杂度 ≤ 5)
高复杂度意味着该方法可能包含大量if-else、switch-case或循环嵌套,导致可读性和可维护性降低。
可能涉及状态管理(如电梯运行逻辑),建议拆分成更小的子方法。
方法体过长,职责不单一
每个方法平均语句数:10.80
超过行业推荐标准(通常建议每个方法 ≤ 5-10 行)。
可能导致方法承担过多职责,违反单一职责原则(SRP)
嵌套层级过深,可读性差
最大块深度:5(位于第36行)
平均块深度:2.54
深层嵌套(如if嵌套for再嵌套switch)会增加认知负担,容易引入逻辑错误。
建议使用卫语句(Guard Clauses)或策略模式优化。
注释严重不足
注释比例:2.0%(远低于推荐值 20-30%)
关键逻辑(如run()方法)缺乏说明,不利于团队协作和后期维护。
方法调用频繁,但复用性存疑
方法调用次数:36
虽然调用较多,但结合高复杂度,可能存在重复代码或过度耦合的情况。
第二次代码分析

  1. User 类
    属性
    name:代表用户的姓名,类型为String,用于标识用户。
    phone:代表用户的电话号码,类型为String,用于联系用户。
    用途
    作为系统中用户的基础类,为其他用户类型(如IndividualUser和GroupUser)提供了通用的属性和方法(虽然图中未显示方法)。
  2. Flight 类
    属性
    flightNumber:航班号,类型为String,用于唯一标识航班。
    departureAirport:出发机场,类型为String,表示航班的起始地点。
    arrivalAirport:到达机场,类型为String,表示航班的目的地。
    flightDate:航班日期,类型为String,用于记录航班的飞行时间。
    maxWeight:最大载重,类型为double,表示该航班能够承载的最大货物重量。
    方法
    多个get方法(如getFlightNumber等):用于获取航班的相关属性值,这些方法有助于在系统中查询航班信息。
  3. Cargo 类
    属性
    name:货物名称,类型为String,用于标识货物。
    length、width、height:货物的长、宽、高,类型为double,用于计算货物的体积。
    actualWeight:实际重量,类型为double,表示货物本身的重量。
    type:货物类型,类型为String,用于分类货物。
    方法
    calculateVolumeWeight:计算货物体积重量,根据长、宽、高计算得出,这在航空货运中用于计费。
    calculateChargeWeight:计算计费重量,可能会基于实际重量和体积重量来确定最终的计费重量。
    getType:获取货物类型,用于货物分类管理。
  4. Payment 类
    属性
    payAmount:支付金额,类型为double,表示用户需要支付的费用。
    用途
    作为支付的抽象类,定义了支付金额这一基本属性,为具体支付方式类(如AlipayPayment、WechatPayment、CashPayment)提供了基础。
  5. Order 类
    属性
    orderDate:订单日期,类型为String,记录订单生成的时间。
    user:下单用户,类型为User,关联到下单的用户。
    flight:使用的航班,类型为Flight,关联到货物所搭乘的航班。
    cargos:货物列表,类型为ArrayList,包含了订单中的所有货物。
    paymentMethod:支付方式,类型为Payment,关联到订单所采用的支付手段。
    方法
    addCargo:用于向订单中添加货物,操作cargos列表。
    calculateBaseFee:计算基本费用,可能基于货物的重量、体积等因素计算得出。
    calculateTotalFee:计算总费用,可能会考虑基本费用和其他附加费用。
    generateOrderReport:生成订单报告,用于为用户或系统提供订单的详细信息。
    generateCargoReport:生成货物报告,提供订单中货物的详细情况。
  6. 继承关系
    IndividualUser 和 GroupUser
    都继承自User类,意味着它们继承了User类的name和phone属性。
    这两种用户类型可能在系统中会有不同的处理方式,例如订单权限、折扣等方面可能存在差异。

    总行数(Lines)
    总行数为 101 行,属于一个相对较小的 Java 文件。
    语句数(Statements)
    语句数为 71,表明文件中有实际操作的代码语句占总行数的一定比例。
    语句百分比(Percent Statements)
    语句百分比为 21.1,不太清楚此百分比的计算方式和含义,如果是相对于总行数的比例,这个值可能有误(71/101 ≈ 70.3%)。
    方法调用次数(Method Call Statements)
    方法调用次数为 36,说明文件中方法之间的交互较为频繁,可能存在较多的功能依赖关系。
    每行带有注释的百分比(Percent Lines with Comments)
    每行带有注释的百分比为 2.0,这表明文件中的注释相对较少,可能会影响代码的可读性和可维护性,建议适当增加注释。
    类和接口数量(Classes and Interfaces)
    类和接口数量为 1,说明该文件中主要实现了一个类相关的功能。
    每个类的方法数量(Methods per Class)
    每个类有 5 个方法,对于一个类来说,这个方法数量适中,但需要结合具体功能来判断是否合理。
    每个方法的平均语句数(Average Statements per Method)
    每个方法平均有 10.80 个语句,这表明方法内部的逻辑可能较为复杂,可能需要进一步检查方法是否可以进行拆分以提高可读性和可维护性。
    三,踩坑心得
    在完成此次空运计费程序的过程中,我踩过不少坑,收获颇丰。起初,未深刻理解单一职责原则,将订单处理、货物计算和支付逻辑混杂在一个类中,导致代码臃肿且难以维护,后续拆分类后,代码的可读性和可扩展性大幅提升。
    在运用里氏代换原则时,曾因子类重写父类方法时未保持行为一致性,引发运行时错误,通过反复检查方法签名和功能实现,确保子类能安全替换父类。在开闭原则实践中,新增货物类型和支付方式时,最初直接修改已有类的代码,违背原则,后来通过抽象类和接口,实现了对扩展开放、对修改关闭。
    合成复用原则方面,错误地使用继承实现支付方式,导致代码耦合度过高,改为通过接口注入后,系统的灵活性显著增强。依赖倒转原则的应用也并非一帆风顺,高层模块依赖具体类引发诸多问题,改为依赖抽象后,代码结构更加稳定。这些经历让我对设计原则有了更深刻的理解。
    四,总结
    通过本阶段两次题目集的实践,我在面向对象设计与编程方面收获颇丰。不仅深入理解了单一职责、里氏代换等五大设计原则,并能将其运用到代码架构中,使程序的可维护性和扩展性得到显著提升;还学会了如何合理划分类与接口,通过抽象和封装实现代码的高内聚低耦合。在解决实际问题的过程中,锻炼了从需求分析到代码实现的全流程能力。
    然而,仍有许多需要进一步学习的地方。例如,对设计模式的综合运用还不够熟练,在复杂业务场景下,难以快速选择合适的模式优化代码。此外,对程序性能调优、异常处理机制的完善等方面也存在不足。
    关于课程和作业,建议可以增加更多实际场景的案例分析,在课上讲解设计原则时,结合具体的代码优化过程进行演示,帮助学生更好地理解。作业方面,能否提供一些阶段性的提示或代码框架,引导我们逐步完成任务,同时增加作业互评环节,促进同学间的交流学习

posted on 2025-05-25 17:44  NoRA卡密  阅读(25)  评论(0)    收藏  举报