“航空货运管理系统”-第二次大作业总结
一、前言:
知识点:
这两次题目集主要考察了对类的封装、继承、多态和抽象类的使用。开始接触各种设计原则,单一职责原则、里氏代换原则、开闭原则、合成复用原则。
题量:
题量不大有比较多的时间来设计代码结构。
难度:
难度中等,掌握一定的语法知识,加上不多的逻辑推理就能通过测试点。
所以,总体上这两次题目集还是能比较愉快的完成,美中不足的就是程序设计原则刚刚接触,理解不够深入,运用上会感觉模糊。
二、 设计与分析:
(1)第一代“航空货运管理系统”:
a、计费重量的确定
空运以实际重量(GrossWeight)和体积重量(VolumeWeight)中的较
高者作为计费重量。
计算公式:
体积重量(kg)= 货物体积(长×宽×高,单位:厘米)÷6000
示例:
若货物实际重量为80kg,体积为120cm×80cm×60cm,则:
体积重量 =(120×80×60)÷6000=96kg
计费重量取96kg(因96kg>80kg)。
b、基础运费计算
费率(Rate):航空公司或货代根据航线、货物类型、市场行情等制定(如
CNY 30/kg)。本次作业费率采用分段计算方式。
本次题目模拟某客户到该航空公司办理一次货运业务的过程:
航空公司提供如下信息:
航班信息(航班号,航班起飞机场所在城市,航班降落机场所在城市,航班
日期,航班最大载重量)
客户填写货运订单并进行支付,需要提供如下信息:
客户信息(姓名,电话号码等)
货物信息(货物名称,货物包装长、宽、高尺寸,货物重量等)
运送信息(发件人姓名、电话、地址,收件人姓名、电话、地址,所选
航班号,订单日期)
支付方式(支付宝支付、微信支付)
注:一个货运订单可以运送多件货物,每件货物均需要根据重量及费率单独
计费。
程序需要从键盘依次输入填写订单需要提供的信息,然后分别生成订单信
息报表及货物明细报表。


类图:

根据类图,类间关系主要为依赖和关联,在支付方式上使用了抽象类,方便了对支付方式的扩展。
SourceMontor的生成报表:

