jyh0524

导航

 

1.总结:

感受:
两次作业作为迭代作业,第一次比较耗时难做,但是第二个题目集在第一次的基础上进行迭代,就容易了很多,只是在第一次基础上进行修改。
知识点:
1.类与对象的封装
2.继承与多态
3.对于数据的存储
好处:
可维护性:代码按类拆分,修改某个功能时只需调整对应类,避免牵一发而动全身。
可扩展性:新增功能(如添加新的计费规则)时,可通过继承或新增类实现,无需大幅修改现有代码。
可读性:类名和方法名直观反映业务含义,易于理解。
难度:
整体难度不大,只需要耐心,修改迭代前代码,并且知道代码作用(最好添加注释),即可快速写出。

2.设计与分析

对于第八次题目集中的航空货运管理系统:

  1. bh 类:基础编号类
    作用:
    抽象通用属性:定义编号字段 bh,作为其他类(如客户、航班、订单)的公共属性,体现 “所有实体都有唯一编号” 的业务逻辑。
    代码复用:通过继承让子类(Kh、Hb、dd)直接拥有编号属性,避免重复定义。
  2. js 类:计算基础类
    作用:
    封装货物计算逻辑:定义货物的尺寸(长、宽、高)、实际重量、计费重量、费率等属性,以及计算运费的通用方法。
    父类抽象:作为 Hw 类的父类,提供计费重量计算(height())、费率设置(dj())、运费计算(fy())的基础逻辑。
    设计意图:
    通过继承让 Hw 类复用计算逻辑,符合 “开闭原则”(扩展新货物类型时无需修改父类)。
  3. Hb 类:航班类(继承自 bh)
    作用:
    描述航班信息:封装航班的编号、起降地点、日期、最大载重等属性,用于校验订单总重量是否超载。
    关键逻辑:
    在 main 方法中,通过 if (b > hb.getZl()) 判断航班是否超载,决定是否输出订单详情。
  4. Kh 类:客户类(继承自 bh)
    作用:
    存储客户信息:记录客户的编号、姓名、电话、地址及订单中的货物数量,用于订单信息展示。
  5. Hw 类:货物类(继承自 js)
    作用:
    核心业务类:描述单个货物的详细信息,包括编号、名称、尺寸、实际重量,并通过链表结构连接多个货物。
    计算逻辑实现:重写父类 js 的 height() 方法,计算计费重量,并调用 dj() 设置费率、fy() 计算运费。
    关键场景:
    在 main 方法的循环中,逐个创建 Hw 对象并添加到链表,计算总重量 b 和总运费 a。
  6. dd 类:订单类(继承自 bh)
    作用:
    封装订单信息:记录订单编号、日期、收发件人信息,用于输出订单详情。
  7. Main 类:主程序类
    作用:
    程序入口:负责读取用户输入、创建对象、组装业务逻辑、控制流程走向(如超载判断)和输出结果。
    核心逻辑:
    输入读取:
    读取客户信息,创建 Kh 对象。
    循环读取 sl 个货物信息,创建 Hw 对象并构建链表。
    读取航班和订单信息,创建 Hb 和 dd 对象。
    业务处理:
    调用 height()、dj()、fy() 计算每个货物的计费重量、费率和运费。
    累加总重量 b 和总运费 a。
    判断航班是否超载,决定输出提示或订单详情。
    输出控制:
    格式化输出订单详情和货物明细,通过链表遍历展示所有货物信息
    类图如下:

    SourceMontor分析如下:


    代码规模相关指标:
    Lines(行数):388 行。表明代码量有一定规模,行数较多意味着代码实现的功能相对复杂,维护时需要花费更多精力去理解代码逻辑。
    Statements(语句数):199 条。语句数反映了代码中实际执行操作的数量,与行数结合看,说明代码不是特别冗余,但可能存在一些较长的语句。
    代码结构与逻辑相关指标
    Percent Branch Statements(分支语句百分比 ):12.6% 。表示代码中分支语句(如 if-else、switch 等)占总语句数的比例,该比例不算高,说明代码的逻辑分支不算特别复杂,但仍有一定的条件判断逻辑。
    Method Call Statements(方法调用语句数):50 。说明代码中存在较多方法间的调用,反映出代码的模块化程度有一定基础,但也需要关注方法间的调用关系是否合理,是否存在过度耦合。
    代码注释相关指标
    Percent Lines with Comments(含注释行的百分比):16.2% 。表明有一定比例的代码行包含注释,对代码理解有一定帮助,但从比例上看,注释可能还不够丰富,对于更复杂的逻辑可能需要增加注释来提升可读性。
    类与方法相关指标
    Classes and Interfaces(类和接口数量):7 。说明代码中定义了 7 个类或接口,体现了一定的面向对象设计思想,将不同功能封装到不同类中,但也需要关注类之间的关系是否合理。
    Methods per Class(每个类的平均方法数):6.00 。意味着平均每个类包含 6 个方法,说明类的功能相对丰富,但也可能存在单个类承担过多职责的情况,违背单一职责原则。
    Average Statements per Method(每个方法的平均语句数):2.57 。平均每个方法的语句数较少,说明方法相对比较短小,这是比较好的代码风格,便于理解和维护,但也可能存在方法拆分过细的情况。
    Line Number of Most Complex Method(最复杂方法的行号):108 。指出最复杂方法所在行号,方便定位重点关注的方法。
    Name of Most Complex Method(最复杂方法的名称):由于图片显示不全,无法确切得知,但可针对该方法进一步分析其复杂度高的原因。
    Max Complexity(最大复杂度):22 。说明代码中存在复杂度较高的方法,高复杂度方法往往意味着逻辑复杂,难以理解和维护,需要考虑重构。
    Max Depth(最大深度):4 。表示代码中方法调用或逻辑嵌套的最大深度,深度较大可能导致代码难以跟踪和调试。
    Avg Depth(平均深度):1.81 。平均深度相对较低,说明整体代码的逻辑嵌套情况不是很严重。
    Avg Complexity(平均复杂度):1.64 。平均复杂度较低,表明大部分方法的逻辑相对简单,但仍需关注个别高复杂度方法。
    图表解读
    Kiviat Graph(雷达图 ):展示了代码在注释比例(% Comments)、每个类的方法数(Methods/Class)、每个方法的平均语句数(Avg Stmts/Method)、平均复杂度(Avg Complexity)、平均深度(Avg Depth)、最大深度(Max Depth)和最大复杂度(Max Complexity)等方面的情况。可以直观看到各项指标的平衡情况,比如从图中可以看出最大复杂度相对突出。
    Block Histogram(块状直方图 ):横坐标是深度(从 0 到 9+ ),纵坐标是语句数。该图展示了不同深度下的语句分布情况,从图中可以看到深度为 1 和 2 时语句数较多,说明大部分语句处于相对较浅的逻辑层次中。
    综合分析与建议
    代码可维护性方面:虽然平均方法语句数和平均复杂度较低,但代码行数较多且存在高复杂度方法,加上注释比例不算高,维护起来仍有一定难度。建议增加注释,特别是对复杂逻辑和关键方法进行说明;同时对高复杂度方法进行重构,拆分成更小、功能更单一的方法。
    代码结构方面:类和方法数量较多,需要检查类与类之间、方法与方法之间的关系,避免过度耦合,确保每个类和方法职责单一。对于分支语句和方法调用,要关注其逻辑合理性,避免不必要的复杂逻辑。
    对于第九次题目集中的航空货运管理系统:
  8. bh 类:基础编号类
    作用:
    抽象通用属性:定义编号字段 bh,作为其他类(如客户、航班、订单)的公共属性,体现 “所有实体都有唯一编号” 的业务逻辑。
    代码复用:通过继承让子类(Kh、Hb、dd)直接拥有编号属性,避免重复定义。
  9. js 类:计算基础类
    作用:
    封装货物计算逻辑:定义货物的尺寸(长、宽、高)、实际重量、计费重量、费率等属性,以及计算运费的通用方法。
    父类抽象:作为 Hw 类的父类,提供计费重量计算(height())、费率设置(dj())、运费计算(fy())的基础逻辑。
    设计意图:
    通过继承让 Hw 类复用计算逻辑,符合 “开闭原则”(扩展新货物类型时无需修改父类)。
  10. Hb 类:航班类(继承自 bh)
    作用:
    描述航班信息:封装航班的编号、起降地点、日期、最大载重等属性,用于校验订单总重量是否超载。
    关键逻辑:
    在 main 方法中,通过 if (b > hb.getZl()) 判断航班是否超载,决定是否输出订单详情。
  11. Kh 类:客户类(继承自 bh)
    作用:
    存储客户信息:记录客户的编号、姓名、电话、地址及订单中的货物数量,用于订单信息展示。
    新增功能:
    通过 lx 区分客户类型,影响最终支付折扣(如企业客户折扣更大)。
  12. Hw 类:货物类(继承自 js)
    作用:
    核心业务类:描述单个货物的详细信息,包括编号、名称、尺寸、实际重量,并通过链表结构连接多个货物。
    计算逻辑实现:重写父类 js 的 height() 方法,计算计费重量,并调用 dj() 设置费率、fy() 计算运费。
    关键场景:
    在 main 方法的循环中,逐个创建 Hw 对象并添加到链表,计算总重量 b 和总运费 a。
  13. dd 类:订单类(继承自 bh)
    作用:
    封装订单信息:记录订单编号、日期、收发件人信息,用于输出订单详情。
    字段与方法:
    字段:
    String ddrq, dz1, xm1, dh1, dz2, xm2, dh2:订单日期、发件人地址 / 姓名 / 电话、收件人地址 / 姓名 / 电话。。
  14. Main 类:主程序类
    作用:
    程序入口:负责读取用户输入、创建对象、组装业务逻辑、控制流程走向(如超载判断)和输出结果。
    核心逻辑:
    输入读取:
    读取客户信息(类型、编号、姓名等),创建 Kh 对象。
    读取货物类型,循环读取 sl 个货物信息,创建 Hw 对象并构建链表。
    读取航班和订单信息,创建 Hb 和 dd 对象。
    业务处理:
    根据客户类型设置折扣(zk),如企业客户打 8 折。
    调用 height()、dj()、fy() 计算每个货物的计费重量、费率和运费。
    累加总重量 b 和总运费 a,应用折扣后输出最终金额。
    输出控制:
    格式化输出订单详情和货物明细,通过链表遍历展示所有货物信息。
    支持三种支付方式(微信、支付宝、现金)的显示转换。
    类图如下:

    SourceMontor分析如下:


    代码规模相关指标
    Lines(行数):388 行。表明代码量有一定规模,行数较多意味着代码实现的功能相对复杂,维护时需要花费更多精力去理解代码逻辑。
    Statements(语句数):199 条。语句数反映了代码中实际执行操作的数量,与行数结合看,说明代码不是特别冗余,但可能存在一些较长的语句。
    代码结构与逻辑相关指标
    Percent Branch Statements(分支语句百分比 ):12.6% 。表示代码中分支语句(如 if-else、switch 等)占总语句数的比例,该比例不算高,说明代码的逻辑分支不算特别复杂,但仍有一定的条件判断逻辑。
    Method Call Statements(方法调用语句数):50 。说明代码中存在较多方法间的调用,反映出代码的模块化程度有一定基础,但也需要关注方法间的调用关系是否合理,是否存在过度耦合。
    代码注释相关指标
    Percent Lines with Comments(含注释行的百分比):16.2% 。表明有一定比例的代码行包含注释,对代码理解有一定帮助,但从比例上看,注释可能还不够丰富,对于更复杂的逻辑可能需要增加注释来提升可读性。
    类与方法相关指标
    Classes and Interfaces(类和接口数量):7 。说明代码中定义了 7 个类或接口,体现了一定的面向对象设计思想,将不同功能封装到不同类中,但也需要关注类之间的关系是否合理。
    Methods per Class(每个类的平均方法数):6.00 。意味着平均每个类包含 6 个方法,说明类的功能相对丰富,但也可能存在单个类承担过多职责的情况,违背单一职责原则。
    Average Statements per Method(每个方法的平均语句数):2.57 。平均每个方法的语句数较少,说明方法相对比较短小,这是比较好的代码风格,便于理解和维护,但也可能存在方法拆分过细的情况。
    Line Number of Most Complex Method(最复杂方法的行号):108 。指出最复杂方法所在行号,方便定位重点关注的方法。
    Name of Most Complex Method(最复杂方法的名称):由于图片显示不全,无法确切得知,但可针对该方法进一步分析其复杂度高的原因。
    Max Complexity(最大复杂度):22 。说明代码中存在复杂度较高的方法,高复杂度方法往往意味着逻辑复杂,难以理解和维护,需要考虑重构。
    Max Depth(最大深度):4 。表示代码中方法调用或逻辑嵌套的最大深度,深度较大可能导致代码难以跟踪和调试。
    Avg Depth(平均深度):1.81 。平均深度相对较低,说明整体代码的逻辑嵌套情况不是很严重。
    Avg Complexity(平均复杂度):1.64 。平均复杂度较低,表明大部分方法的逻辑相对简单,但仍需关注个别高复杂度方法。
    图表解读
    Kiviat Graph(雷达图 ):展示了代码在注释比例(% Comments)、每个类的方法数(Methods/Class)、每个方法的平均语句数(Avg Stmts/Method)、平均复杂度(Avg Complexity)、平均深度(Avg Depth)、最大深度(Max Depth)和最大复杂度(Max Complexity)等方面的情况。可以直观看到各项指标的平衡情况,比如从图中可以看出最大复杂度相对突出。
    Block Histogram(块状直方图 ):横坐标是深度(从 0 到 9+ ),纵坐标是语句数。该图展示了不同深度下的语句分布情况,从图中可以看到深度为 1 和 2 时语句数较多,说明大部分语句处于相对较浅的逻辑层次中。
    综合分析与建议
    代码可维护性方面:虽然平均方法语句数和平均复杂度较低,但代码行数较多且存在高复杂度方法,加上注释比例不算高,维护起来仍有一定难度。建议增加注释,特别是对复杂逻辑和关键方法进行说明;同时对高复杂度方法进行重构,拆分成更小、功能更单一的方法。
    代码结构方面:类和方法数量较多,需要检查类与类之间、方法与方法之间的关系,避免过度耦合,确保每个类和方法职责单一。对于分支语句和方法调用,要关注其逻辑合理性,避免不必要的复杂逻辑。

