软件工程 面向对象程序设计Java -第二次作业总结
第二次作业分析(航空货运管理系统)
24201915(24201501)吴雨芊
前言
1.关于题量
此次大作业一共有两次题目集,从题量上还是难度上都大大减少了许多,做得也很快,主要是对Java继承与多态以及面向对象设计原则这部分知识的把握,而没有考察算法。
2.关于知识点
此次作业中前几次的题目都是在帮助我们巩固Java的基本结构与语法,让我们学习继承和多态,以及掌握抽象类和接口,而最后一题货运系统则是考察我们实践能力的题目,帮助我们培养根据需求设计方案的思维,以及如何设计抽象类,考察了我们对于这块内容的熟练程度,最终要使我们写的程序满足面向对象设计原则中的单一职责原则、里氏代换原则、开闭原则以及合成复用原则、依赖倒转原则。
- 第一次货运管理系统
设计类图,每个类实现特定的功能,其中要注意实现开闭原则,即对扩展开放,对修改关闭,则考察我们如何设计抽象类使下一次需求发生变化时,改动最少。这里要注意单一职责原则,以及代码的可复用性和可扩展性,并且考察了类与类之间的关系如关联,依赖与聚集。 - 第二次货运管理系统
在之前的基础迭代上,大体不变,改变了需求,本题需求可扩展的类:用户、支付方式、货物,要将这些类全部设计成抽象类,这里修改的难易程度正好反应了之前的代码是否具有良好的可复用性
3.关于难度
1.逻辑难度
-
货物类型影响费率
-
客户类型影响折扣
-
航班限制影响订单有效性
2.类设计难度
- 类职责与划分,以及类之间的调用关系:控制类需独立于订单,航班,客户类,但又需紧密协作。
- 继承与多态,怎样设计抽象类使其满足多种设计原则。
设计与心得
1. 08题目集
- 题目: 航空货运管理系统
请编写一个Java程序,本次题目模拟某客户到该航空公司办理一次货运业务的过程:
航空公司提供如下信息:
航班信息(航班号,航班起飞机场,航班降落机场,航班日期,航班最大载
重量)
客户填写货运订单并进行支付,需要提供如下信息:
客户信息(姓名,电话号码等)
货物信息(货物名称,货物包装长、宽、高尺寸,货物重量等)
运送信息(发件人姓名、电话、地址,收件人姓名、电话、地址,所选
航班号,订单日期)
支付方式(支付宝支付、微信支付)
- 设计
![]()
1. 主控类 Main
功能:系统入口,处理用户输入和流程控制
2. 航班信息类 Flight
功能:存储和管理航班基本信息
关键属性:
航班号(no)
起降城市(departure/arrival)
航班日期(date)
最大载重(maxWeight)
3. 客户信息类 Customer
功能:存储客户个人信息
关键属性:
客户ID(id)
姓名(name)
电话(tel)
地址(add)
4. 运输信息类 ShipInformation
功能:记录货物收发信息
关键属性:
发件人信息(senderName/Tel/Add)
收件人信息(receiverName/Tel/Add)
订单号(orderId)
日期(date)
5. 货物抽象类 Goods
功能:定义货物基本属性和计算逻辑
关键属性:
货物ID(id)
名称(name)
尺寸(length/width/height)
重量(weight)
价格(price)
费率(rate)
6. 具体货物类 Cargo
功能:实现货物具体计价逻辑
7. 订单类 Order
功能:管理订单中的货物集合
关键属性:
货物列表(list)
总价(price)
8. 控制器类 Controller
功能:协调各模块并输出订单信息
9. 支付抽象类 Payment
功能:定义支付接口
10. 支付实现类 Wechat/Alipay
功能:实现具体支付方式
-
业务逻辑流程图
![]()
-
代码质量分析
![]()
-
方法与复杂度
-
Methods per Class 7.30 类平均方法数偏高
-
Average Statements per Method 3.58 方法平均长度可控
-
Most Complex Method ,Cargo.caculatePrice() 方法复杂度达24(极高)
-
Maximum Complexity 24 最大复杂度远超正常阈值,这里体现在Cargo.caculatePrice();方法上
-
Maximum Block Depth 5 最深嵌套5层,Cargo.caculatePrice();中由于计算不同区间的费率,用了多个if/else语句。
-
-
可维护性指标
-
Percent Lines with Comments 10% 注释严重不足造成可读性大大降低,关键算法、接口、复杂逻辑需补充注释
-
Method Call Statements 7.5 方法调用频率正常
-
Avg Depth 1.47 平均嵌套深度正常,因此检查局部高嵌套代码
-
2. 09题目集
- 题目:NCHU_单部电梯调度程序(类设计-第一次迭代)
本次题目模拟某客户到该航空公司办理一次货运业务的过程:
航空公司提供如下信息:
航班信息(航班号,航班起飞机场,航班降落机场,航班日期,航班最大载
重量)
客户填写货运订单并进行支付,需要提供如下信息:
客户信息(姓名,电话号码等)
货物信息(货物名称,货物包装长、宽、高尺寸,货物重量等)
运送信息(发件人姓名、电话、地址,收件人姓名、电话、地址,所选
航班号,订单日期)
支付方式(支付宝支付、微信支付、现金支付)
注:一个货运订单可以运送多件货物,每件货物均需要根据重量及费率单独
计费。
程序需要从键盘依次输入填写订单需要提供的信息,然后分别生成订单信
息报表及货物明细报表。
四、题目要求
本次题目重点考核面向对象设计原则中的单一职责原则、里氏代换原则、开
闭原则以及合成复用原则、依赖倒转原则
- 设计
![]()
- 在前一次基础上修改了客户类:
// 新增个体客户类
class Individual extends Customer {
@Override
public double discount() {
return 0.9; // 个体客户9折
}
}
// 新增企业客户类
class Corporate extends Customer {
@Override
public double discount() {
return 0.8; // 企业客户8折
}
}
// 修改Customer为抽象类
abstract class Customer {
public abstract double discount(); // 新增抽象折扣方法
}
- 支付类(由于前一次程序中已经设计成了抽象类,因此改动较少)
// 新增现金支付类
class Cash extends Payment {
@Override
public void pay(double amount) {
System.out.printf("现金支付金额:%.1f\n",amount);
}
}
- 货物类(由于前一次程序中已经设计成了抽象类,只需添加子类)
// 新增加急货物类
class Expedited extends Goods {
@Override
public double caculatePrice(double weight) {
// 加急货物费率更高
if(weight<20) price=60*weight;
else if(weight<50) price=weight*50;
else if(weight<100) price=weight*40;
else price=weight*30;
return price;
}
}
// 新增危险品货物类
class Dangerous extends Goods {
@Override
public double caculatePrice(double weight) {
// 危险品特殊费率
if(weight<20) price=80*weight;
else if(weight<50) price=weight*50;
else if(weight<100) price=weight*30;
else price=weight*20;
return price;
}
}
-
业务逻辑流程
![]()
-
订单处理流程
![]()
-
代码质量分析
![]()
Max Complexity (最大复杂度)
12 Main.main()存在过度耦合
Avg Depth (平均嵌套深度)
1.89 存在过多嵌套块
Max Depth (最大嵌套)
4 在计算不同货物的费率时存在4层嵌套,需重构
Methods/Class
5.93 类职责过重
Avg Stmts/Method (方法平均长度)
3.91 存在异常长方法
Method Call Stmts (方法调用数)
75 调用链过长,需解耦
% Comments (注释率)
6.6% 比上一次大作业要高,但是还是低于正常水平,降低了可读性。
Branch Stmts % (分支占比)
7.8% 可能缺失异常处理分支
踩坑心得
1. 明确需求然后设计
首先重要的一点是要看清题目需求,然后进行设计,再写代码。
对于雨刷系统这题,我并未注意要用接口和抽象类来实现,只是在原有基础上扩展了另一套雨刷系统,没有符合开闭原则,在下一次需求发生变化时,依旧要改动很多。并且由于逻辑差距比较大,当我发现题目理解错误时,代码较难修改,所以从头写了一遍,而且要重新考虑之前没考虑的东西,浪费了大量时间与精力。
2. 注意团队意识
其实在需求分析的时候,如果我能先于小组成员或其他同学一起探讨一下题目的需求,也不至于会犯上述低级错误,在我们的班群里,也有人提出了同样的问题,没有看清第八次题目集的雨刷题目需求,因此这题零分,正所谓团结力量大,个人的单打独斗不仅效率低下,甚至会出现考虑问题不全面的时候。而且可能有问题是团队中都有出现的,如果每个人都独自去解决,会大大降低时间效率。
4. 注释太少
每次代码注释率都在%10以下,减少了可读性,这是上一次大作业中就已经存在的问题,由此可见我的代码习惯存在问题,并且需要一段时间改正。
改进建议
-
优化数据结构
-
增加可读性
-
添加注释
在关键的方法和逻辑处添加注释,解释代码的功能和实现思路。 -
拆分职责
-
-
提高代码效率
在判断不同货物的计费方式时
拆分if/else分支,有效降低了代码的复杂度和最大深度
总结
一、主要收获
- 面向对象设计思维的提升
通过二次迭代开发,深刻理解了类职责划分与抽象类的重要性
实践了面向对象各大设计原则
- 工程化思维的建立
+ 从"能运行"到"可维护"的转变:
+ 方法平均长度优化
二. 代码质量三要素
-
可读性: 通过 添加注释提升代码理解效率
-
可维护性: 单一职责原则使模块修改时间减少一半
-
可扩展性: 在第二次迭代时,改变了需求,但是抽象类使替换成本降低70%
三. 实践出真知
-
需求分析阶段投入可节省后期调试时间
-
代码审查发现的问题中,有许多源于过早优化,下次应该先明确需求,明确代码正确基础上再修改和优化。
本次作业不仅是编码实践,更是软件工程思维的启蒙。获得了解决实际问题的能力,期待在未来作业和项目中运用这些经验以及牢记教训,打造更健壮,更高效的程序
四.课程建议
老师非常认真,对于每道题都是原创的,也会给相应的参考类图。不过我觉得对于前面的一些简单题目,可以先不给类图,让我们自己思考与设计,对于我来说,有了参考类图可能就完全按照上面的思路来进行设计,会有一点无脑写代码的感觉,其实也降低了编码的难度。可以先让我们自己设计,之后再在群里给出参考类图,来比较是否有什么可借鉴与修改的地方,然后进行优化。







浙公网安备 33010602011771号