- Lines(行数):384
表明系统包含 384 行代码,具有一定规模,实现了相对丰富的功能。 - Statements(语句数):206
这表明代码中可执行或声明等语句数量为 206 条。语句数与行数不同,语句数反映了代码实现功能时指令的实际数量。与行数相比,语句数量适中。 - Percent Branch Statements(分支语句百分比):2.9
表明分支语句(if - else、switch 等)在总语句中占比 2.9% 。占比较低意味着代码中条件判断逻辑相对较少,代码执行路径相对较直接,逻辑较简单,有利于后期的维护。 - Method Call Statements(方法调用语句数):66
这表明代码中存在 66 条方法调用语句。方法调用频繁程度反映代码的模块化和方法间交互情况,说明代码在功能实现上依赖多个方法协作,体现了一定的模块化设计。但相对于总语句数来说,所占比例较高,这可能影响代码的耦合度和性能。 - Percent Lines with Comments(含注释行的百分比):11.5
这意味着代码中 11.5% 的行包含注释。注释比例不算高,一定量注释有助于理解代码逻辑,较低注释比例可能使代码阅读和维护难度增加。 - Classes and Interfaces(类和接口数量):7
这说明该代码文件定义了 7 个类或接口。这体现代码有一定的模块化和封装性,不同类或接口可承担不同职责,实现功能分离。 - Methods per Class(平均每个类的方法数):7.14
这表明平均下来每个类拥有约 7.14 个方法。若类中方法数过多,可能意味着类承担职责过多,违反单一职责原则,后期维护和扩展时可能相互影响。 - Average Statements per Method(平均每个方法的语句数):3.90
这表明平均每个方法含 3.90 条语句,说明方法内代码量相对较少,方法功能可能较单一,代码相对简洁,可读性和维护性较好。不过也可能存在方法拆分过细的情况。 - Line Number of Most Complex Method(最复杂方法的行号):49
最复杂方法位于第 49 行。通过定位到该行可重点分析此方法的实现逻辑,查看是否存在可优化之处,比如是否能拆分复杂逻辑为多个小方法,以降低方法复杂度。 - Name of Most Complex Method(最复杂方法的名称):FightMessage.setLoadmax ()
明确最复杂方法是 FightMessage.setLoadmax() 。需关注此方法内部实现,是否存在大量条件判断、循环嵌套或复杂算法,若有可考虑重构优化,提升代码可读性和可维护性。 - Maximum Complexity(最大复杂度):1
这表示代码中方法或模块的最大复杂度为 1 ,通常复杂度度量会考虑控制流复杂度等因素,此值低说明代码逻辑相对简单,代码执行路径较清晰,维护起来相对轻松,可以降低后期的代码维护成本。 - Line Number of Deepest Block(最深代码块的行号):350
这说明在第 350 行处存在最深层次嵌套的代码块。深层次嵌套可能使代码逻辑难以理解和跟踪。 - Maximum Block Depth(最大块深度):3
即代码中嵌套结构的最大深度为 3 层。一定程度嵌套不可避免,但深度过高会使代码逻辑混乱,3层不算特别高,代码逻辑结构正常。 - Average Block Depth(平均块深度):1.00
即平均块深度为 1 ,这表明整体代码中代码块嵌套程度较低,代码结构相对扁平,逻辑相对清晰,对代码阅读、理解和维护都比较有利。 - Average Complexity(平均复杂度):1.00
即平均复杂度为1,这表明代码逻辑简单易懂,容易阅读也有利于后期的维护。
踩坑心得:
1、由于设计的代码结构主要是类与类间的依赖与关联关系,所以在调用方法时需要进行大量的传参工作,在编写一些调用方法较多的语句时,就很容易漏写或者传入错误的参数。
2、对于货物的存储,我选择了ArrayList
后面,换了一种遍历方法才,得以解决。
3、类图上并没有做异常测试,到了最后只好在Main方法里做异常的检测。
改进建议:
1、拆分高方法数量的类。平均每个类有 7.14 个方法,部分类可能违反单一职责原则,可进行拆分,以达到单一职责的设计原则。
2、减少类与类之间的耦合度,特别是在此次大作业中,运用了大量的参数传递来完成类间协作。检查方法调用链,避免过度依赖特定实现类,可以尝试使用工厂模式来提高代码灵活性。
3、继续保持写注释的好习惯,此次大作业我的注释率来到了11.5%,相较以往有所进步,但所占比例仍然较少,需要进行补充,比如说,增加类和方法的功能说明,复杂算法或业务规则的解释。
(2)第二代“航空货运管理系统”:
增加业务规则:
1、有集团客户和个体客户两种类型,对应不同的折扣,分别是8折和9折;
2、本次作业费率与货物类型有关,货物类型分为普通货物、危险货
物和加急货物三种,其费率分别为:
3、支付方式(支付宝支付、微信支付、现金支付),可以选择支付方式。
类图:


根据类图,构建了一个涉及产品管理、客户管理、订单处理、支付处理等功能的业务系统框架,产品管理和客户管理都采用了继承和多态,有利于后期对客户类型和产品类型的个性化扩展。支付处理也采用了继承和多态,包含了微信,支付宝和现金三种支付方式。最后,通过依赖和关联把客户、航班、产品、支付处理等信息集成到订单处理类。
SourceMontor的生成报表:


- Lines(行数):511
表明该Java文件代码具有一定规模,代码规模还是较大的。 - Statements(语句数):244
代码中可执行语句数量,反映代码实际执行操作的数量,可一定程度体现代码的复杂程度和工作量。与行数对比,可知代码量适中。 - Percent Branch Statements(分支语句百分比):5.7
分支语句(if - else、switch 等)占总语句比例较低,这表明代码逻辑的分支情况较少,代码逻辑相对较为线性,可能更容易理解和维护。 - Method Call Statements(方法调用语句数):71
这表明代码中方法调用的频繁程度,较多的方法调用意味着代码模块化程度相对较高,通过方法调用实现不同功能模块的组合。 - Percent Lines with Comments(含注释行的百分比):8.0
注释比例较低,可能不利于代码的可读性和可维护性,对于后续维护和扩展代码,理解代码意图可能存在一定难度。 - Classes and Interfaces(类和接口数):11
这说明该文件定义了较多的类和接口,体现了代码较高的抽象和模块化程度,不同类和接口可实现不同功能。 - Methods per Class(每个类的方法数):5.82
平均每个类包含的方法数,反映类的功能丰富程度,数值表明类中功能相对较多,一定程度上体现类的内聚性较好。 - Average Statements per Method(每个方法的平均语句数):3.64
方法平均语句数较少,说明方法功能相对单一,遵循了代码编写中方法短小精悍的原则,有利于代码的复用和维护。 - Line Number of Most Complex Method(最复杂方法的行号):207
指出代码中最复杂方法所在位置,方便开发者定位重点关注的代码区域。 - Name of Most Complex Method(最复杂方法的名称):DangerProduct.freight ()
明确
了最复杂方法,后续可针对该方法进行优化、重构等操作。 - Maximum Complexity(最大复杂度):5
这表明代码中方法的最高复杂度,复杂度相对不算高,说明代码逻辑结构相对清晰,没有极度复杂难以理解的代码块。 - Line Number of Deepest Block(最深代码块行号):209
这确定代码中嵌套最深的代码块位置,有利于后续优化。 - Maximum Block Depth(最大代码块深度):3
这表明代码块嵌套深度不算深,而嵌套层次少有利于代码理解和调试,降低出错概率。 - Average Block Depth(平均代码块深度):1.04
平均深度较低,说明整体代码结构较为扁平,代码逻辑简单易懂。 - Average Complexity(平均复杂度):1.15
这表明代码整体上还是容易理解和阅读的,有利于后续维护和扩展。 - Kiviat Graph(雷达图):展示了代码多个维度(如注释百分比、平均复杂度、每个类的方法数等)的综合情况,直观呈现各项指标在整体代码度量中的位置,便于从宏观角度评估代码特征。
- Block Histogram(块直方图):以柱状图形式展示不同深度代码块中语句数量分布,可清晰看出大部分语句集中在较浅深度的代码块中,再次说明代码结构简单,嵌套少。
踩坑心得:
由于上一代程序在产品和客户信息没有预留扩展的接口,所以这一次需要重新定义抽象类,在类内进行修改时,具有共性的公共方法不应改为抽象方法,下放到子类来重写,这导致代码的冗长和不高效。所以得先思考好什么方法要在子类重写,什么方法可以直接继承使用。再一个,修改后,在主类方法中的调用要有更改,此时要特别注意是否使用了正确的对象实例,逻辑上要清晰。因为上一代对支付方式预留了可扩展的抽象类,所以在这一个程序中,对于支付方式的重构比较容易。
改进建议:
1、注释覆盖率仅 8.0%,远低于行业建议的 20%-30% 标准,还要加大注释的编写,较少的注释可能导致后续维护者误判算法边界条件。
2、平均每个类包含 5.82 个方法,有的类承担过多职责导致耦合度高,方法间依赖关系复杂,修改一个方法可能影响其他功能。可以对类间方法数较高的类进行重构和优化。
三、总结:
我认为困难的点:
这两次大作业,在功能的实现上并不难,较难的部分是程序设计上是否符合了各种面对对象的设计原则,代码的结构上能不能灵活应对各种个性化的修改和扩展。
收获:
- 对于类的单一职责有了更深的理解,感受到了各种设计原则,并运用它。
- 学会了如何使用继承和多态,对于继承和多态有了自己的理解,在程序中使用继承和多态,感受到了它对于扩展的便利性,在代码上变得更加简洁高效,也帮助我理解了开闭原则,对修改关闭对扩展开放的内涵。
- 略微感受了“工厂模式”,但是只是在主类方法里使用。
- 体会到了注释的好处,对于核心逻辑上进行注释极大的提高了我后期迭代代码时的效率,能够快速的阅读和理解我的代码逻辑。
不足:
- 在类的设计上,对于单一职责的设计原则还需继续研习,通过分析来看有一小部分类的单一职责做得并不好。
- 其他设计原则还在摸索中,比如说里氏代换原则,真正严格意义上来说,现在的类设计只能说是有所体现,但并不深刻。
- 注释占比仍然不高。
- 代码行数相对来说,有点偏高。
综上:
这两次大作业完成得比较愉快,一定程度上增加了我的信心。遵循面对对象的设计原则来编写程序,的确会让代码编写过程变得更加顺畅,而不是说在添加新功能时需要思考大半天不知道从哪下手,甚至修改过后代码已经不成样子,只好推翻重写。后续,我将继续研习类的设计原则,继承与多态还有接口的使用并且和“工厂模式”结合,锻炼思维能力。

浙公网安备 33010602011771号