3.踩坑心得:

1.在完成题目集 8-9 的航空货运管理系统时,由于对 Java 数据结构特性理解不足,在数据存储方式的选择上走了弯路。最初受 C 语言惯性思维影响,直接采用手动实现链表结构(通过Hw类的next指针构建),而非使用 Java 提供的 **ArrayList等集合框架 **,导致代码复杂度增加、调试成本上升。
2.业务逻辑边界处理不当
在计算费率时,js类的dj()方法对货物类型(lx)的判断使用大量if-else,未处理非法类型(如输入其他字符串),可能导致费率默认值错误。
3.代码注释与可读性不足
因为是迭代题目,所以代码注释极其重要,但是原始代码注释比例仅 16.2%,导致迭代起来有点困难,复杂逻辑(如体积重量计算、折扣规则)缺乏说明。
踩坑总结:
数据结构选择:Java 的集合框架(如ArrayList、LinkedList)已封装了链表、数组等数据结构的底层实现,应优先使用而非手动实现,以减少编码错误和维护成本。
输入输出健壮性:永远假设用户输入是非法的,必须添加严格的校验逻辑(如类型、范围校验),避免程序异常终止。
模块化与注释:复杂方法(如dj()、链表操作)应添加详细注释,类与类之间的协作关系(如Kh与Hw的数量关联)需通过文档或类图明确,提升代码可理解性。
通过这次踩坑,深刻体会到 Java 面向对象编程中 “工具优先” 的原则 —— 合理利用 Java 提供的类库和框架,而非重复造轮子,是提升开发效率和代码质量的关键。同时,编码时需养成 “先设计后实现” 的习惯,避免因惯性思维(如 C 语言的链表操作)导致的适配问题。

