BUAA OO 2023 第四单元博客

BUAA OO 2023 第四单元博客

1 本单元正向建模与开发

正向建模是从需求出发建立模型的过程。从某个需要解决的实际问题出发,建立模型。而逆向建模则与之相反,是从已有的某个模型出发,“套用”到某个使用场景中。在本单元构建图书馆管理系统的过程中,我们使用正向建模的方式,根据指导书给出的图书馆的功能需求编写代码建立模型。

首先有必要回顾一下基本的需求:借书,还书。在这里就较为自然的给出了Lirary图书馆类和Student学生类还有Book类的创建需求。在借还书的过程中存在一些中间对象,它们有判断借书合法性的功能要求,还有改变书的状态的功能需求(后勤处),也有暂存书的需求。所以需要对这些对象建立类。基于上述类,我构建出了本单元作业的基本框架,未曾有过大规模删减。

2 三次作业的架构设计

在三次作业中,我对指导书所提到的每个语义上的对象都建立了类。

2.1 第十三次作业

在本次作业中我除了主类一口气建立了11个类。因此我的类图也非常复杂和庞大(尽管是第一次作业)
在这里插入图片描述

从机制的设计上,我的代码编写过程比较贴合指导书(至少我是这么以为的),例如学生借书时,借还管理员或自助机器会先把书放到自身容器中暂存,再进行合法性判断,通过则借出,不通过则不借出。

唯一比较值得讨论的机制是借书的机制。我的Library类是在初始化的时候把每本书的信息记录在了图书馆中,包括书本本身的信息和数量信息(馆藏数量和当前数量),全部使用hashmap存储。每次借出图书时,根据图书馆中的图书信息进行深克隆。这点跟指导书的说明有些出入,大概是因为习惯性的认为每本书一个对象存在图书馆里面比较费空间吧(虽然知道不要求性能,但是还是觉得不太舒服)。

2.2 第十四次作业

本次作业最大的挑战在于机制的复杂性,不仅包括借书还书预定的机制,还有校际借阅和购书的机制。考虑到不同机制的耦合(比如预定和校际借阅信息的相互输出顺序和内部输出顺序,添加了校际借阅和预定对彼此的合法性判断的影响),以及机制本身的复杂性(校际借阅第二天发放书带来的种种问题,每一天结尾判断)使得代码量暴增。

在本次作业中,由于出现了学校的概念,我首先将上次作业的所有Library和Librarian类使用School封装了起来。

本次作业最大的难点其实在于校际借阅机制,因为在学校之间运输的图书有借出和还书两个方向,不同学校之间都可以产生联系。于是我设立了outBorrowLibrarian,全系统唯一,关系所有的校际运输,可以视为运输部门。

在本次作业中,“在每一天的结尾判断”这个事情变得更加的突出,因为有处理预定和校际借阅两个类型的工作。我使用了根据输入更新的办法,在主类中使用正则表达式区分出输入的各个参数,根据日期来进行判断。当某个输入与上一个输入的日期不同时,就认为前一天结束了,于是更新outBorrowLibrarian,把上一天的请求全部处理完。

由于有很多在最后一天处理的需求,所以有在outBorrowLibrarian里面建立容器的需求,我将所有暂时不能满足的需求用借书请求信息BorrowRequest封装后以队列形式在outBorrowLibrarian中(校际还书请求同理),在一天结束后的update方法中处理。

从uml图的角度来看,虽然本次作业的代码中,我的类数暴增到了17个,码量从800+暴增到1700+(跟其它同学相比完全可以说是异常的膨胀),但是总体的关联层次关系仍不算太混乱(uml图比较乱,是因为类比较多,还有不少依赖关系也被我画出的缘故)。例如outBorrowLibrarian只是与Date有关联关系(需要根据日期更新),和school与BorrowRequest和DeliveryRequest有聚合关系。school与图书馆、管理员们、后勤处关联,管理员和后勤处这些school内部的类由于协作关系存在一些关联。剩下的小型封装特性的类比如BorrowRequest和DeliveryRequest。以及最底层的功能性的类Date以及基本对象Book。总体的类的构建逻辑层次性还是比较明显的。

在这里插入图片描述

总体来说,中上层的类功能性越强,机制的复杂性在outBorrowLibrarian中达到了一个顶峰。
在这里插入图片描述

虽然outBorrowLibrarian的复杂性很高,但是它的关联(Date)、聚合关系(BorrowRequest, DeliveryRequest)却并不多,所以这个类的功能内聚性可以认为是比较高的。

在本单元的作业中,我们还画出了状态转移图。我认为这个手段(围绕书这个最底层对象分析状态变化)能够比较好的理清楚需要考虑的所有机制问题。
在这里插入图片描述

2.3 第十五次作业

本次作业的内容相对较为简单(主要是因为上次作业的机制复杂性太难绷了),增加超期检测机制即可。

