昌航面向对象程序设计8-9次航空货运题目小结
一、前言
在经历了第一次大作业电梯对于算法的考察后,本次航空货运题目集更多的是考察java中一些基础的思想包括对继承、多态等使用。其中第八次题目集的货运题里,最主要的难点与知识点在于对类的设计,需要对题目进行一定程度的分析和抽象化;而第九次的题目中则主要考查了Java中继承、接口、抽象类的知识。这次第二轮的大作业相比第一次的题量要少一些,如果掌握和熟悉了Java中的一些相关的思想,解题的思路和代码的编写都会较为流畅,所以本次题目集的难度也较为适中,便于我们熟悉Java中的设计与思想。
&esmp;下面我将着手SourceMonitor的生成报表内容以及PowerDesigner的相应类图对这两次大作业进行分析,给出我个人的看法与总结,也算是对这几周Java学习的回顾吧。
二、设计与分析
第一次航空货运作业
第一次的作业的要求是根据提供的输入信息(依次输入客户信息、货物信息、航班信息以及订单信息)来思考和设计需要的类,并且计算比较货物的实际重量与体积重量,最终输出货运服务的整个订单。类设计原则要符合面向对象设计原则中的单一职责原则、里氏代换原则、开闭原则以及合成复用原则。
类设计:
本次作业作为第一次作业,主要考察类的设计。那么,我根据输入的数据依次构建了Customer类来存储客户各类信息,Product类来存储各个不同商品的信息,同时编写了一个Order类来串联管理所有商品组成的订单,以及存储航班信息的Airline类。而为了满足开闭原则,我通过Payment这个接口来实现不同的支付方式,便于后续代码的扩展和延续。本次题目集主要的计算货物重量,以及所需要的运费的方法则被我放到了Product类来实现。
代码分析:
由代码的静态度分析来看:
(1)代码规模:代码共有391行,250条语句,语句密度约为0.64(250 ÷ 391),代码的整体规模较为适中,语句密度也处于合理区间,说明代码在结构与逻辑上较为平衡。
(2)类分析:共有7个类或接口,每个类平均包含8.43个方法,方法数较多,表明功能拆分相对充分;每个方法平均2.66条语句,说明方法实现较为简洁,符合高内聚低耦合的设计原则。
(3)代码注释:注释行占比为0.0%,注释完全缺失,严重影响代码的可读性、理解性和后续的维护性。尤其对于逻辑判断和接口实现类,缺乏注释不利于他人阅读及代码重构。
(4)代码结构:最大块深度为3层,平均块深度为1.63,且有超过60%的语句(157 条)处于第2层及以上的嵌套中,说明逻辑结构尚可接受,但部分函数仍有一定嵌套复杂度,后期可酌情优化。
(5)代码复杂性:最复杂的方法为Product.getRate(),其圈复杂度达到7,说明存在多个分支判断逻辑,若再增长将会降低代码可维护性与可测试性。整体平均圈复杂度为1.18,复杂度处于可控范围。
(6)分支与方法调用:分支语句占比为4.0%,逻辑判断使用不多,主要以简单流程为主;方法调用数为36次,占比约为14.4%,调用频率适中,整体结构清晰,但可适当提升复用性和面向接口编程的比例。
第二次航空货运作业
第二次作业的要求是对客户、支付方式以及货物类型进行泛化处理(继承),主要考察检验代码复用性和可拓展性,不同的客户有不同的折扣,而不同货物也有不同的收费比例,本题仍需符合面向对象设计原则中的单一职责原则、里氏代换原则、开闭原则以及合成复用原则。
类设计:
本次题目类设计的基本框架与第一次作业基本保持不变,但在题目的要求上对Customer类抽象化并泛化出了Individual和Corporate两个子类,其区别为各自的折扣。同样的,也对Product类泛化出NormalProduct、ExpediteProduct、DangerousProduct三个子类,对payment接口泛化出三种支付方法的实现类。同时,观察到题目通过输入字符串来选择不同的子类实例,于是给三个抽象类都编写了对应的工厂类,是对象实例的构建根据输入在工厂中就创建好,避免主方法中过多判断语句。
代码分析
由代码的静态度分析来看:
(1)代码规模:代码共有495行,326条语句,语句密度约为0.66(326 ÷ 495),代码规模适中,结构紧凑,说明项目整体开发规范、逻辑清晰,未出现冗余的结构膨胀现象。
(2)类分析:共包含17个类或接口,每个类平均包含约4.41个方法,方法数量适中,说明在功能设计上有一定的职责分离意识;每个方法平均约2.72条语句,说明大多数方法功能单一,结构较简洁,有助于后期维护和测试。
(3)代码注释:注释行占比为0.0%,当前版本未包含任何注释信息,文档性严重不足。如果这是工作上的代码,不便于往后的多人协作、交接维护或功能重构时将严重影响代码可读性和理解效率,还是需要补充关键类、方法与复杂逻辑的注释说明的。
(4)代码结构:最大块深度为3层,平均块深度为1.62,嵌套层级控制得当;根据语句分布,约62%的语句集中在深度2~3层之间,说明部分业务逻辑略显集中,但尚未影响整体代码清晰度,建议保持当前结构,避免向更深层次演化。
(5)代码复杂性:最复杂的方法为DangerousProduct.getRate(),圈复杂度达到7,语句数为9,说明该方法可能包含较多分支判断逻辑。整体平均圈复杂度为1.41,属于偏低水平,说明代码逻辑相对简单、可控,仍具有较高的可维护性和可测试性。
(6)分支与方法调用:分支语句占比为8.0%,逻辑复杂度中等,说明系统中存在一定的业务判断需求;方法调用数为62次,占语句总数的约19.0%,调用频率合理,体现了良好的模块化结构,具备一定的代码复用与面向接口设计的倾向。
三、采坑心得
第一次航空货运作业
本次航空货运作业大量的代码都是在处理输入和输出相关的功能,其中许多的输入是字符串和整形交替输入,所以本次题目集我遇到的第一个问题就是输入的数据由于换行符等原因而无法对齐,最终无法存储相应的数据而正确输出。我最终的解决方案就是在每次for循环输入的结尾sc.nextLine()来消耗换行符,再经过一些调试后解决了问题。而之后第二个问题则又是犯了第一次大作业也犯过的理解题意的问题:题目中有一个数据是需要计算总重量,我一开始是直接把实际重量求和,但题目集一直无法通过:
之后我将累加的数据改为实际重量和体积重量中更大的那个,最终通过了题目。
第二次航空货运作业
而第二次作业中我在对类的抽象化和泛化出各种子类时没有遇到太大的问题,反而是一直在考虑怎么简洁的通过输入字符串来决定创建哪个子类实例。而在上了java课程后,通过老师讲解的简单工厂形式我很快的解决了这个问题,这样Main方法中代码就不会过于冗杂。
四、改进建议
通过回顾这两次代码的编写以及各种外部工具代码的分析,我发现许多问题和需要改进的地方:第一要强调的还是注释的缺少,这在上次电梯题目中也是一个问题,要分析问题的产生的原因我认为是现在这两次大作业代码量还不是过于复杂,也不需要多人协同合作,所以注释的用处不大,但写注释仍然是代码健壮性的一部分,是我之后还需要改进的地方。而第二个问题则是类图,我以往编写代码都是直接开始编写,而通过本次对于类的设计让我明白在编写代码前类图绘画的必要性,这样就让代码的编写有了一个方向指导,编写起来更有效率,更有整体。而通过本次题目的迭代,我也明白了代码复用性和扩展性的好处,所以我往后代码的编写要更注重这方面。
五、总结
本次作业可以算是正式将Java各种核心思想和工具包括继承、多态、接口、抽象类这些东西应用在代码的作业,紧随着就是代码量的扩大。为了代码的复用性和扩展性等,搭建起来的就是一个代码量远比面向过程编程大的框架,所以这对我们的考查是全方面的。而完成了这次的大作业后,我感觉我对Java理解有更进一步,我从一开始认为许多Java的代码是多余和过于复杂的,到现在发现前面对代码的封装、继承都是有意义的,或是为了代码的安全性、或是为了代码的复用与继承。同时我也逐渐区分开了各个语言的特点,Java虽然做到了安全复用,但其效率可能就会打折扣,这让我明白不同场合应该使用不同的语言。
从开学对Java这门快节奏的课程不适应,到现在逐渐跟上脚步,我感受Java课程间各环节设置的合理性,但我依然认为Java课程中实验还是较为消耗时间,还是可以更加提升效率。
希望后续的代码编写能吸取这次的经验,本学期的Java课程能取得一个好成绩。