4.总结与提升方向

(一)实践总结:面向对象设计的得与失

通过两次航空货运管理系统的作业实践,完整经历了从需求分析、类结构设计到代码实现与迭代的全流程,对面向对象编程(OOP)的核心思想有了更深刻的认知。

  • 优势体现:通过封装(如Hw类隐藏货物计算细节)、继承(bh类统一编号管理)和多态(jsHw的方法重写),系统结构清晰,功能扩展便捷。例如,第二次作业新增客户折扣功能时,仅需在Kh类中添加类型字段并修改Main类的计算逻辑,无需改动其他核心类,充分体现了OOP的可扩展性。
  • 现存问题
    • 代码质量:虽平均方法语句数(2.57)和复杂度(1.64)较低,但存在单个高复杂度方法(Max Complexity=22),且注释比例不足(16.2%),复杂逻辑(如体积重量公式推导)缺乏说明,增加了维护成本。
    • 设计缺陷:手动实现链表结构导致代码冗余(如Hw类的next指针操作),未充分利用Java集合框架;Main类承担过多职责(输入、逻辑、输出),违背“单一职责原则”,耦合度较高。

(二)提升方向:从代码优化到架构升级

1. 代码质量与可维护性优化
  • 注释与文档补充
    • 对核心算法(如Hw类的height()方法中“体积重量=长×宽×高/6000”)添加公式说明,对状态判断(如航班超载逻辑if (b > hb.getZl()))解释业务规则,将注释比例提升至20%以上。
    • 绘制类协作图(如KhHw的数量关联、ddHb的订单-航班关系),明确模块间依赖,降低理解成本。
  • 高复杂度方法重构
    • dj()方法中基于货物类型的费率判断逻辑,从冗长的if-else链重构为枚举类型(如定义HwType枚举)或策略模式(RateStrategy接口及其实现类),提升扩展性与可读性。
    • 拆分Main类中长达108行的核心逻辑,将输入读取(readInput())、业务计算(calculateFreight())、结果输出(printResult())分离为独立方法,避免“上帝类”问题。
