8~9题目集航空货运系统
前言
相比于上一次的单部电梯调试的题集,本次题集在算法上的难度下降了,侧重点更偏向于类设计以及添加了继承与多态两大特性的运用,所以说就不用那么费脑筋去苦思冥想算法了😄,虽然说设计也不是一件简单的事,但对我来说,相比于去研究一个复杂的算法,我还是更喜欢类设计。
第一次题目主要的难点就是类设计,需要分析该有哪些类,每个类有哪些属性和方法以及类与类之间的关系,类一般分为三大类[1](实体类、控制类和边界类),简单来说实体类就是用来实现现实世界中具体事物或概念的类,而控制类就相当于连接几个相对独立的实体类的“中介”,边界类就是用来输出的。
然后第二次实际上就是在第一次的基础上进行扩展,如果第一次类设计比较合理(符合设计原则)的话,第二次简直就是有手就行。第二次相比第一次来说客户类型、支付方式和货物类型增加了,所以此时就需要抽象出它们的共性来设计出它们分别的父类。
总而言之,题目的难度与题量都还算适中,但是让我们对面向对象这门技术有了更深的理解与运用。
设计与分析
第一次题目
第一次代码类图:

第一次代码分析:
SM分析表:



表格解释:
解释:
代码规模相关指标
- Lines:代码总行数为 431 行。
- Statements:语句数量为 99 条。
- Percent Branch Statements:分支语句(如if 、switch等)占比 2.0% 。
- Method Call Statements:方法调用语句数量为 35 条。
代码结构相关指标
-
and Interfaces:类和接口数量共 3 个 。
-
per Class:平均每个类的方法数为 5.00 个。
-
Average Statements per Method:平均每个方法的语句数为 4.47 条。
代码复杂度相关指标 -
Line Number of Most Complex Method:最复杂方法所在行号为 4,该方法是Main.main() 。
-
Maximum Complexity:最大复杂度为 1 。这里的复杂度可能是指圈复杂度(Cyclomatic Complexity ),用于衡量一个方法中独立路径的数量。
-
Line Number of Deepest Block:最深代码块所在行号为 6。
-
Maximum Block Depth:最大代码块深度为 2 ,表示代码中嵌套结构的最大层数。
-
Average Block Depth:平均代码块深度为 1.12 。
-
Average Complexity:平均复杂度为 1.00 。
最复杂方法信息 -
Most Complex Methods in 2 Class(es) :列出了最复杂的方法及其复杂度、语句数、最大深度、调用数。Main.main() 方法复杂度为 1,语句数 2 条,最大深度 2 ,调用数 15 次;-View.View() 方法复杂度为 1,语句数 0 条,最大深度 0 ,调用数 0 次。
总体来看,这段代码在复杂度方面表现较好,结构相对简单清晰,但在代码规模、类和方法的设计上可能存在进一步优化的空间,比如考虑提高模块化程度、进一步明确类和方法的职责等,以提升代码的可维护性和扩展性。
心得:
这一次在一段时间的学习以及上一次的积累下来的经验结合下,写程序的过程还挺顺利☀️。其考察的内容就是类设计,首先就是从需求中抽象出一个个实体,并将它们分别包装成一个个类,然后再确定类每个类该有哪些属性和方法,一个方法放在哪个类中更加合适,在这我遇到的难题就是计算一个货物的计费重量和获取单价的方法是该放在订单项类中还是放在货物类中,后来为了计算方便我就放在了订单项类中(但实际这为后面扩展埋了一个坑)。这些完成后就进入到了最核心的部分,设计类与类之间的关系,以及类与类之间逻辑关系的处理。
第二次题目:
第二次代码类图:

第二次代码分析:
SM分析图:


表格解释与分析:
基本信息(以下为所有类放在一个文件的分析,仅供部分参考)
Lines:代码总行数为 782 行
Statements:语句数量为 329 条。
代码结构指标
Percent Branch Statements:分支语句(如if、switch等)占比 8.2% 。
Method Call Statements:方法调用语句数量为 79 条 。
Percent Lines with Comments:含注释的代码行占比 27.6% 。该比例适中,一定程度上有助于开发人员理解代码功能,但如果注释过少则不利于代码维护,过多可能存在冗余注释。
Classes and Interfaces:类和接口总数为 20 个 。
Methods per Class:平均每个类的方法数为 15.50 个 。
Average Statements per Method:平均每个方法的语句数为 5.15 条 。
代码复杂度指标
Line Number of Most Complex Method:最复杂方法所在行号为 6,该方法是Main.main() 。
Name of Most Complex Method:明确指出最复杂方法是Main.main() 。
Maximum Complexity:最大复杂度为 11 ,表示Main.main()方法的圈复杂度(衡量方法中独立执行路径的数量)为 11。
Line Number of Deepest Block:最深代码块所在行号为 277 。
Maximum Block Depth:最大代码块深度为 5。
Average Block Depth:平均代码块深度为 0.97 ,整体代码块深度较浅,说明大部分代码逻辑较为扁平。
Average Complexity:平均复杂度为 1.27 (参考第一张图)。
心得:
这第二次就是在第一次的基础上扩展了几个新类,运用到的就是Java中继承与多态两大特性。在第一次时类设计就比较合理,所以扩展起来还是比较简单的,但我在上面说到后面会有一个坑,这个坑就是,如果我们将计算计费重量的方法以及获取重量单价的方法放在订单项类中的话,现在在原有的基础上增加了危险品与加急品两种货物类型,并且它们的单价有所不同,难道我们要在订单项类下扩展出几个货物类型的子类吗?这显然是不合理的,所以用于计算计费重量的方法与获取单价的方法放在货物类中更为合理,而计算一个货物价格的运费放在订单项类中更为合理。
踩坑心得
这一次题目集相比与上一次踩坑点比较少。
📖其一,就是上文中提到的方法的归属问题,这是类设计中的一大难点,这个就告诉我们,眼光要放长远些,不要图一时的方便,客户的需求一般是具有不确定性与变化性的,所以在编写程序时得时时刻刻注意是否符合可扩展性。
📖其二,这个坑我在两次题目中都踩了,那就是输入格式的问题,题目给的输入格式是每输入一个数据换一次行,所以当输入的一个数据不是nextLine()时,应该在其后面加一个nextLine()来消耗掉换行符。
📖其三,同样是两次题目都踩过的坑,所以现在记忆犹新,那就是没有将引用初始化,见下图:


在第一张图中一开始"private View view=new View();"一句中一开始只是写了"private View view;"而没有实例化对象,在构造函数中也没有,而在第二张图中也没有给client赋值,最后出现返回nullpoints的错误。
改进建议:
在编写程序时一定得确保程序的可扩展性和可维护性,要不然等以后需求发生改变时可能得大量修改原有代码甚至推翻重做。
总结:
通过这次题目训练呢,我对设计原则以及继承与多态两大特性有了更深刻的了解,实际上,上一次题目主要是考验我们的逻辑思维能力以及对单一职责原则的逐步探索与理解,而本次作业则运用到了除接口隔离外的另外六大设计原则,可见单一职责原则是其它几个原则实现的基础。此外,继承与多态的技术也是与设计原则实现密切相关的,例如依赖倒转原则提到面向抽象编程,而抽象指的是抽象类或接口,涉及到继承中的父类。
实体类:描述具体的实体,通常映射到数据库表格与文件。
控制类:体现应用程序的执行逻辑。
边界类:边界对象的抽象,通常是用来完成参与者(用户、外部系统)与系统交互的对象,例如:Form,对话框、菜单、接口等。
简单来说实体类就是用来实现现实世界中具体事物或概念的类,而控制类就相当于连接几个相对独立的实体类的“中介”,边界类就是用来输出的。 ↩︎
浙公网安备 33010602011771号