一、前言
第一阶段的面向对象程序设计作业集已全部完成。这是我们初次接触Java语言与面向对象思想,有很多收获,也有很多值得学习与改进的地方。

围绕“航空器配载与货运管理系统”这一题目,我们进行了三次代码的迭代。总体上看,三次作业题量适中,因为总是在前一次代码的基础上去完善与增加新功能,相当于时将一个复杂问题拆解为较易实现的几个阶段,所以每一次的任务量都恰到好处。我想这也是未来我们解决问题的一种方式。

难度上,不得不说每一次新的题目出现后,我都感到比上一次困难,例如需求在逐渐变得专业化而不易理解,功能的增加致使系统变得复杂,等等。但在过五关斩六将后,现在再看这几次作业,已经觉得很清晰、手到擒来了,相信我的编程思维和能力都有了一定的进步^ ^

我认为前三次作业主要的目的是提升我们对类间关系的理解,尚未涉及继承、多态等面向对象特性。因为我们刚从C语言入门编程这一领域,从面向过程到面向对象的思维转换需要一定的时间和练习。同时,我们深刻认识了面向对象五大原则(SOLID)中的单一职责原则(SRP),其要求我们在设计类的时候充分考虑每个类应该和不该“做什么”,使类设计和类间关系更合理,也是其他原则的基础。此外,老师还重点强调理解需求的重要性,这是程序设计与软件开发的重要前提。

二、设计与分析
以下我将对这三次作业的源码做简要分析与总结。

第一次作业
·要求

设计一个基础的航班货运配载模块。系统需要记录航班的基本信息。地勤人员可以按照货物重量从高到低向该航班添加货物。系统需要实时计算当前已装载的总重量,并判断是否超载。

·代码规模
1

·类图
system1
其中Input为输入类,GetTotalWeight用于获取货物总质量,GetState用于了解是否超载,LoadManifest打印装载信息

·总结

在第一次作业的需求分析和类间关系于我而言都相对较容易。

不过从类图上来看,我认为我把职责拆的有些过于零散了,例如求总质量和获取装载状态两个行为,其实可以做成Flight的方法,因为求总质量和求状态都是针对Flight的,ArrayList也是属于Flight的,没有必要单独做类。然而其实在程序变复杂以后,这样做也有了一定的的好处。希望读者可以针对职责分配问题为我提供一些意见。

我尝试将老师所说的中介思想应用到了这次的设计中,实现了Flight和Cargo两个类的解耦,这个做法在后续的系统迭代中展现了一定的优势。

第二次作业
·要求

进一步细化配载管理。飞机分为多个货舱,每个货舱有独立的最大载重和固定数量的装载位置。货物按序存入各货舱,系统需实时检查该货舱是否超载。同时记录航班整体的最大起飞重量和最大业载重量,并判断整体是否超载。

·代码规模
2
Agent复杂度过高,应将复杂的方法拆分为多个小方法;增加注释解释核心逻辑。

·类图
system2

·总结

从这一次作业开始,需求就变得复杂了很多,同时多出了CargoCompartment和Position两个实体类,如何处理好几个实体类的类间关系以及职责分配是重点需要思考的问题。我仍然选择将需要关联多个类的行为交给Agent来完成。

第三次作业
·要求

在航空器配载中,所有装载项都有其对应的力臂和力矩,并以此求得飞机的实际重心和空气动力弦(MAC)的百分比。

·代码规模
3
Builder复杂度过高,没有做好单一职责;WeightBalanceCalculator分支过多

·类图
system3
其中Builder类用来组装Flight类,InputValidator用于输入合法性校验,WeightBalanceCalculator用于相关计算

·总结

第三次作业首先在需求上就令人望而却步,大量的专业术语需要我们自己去调查研究,我想这才最接近软件开发的真实情况。同时又多了Passenger和Luggage两个实体类,由于类实在是太多了,我也没有熟练掌握中介类的用法,于是在这里放弃使用了……在以后的学习中应该再多花些时间研究中介类的使用方法。

不过到此为止,我对类间关系和职责分配的理解已经有了很大的提升,写这次作业时也觉得思路比以前要清晰很多,已有框架的基础上应该添加哪些内容、怎么添加,解决这些问题逐渐如鱼得水了。

因为Flight类目前已经变得很复杂了,尝试使用了新学到的Builder来进行组装,一定程度上使Flight的创建条理清晰。不过运用还是不够好,要继续钻研和练习建造者模式。

三、踩坑心得
首先,我认为老师说的“先做设计,再写代码”确实是十分正确的。我们习惯了C语言一条逻辑线从头顺到尾的风格,还有各种if-else、循环的嵌套,导致我们忽略了Java语言面向对象的特性。在面向对象思想下,一个程序是分块的,各部分合作来完成一个任务。于是谁来做什么、谁和谁是什么关系,弄清这个是很重要的,而且设计是做在最前面的。如果不是先画好大致的类图,而是一上来就写代码,就会导致最后整个程序越套越乱,连自己都混乱了。

我在几次作业前也画过类图,但是后来觉得和代码出入比较大,实现起来也并不像想象的那么容易,最后删除了。现在想来,如果我坚持先认真改进和完善设计,再动手实现,或许能少走很多弯路,也不必大量删改代码了。

其次,虽然不是这次作业中遇到的问题,但是我仍然印象深刻,借此机会可以记录一下。第一次测验时,由于我没有认真阅读需求,少做了一个类,尽管最后运行结果达到预期,但是设计上并没有达到要求,导致最后失了分。这严肃告诫我们需求分析的重要性,软件开发的成功与否不仅仅在于软件本身,更要看到它是否符合客户的要求,正如我们老师总爱开的一个玩笑——给空调添加一个洗衣机的功能,哪怕做的完美无缺又有什么意义呢!

此外,我在第三次作业中仍然使用了硬编码,具体是在处理前后舱的装配、计算上。这次作业只提供了这两个机舱的相关数据,所以用if-else语句可以很快解决,但毕竟不是长久之计,飞机上也不可能只有两个机舱。尽管当时做题时我有考虑到这一点,但是由于这次的迭代确实变得复杂了很多,我暂时还没能想出什么更好的解决方法,后续在代码复用性问题上还是需要更多的学习和思考。

四、改进建议
由以上图片可以看出,我的代码注释率很低,这会使代码的可读性下降,比如一段时间后再来复盘代码可能会有看不懂的情况,以及不利于以后工作中的团队协作。在之后的学习中,要培养规范写注释的意识和能力。

单一职责做的还不到位,涉及到核心业务逻辑的类复杂度非常高,应该将职责细化,拆成多个方法或做成多个类来完成。

五、总结
在第一阶段的学习中,Java语法只是很基础的一方面,毕竟我们有C语言基础,应该要做到触类旁通。更重要的是,面向对象的编程思想是一个很新颖也很重要的能力,包括面向对象的五大原则、23个设计模式等等,都需要重点学习和关注。扎实基础,拔高能力,不做井底之蛙,也不能眼高手低,作为一个概括性的学习格言铭记吧。

在此期间,我接触到了大量的工具。IDE也好,类图绘制工具也好,代码分析工具也好,都需要我们亲自探索和研究。这便是俗话所说师傅领进门,修行靠个人。从过去老师教什么学什么,遇到不懂的就扔到一边等待别人来指导,到现在自己主动去学习,学习新工具如何使用,不熟悉的界面、看不懂的术语也渐渐能够掌握一些,这个过程是艰辛却充满意义的。这也是学习原本的样子。我很高兴学到了如此重要的一课!