2. 数据结构与工具链升级
  • 摒弃手动实现,拥抱Java类库
    • 将货物链表从自定义next指针改为使用LinkedList<Hw>ArrayList<Hw>,利用集合框架的add()remove()等方法简化操作,减少底层代码错误。
    • 引入HashMap管理客户信息(如以客户编号bh为键),提升查询效率,避免线性遍历。
  • 增强输入输出健壮性
    • 对用户输入(如货物类型、客户类型)添加枚举校验,使用try-catch捕获非法输入异常,避免程序崩溃。例如,通过EnumSet.allOf(HwType.class).contains(lx)校验货物类型合法性。
3. 设计模式与架构优化
  • 应用设计模式解耦逻辑
    • 工厂模式:创建ObjectFactory类统一管理对象创建(如KhHwHb的实例化),减少Main类中的硬编码依赖。
    • 策略模式:将运费计算逻辑(如普通货物、特殊货物的不同费率)封装为策略接口FreightStrategy,不同策略类实现具体计算,通过依赖注入动态切换,符合“开闭原则”。
  • 分层架构设计
    将系统划分为表现层(UI)(负责输入输出,如Main类)、业务逻辑层(Service)(处理运费计算、超载校验等核心逻辑)、数据层(DAO)(管理数据存储,如客户、航班信息的增删改查),明确层间职责,降低耦合度。
4. 工程化能力提升
  • 单元测试覆盖:使用JUnit对关键方法(如Hw.fy()js.height())编写测试用例,覆盖正常场景(如标准货物计费)、边界场景(如体积重量与实际重量相等)和异常场景(如非法费率输入),确保代码修改后功能稳定性。
  • 代码规范与协作:遵循Java编码规范(如类名驼峰命名、包名小写),使用IDE插件(如SonarLint)扫描代码异味(如过长方法、魔术值),提升团队协作效率。

(三)结语:从“实现功能”到“设计系统”

本次作业不仅是代码的编写过程,更是从“面向过程”到“面向对象”思维的转变。未来需以“可维护性、可扩展性、可读性”为目标,摆脱“惯性思维”(如C语言的手动内存管理),充分利用Java生态的工具与框架,在实践中持续打磨设计能力,逐步实现从“功能实现者”到“系统设计者”的进阶。每一次代码重构都是对系统认知的深化,而每一处细节优化都是向高质量编程的靠近。

posted on 2025-05-25 13:24  辣辣辣辣辣  阅读(31)  评论(0)    收藏  举报