302
社区成员
在经过前三个单元表达式解析,多线程,JML的学习坐牢之后,终于完成了最后一项内容—UML的学习。回顾这一个学期的学习历程,我收获很多,因此本文将从以下几个方面回顾第四单元和本学期的学习内容。
在正向建模中,通常遵循以下步骤:
要将其运用到本单元的作业中,我们首先需要分析需求,详细了解待实现的图书管理系统借阅、预约、续借、整理等一系列功能的具体要求,然后设计出对应的类和类中的方法,并通过UML图初步描述整体架构(包括类的协作关系,状态转换),然后根据UML图完成代码编写,并在这一过程中对整体架构进行完善,并将其反馈在UML图上。
考虑到本单元未对架构进行大的修改,我们只针对最后一次作业进行分析。
Controller为整个系统的核心,封装了用户的所有操作和图书管理的操作;User用于存储学生的信息;Drift表示图书漂流角,存储了所有捐赠的书籍;Bookshelf表示书架,存储了图书馆内的书籍;AppointmentOffice为图书预约处,存储所有已生效的预约记录,以及用户未取书时的预约信息;ReserveData用于将书籍和预约用户进行整合,便于处理;BorrowAndReturnOffice为借还处,在存储用户归还的书籍和借阅失败的书籍之外,还存储了书籍被完整借还的次数和图书的捐赠信息。
Contoller类和User,Drift,Bookshelf,AppointmentOffice,BorrowAndReturnOffice类之间均存在关联关系,在实际运行时,Main类调用Controller类中的Simulate方法,启动整个工作过程。工作时,Controller类初始化书籍库存,读取指令并解析,获取到对应用户(如果存在),然后把相关数据发送给对应工作部门,工作部门调用对应方法后返回结果,Controller据此执行同意或拒绝操作,并调用相关方法,完成对工作部门内部状态的修改。
总的来看,这个架构允许添加工作部门与指令,有较好的可扩展性,因此在三次作业中,我并不需要进行架构上的修改。
这张状态图描述了图书状态的转化过程:图书有两种可能的初始状态,初始化到书架,或者由用户捐赠到图书漂流角。对于正式书籍,如果借阅成功则会被送至用户,如果是特定状况的失败,则会被送至图书借还处。如果被预约成功,则会被送到预约处等待用户取书,如果取书成功则会被送到用户,如果逾期则会被返还至书架。用户归还时,将书籍送到借还处,等待整理时送回书架。
非正式书籍的状态转换过程大体相似,只不过不允许预约。除此之外,如果借还次数大于二,则会被升级成正式书籍并送回书架。
由于在最后一次作业中,用户的信用积分有上限,因此必须明确整理时可能改变用户积分的行为的顺序,可能的行为如下:
考虑到某些天没有开闭馆的指令输入,我们将这些操作放在开馆整理时刻,按照扣除逾期用户信用分->送回预约处逾期书籍->送回借还处书籍的顺序执行,相应的,闭馆整理时,只需将被预约的书架中存在的书籍送至预约处即可。
在最终实现中,代码设计和UML模型设计之间呈现出良好的追踪关系,体现在以下几个方面:
第一单元的任务是表达式解析,主要考察递归下降法的使用和层次化设计。在实际设计过程中,需要考虑到表达式,项,因子(包括指数,求导等运算)之间的层次关系,并将其用类的继承,接口的实现等关系加以表示。在前两次作业中,我不知如何下手,架构设计并不是很合理。直到第三次作业,我才使用一个通用的表达式类来表达所有层级的实体,并在这个类内实现运算和化简。
第二单元的任务是电梯调度,主要考察多线程并发设计,需要解决并发访问时的冲突问题,避免死锁。在具体设计时,需要分析线程间的共享对象和同步-互斥关系,确定乘客-调度器-电梯的消息传递流程,使用syconized关键字和读写锁对并发访问加以控制。特别的,在构建等待队列时,需要使用生产者-消费者设计模式。
第三单元的任务是社交网络模拟,主要考察JML规格。在实际设计时,需要阅读规格文档,确定每种正常和异常行为的前置条件,在每种条件下分别实现规格的要求,并针对异常进行处理。特别的,在宏观上满足规格要求的同时,需要设计者采用合理的设计结构和算法优化性能。
第四单元的任务是图书管理系统模拟,主要考察UML建模。在实际设计时,需要运用正向建模思维,先分析需求,然后绘制UML图,描述类间关系(类图),书籍状态转换过程(状态图),类间交互流程(顺序图),再初步确定代码的具体实现,最后根据结果反馈对代码和UML图进行完善。
通过采用合理的实际思路,我们可以更好地保持代码高内聚低耦合的特征,提升代码的可扩展性和可维护性,同时为测试提供便利。
整个课程中,我只在第一二两个单元完成了自动评测机的搭建。
第一单元利用类似递归解析表达式的思路,递归生成表达式。为了限制表达式的复杂程度,生成数据时指数,项数,系数,括号深度均做限制,且伴随递归深度增加,内层表达式的指数,项数,系数上限均减小,且再次生成带括号因子的概率下降。比较结果时,检测合法性并调用相关python包比对结果即可。
第二单元中,我们会生成100名用户,并随机生成它们的到达时间,始发及目的地,同时,我们生成10个重置请求,并随机生成到达时间及种类,然后我们将这些内容按照时间顺序排序并输出。判断正确性时,我们将数据生成器的输入和程序代码的输出整合并按照时间排序,每获取一条就更新电梯和用户状态,并检查合法性。这一过程由python调用命令行实现,当检测到进程运行时间过长时,报错并杀死进程。
特别的,评测机也生成了部分极端数据,例如第一单元中多层括号和函数的嵌套,第二单元中同一时间内有大量乘客到来。同时,数据生成强度均略强于强测。
对于第三四次作业,考虑到第三次作业需要与其他人对拍以检验正确性,第四单元数据生成与校验比较复杂,我没有搭建评测机,决定使用DPO评测系统进行测试,但我在第三单元中对部分极端数据进行了测试,用于检验性能。
通过这一个学期的学习,我了解了测试的基本方法,掌握了多线程设计,正向建模,层次化设计等设计思路,对面向对象设计与构造有了全新且深入的理解。