301
社区成员
发帖
与我相关
我的任务
分享第四单元的任务为利用UML进行建模设计,完成一个能处理各种请求的图书馆管理系统
· hw13实现了支持指定日期开馆闭馆、支持用户查询、借书、还书、预约和取书请求和图书转运的图书馆管理系统,并用UML类图进行设计
· hw14新增了图书的捐赠和续借,以及热门图书升级的逻辑,同时需要用UML类图进行设计并用UML状态图对图书行为进行建模
· hw15新增了用户的信用积分和与积分相关的限制,同时在UML类图、UML状态图的基础上,新增了UML顺序图对图书馆和用户的交互行为进行建模
本单元的正向建模主要聚焦于UML图的绘制,通过UML类图、UML状态图和UML顺序图来从多个角度对图书馆管理系统进行设计
UML类图用于从顶层设计类之间的关联关系,指导了整个系统中关键的组成部分,如图书馆、书、用户等实体之间的关系,从而约束了代码实现时类的内部行为与类与类之间的交互行为。
UML状态图主要建模了图书在其整个生命周期中的状态,在我的设计中即为图书所处的位置。通过设计图书所处位置以及转移的方向和条件,可以为实现时涉及到图书转移的行为进行约束。
UML顺序图则建模了图书馆与用户间的交互流程,通过消息传递顺序,直观地展现了图书馆响应用户请求的逻辑。
图书馆系统顶层的架构设计以及实体间的关系由UML类图来建模表示,如下图所示

用户类为Person,图书馆类Library负责与其进行交互,接受并响应请求。Library中有四个存放图书的实体,分别是书架bookShelf(直接作为Library的属性)、借还处BorrowReturnOffice类、预约处AppointmentOffice类和图书漂流处bdc(也是Library的属性)。由于用户和每个存放图书的实体对于图书的存取查找都有统一的操作,因此将这些操作封装进一个图书管理容器类BookContainer,实现这些操作间的高内聚,而每个拥有图书的实体都由该类的一个实例来进行图书管理操作。另外,Record类用于记录预约相关的信息。
图书的状态转移由UML状态图表示,如下图所示

在图书生命周期的最开始,图书可以被初始化至书架,也可以由用户捐赠至漂流处。之后,通过用户借书请求,图书会被送至借还处或用户手中,或通过预约请求在书架与预约处之间转运,并由取书请求转移至用户手中。最后,用户还书后图书会先转移至借还处,再根据图书属性归还至书架或漂流处,非正式书架也可能在这一过程中得到升级,进入书架。
图书馆与用户的交互流程由UML顺序图来描述,下图展示了从预约到取书场景的主要流程

最终的代码实现上,类的设计与类间的关系与UML类图保持了完全一致;UML状态图则从较宏观的角度描述了代码实现中方法调用的逻辑,也即图书转移部分的代码在UML状态图的框架下进行实现,并细化了其中的逻辑;对于UML顺序图约束的预约和取书场景,也由代码中对应的方法完成了实现
第一单元的主题是表达式解析并化简,观察到表达式、项和因子都可以归为一个统一的形式,因此我设计了一个通用的类来进行封装,表示文法中所有层级的实体,所有的运算也是由该类对象进行。这样的统一封装有效地减少了表达式解析和化简时的冗余代码,也减小了调试的难度。
第二单元的主题是多线程和调度,涉及到并发访问资源,主要问题在于解决并发冲突和避免死锁。通过从宏观交互行为上对主线程、调度器和电梯线程进行时序建模,分析各个行为逻辑中资源的并发访问情况,来预防潜在的冲突和死锁。
第三单元的主题是在指定的JML规格下实现符合约束要求的代码。在宏观的架构设计上保持和规格的约束一致,在微观上则进行数据结构的设计,使代码实现在符合规格的情况下,尽可能优化性能。其中包括并查集优化、预先求值、延迟更新等。
第四单元的主题是UML正向建模指导代码实现。通过事先用UML进行宏观架构(类图)、主要逻辑的架构(状态图)和类间交互流程(顺序图),来对真正的实现进行预先规划,也即正向建模。通过正向建模,在建模阶段进行高内聚、低耦合的行为和关系设计,来使代码实现的思路变得清晰。
第一单元,需要测试表达式化简的正确性。我按照文法随机生成初始表达式进行化简,同时使用现有求解器判断化简前后表达式是否等价。通过多组随机生成的数据进行代码测试,来增加验证强度。第二单元,需要检测电梯运行的行为是否出现异常,测试用例的输入仍为随机生成,而在解析输入和输出时,使用Python进行OOP设计,搭建简化的模拟运行环境,在解析时同时模拟局面,对于每种可能的错误情况加以判断,当探测到某处输出与模拟局面不符时报错,同时加入了对TLE,即死锁或不合理的调度的判断。第三单元,由于对于同样的输入仅有唯一的输出,因此可以使用对拍的方式,在多轮随机测试用例中对测试代码和标准代码(假定某个人的代码实现是正确的)进行比较查找是否存在不一致,同时,对随机生成的指令概率分布使用一个向量进行控制,增大极端情况出现的概率。第四单元,需要测试图书馆行为的正确性,由于不同的实现方式有不同的输出,因此需要用类似第二单元的模拟环境进行测试,同时使用Python subprocess运行测试代码,用管道与之进行交互。
综上,在测试中我使用了归约验证、模拟、对拍等多种因地制宜的测试方式,并通过多轮随机数据加强测试的强度,并在一定程度上控制随机输入的分布。除此之外,还会单独设计一个生成器,生成更加极端的情况,测试某些性能表现或罕见情况是否正确。在这个学期中,我将每单元的测试都部署在了自己搭建的在线评测服务器上,开放给全年级同学使用。在设计每次作业的评测机时,也在细化自己对于作业要求的理解,并通过同学的反馈和测试结果对自己的理解和实现进行改进。
终于结束了。
本学期课程让我在一次次作业中从0开始学会了Java的基本用法,也让我掌握了面向对象的一些设计模式和建模分析方法。
不过最让我有成就感的是我与同学合作搭建的DPO评测系统,我们的评测机覆盖了全部的12次代码作业,有200多名同学注册使用。在整个学期的每次作业中,这个平台也在不断的迭代,从最初的仅有评测接口,到加入了选择作业、更美观的UI、多线程评测排队和自测等外观和功能的更新。对我个人来说,搭建评测机不仅能让我更加细致的去考虑和理解作业中的每一条要求,也能让我在同学对平台的反馈中对自己的代码查缺补漏。而对广大同学们来说,DPO为他们提供了面向数据调试的机会,让许多同学在强测前及时发现了代码中的漏洞,避免了强测出错时的心 肺 停 止,我觉得这便是我们工作的意义所在。尽管有时评测机出现了异常,或者没能及时测出来隐藏很深的bug,带来很多打击,但我们始终坚持着完成每次作业的评测机的开发,并及时响应同学们的问题反馈,及时修正。我能够一人身兼PM、开发、运维、测试、客服等数职并坚持一个学期,也离不开同学们的支持与鼓励。可以说,OO课程和作业教给了我一些理论知识,而这个平台的开发与维护,才让我在实战中深刻的体验了OO以及软件工程中的设计、开发、迭代与团队协作的思想或方法论,实在是受益匪浅。