我的做法是在Student类中增加记录每本书借书时间的hashmap(反正不能持有同名书籍),在还书时自查是否超期,作为参数传给自助机器和管理员。

总体来说就是加个一个属性,方法加个参数的问题。

本次作业还增加了顺序图。我的对顺序图的理解也是偏向于刻画机制。和状态图的区别在于,状态图是围绕着某个对象,通过其状态的变化,自底向上的刻画机制。而顺序图是纵观所有的上层功能类(各个管理员),从这些上层功能类的交互的角度自顶向下的刻画机制。而类图侧重于刻画整个系统的架构。在这里插入图片描述

2.4 总结

在此附上最终的类图
在这里插入图片描述

在几次作业中,我没有经历过重构,所以码量相当膨胀(1852),大概是我知道的某些极致压缩码量同学的3倍以上。
在三次作业中,我所作的主要是不断的添加功能上更高层次的类,充分的利用已有的类的功能。在几次迭代的过程中,我的类之间的关系也没有大规模的改动,改动的主要原因在于封装和添加。

在设计类的过程中,我在一开始是根据客观实在的对象设计类为主(Book,Library, Student),到后来是根据功能需求设计类为主(封装用的*Request、school,管理运输的outBorrowLibrarian),算得上是根据需求(只不过后续的需求增加主要时机制)改动设计(增加类),勉强算是正向建模了(吧?)。

3 架构设计思维演进

经历了从面向过程到面向对象,再到面向过程(bushi)的过程。
我在第一单元的第一次作业中经历了第一次也是唯一一次重构。现在看来是因为把面向对象的代码当成了数据结构的代码来写(引入了二叉树结构),给自己增加了很多能力范围无法解决的困难,最终作罢。

在电梯单元中,如何构造对象的问题被提了出来,从类图的角度来说,对象和对象的关联关系构成了代码的整个架构,架构设计不好会使得代码的实现增加很多困难,记得将电梯和电梯线程区分开,在电梯线程中把控制器单独建立类,还有建立路径规划的Guider类,这是一种功能封装的思想,有助于解决问题,使得代码更加清晰。

第三和第四单元其实可以一起说,都是一个复杂系统,第三单元是把总体架构完全指明,而第四单元是需要自己设计总体架构。这两个单元的内容我认为就是数据封装+功能封装的过程。第三单元的通信系统,我最终的功能封装仅限于一个用于图搜索的缩略图,而第四单元的功能封装更为复杂,也更为陌生。因为建图的操作在数据结构课程中已经非常熟悉了,而第四单元需要自己思考如何进行功能封装,而且也不是一个(层次的)类能够完成的。

总体来说,其实根据数据去构造类实现封装还是比较简单的,真正困难的是从需求中抽离出一条条机制,然后根据分析这些机制(过程),根据机制的要求(相互的耦合关系等等)去判断需要哪些步骤,每个步骤建立一个功能类,最终实现一个能用的系统。

4 测试思维演进

手动构造数据:在手动构造数据方面,我在课程开始时仅仅会根据特殊情况构造数据,随着课程的推进,根据机制构造数据也是非常重要的,例如在电梯单元中,手动构造瞬时大规模请求,以及各种稀奇古怪的请求序列来测试电梯性能,还有第四单元的手动构造数据来针对机制的正确性进行测试。

自动构造数据:在课程开始时,我在电梯单元与同学合作试图写了一个评测机。那个时候完全依赖随机生成,通过无脑增大数据量来保证覆盖性,是一种比较低效的行为。后来在蹭和修改本届和往届大佬们的评测机过程中,看到了有的同学在评测机种设置了几种生成数据的逻辑,我自己也会不断的调整数据的生成逻辑来完成从功能到性能的多种测试需求。最后,用好评测机也是非常重要的,调整各个参数的过程本身也需要自己对整个系统的理解,不断改变参数配置测试,才能更高效的用好自动测试。

5 课程收获总结

知识上的收获前两节已经绞尽脑汁写出来了,这一节我想说说自己的感受。我认为本门课程,就作业做好的功利性目的而言,最需要的是交流和合作。多和同学对拍,多多讨论架构的设计思路对功能和性能的提升大有裨益。知识水平(比如算法)和编码能力的差距其实可以完全被交流几乎抹平。

遗憾的是由于种种原因,在这方面做得还不够好。比如第三单元第一次作业由于其它任务的压力,没有进行足够多的测试导致强测大量失分,是一个痛点。第四单元第三次作业deadline前夕,同学找我对拍出来一个之前作业的隐藏bug,惊出一身冷汗。可想而知,如果他没有来找我,强测会是什么结果。

考虑到本系列课程的后续是软件工程,更加需要同学协作(据说是小组合作完成任务?),协作性的增加可能是学习这一系列写代码课程的同学需要注意的,相比来说,OO课程的协作(合法范围内的)只是没有显式体现在代码中罢了。再往远了说,合法的交流协作本来就是科学和技术进步,完成许多复杂工程所必须的手段。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值