272
社区成员




BUAA_OO_Unit4
“正向建模”是一种从抽象到具体的面向对象建模方法,遵循“自定向下”的设计思路。本质是通过对需求和问题的抽象设计,建立起对应的对象模型,再逐步细化为可实现的软件系统。
本单元主要设计并实现了一个简易的图书管理系统,实现查询、借阅、预约、取书、还书、阅读等功能。
Book
、Bookshelf
、ReadingRoom
、BookChecker
、BrownAndReturnOffice
、AppointmentOffice
、User
等类Dispatcher
)来封装一组对象(如 Bookshelf
、AppointmentOffice
)之间的交互逻辑(Book
的移动),避免对象直接相互引用。因此,在上文提到的若干实体类中只需要实现add
和get
方法确保书籍对象的正常移入和移出,由抽象类Dispatcher
来调用add
和get
方法实现书籍的移动Dispatcher
类和这些实体类明显是组合关系与依赖关系,实体类和Book
类是关联关系MainClass
:主类,识别指令并调用Dispatcher
类的方法
Dispatcher
:抽象中介者类,实现书籍在不同实体之间的移动,调用各个实体的方法
ReadingRoom
:阅览室类,实现阅读功能,存储阅读后未归还书籍和相应的阅读记录
BookChecker
:查询机类,查询书籍的移动轨迹
User
:用户类,存储当前用户借阅的书籍,存储当前用户的信用值
BrownAndReturnOffice
:借还处类,存储用户借阅或阅读后还回的书籍
Bookshelf
:书架类,拥有normanlBookshelf
和hotBookshelf
两个实例,存储馆内在架书籍副本
AppointmentOffice
:预约处类,有效期内存储用户之前预约的书籍和预约信息
BookRecord
:预约组合类,存储预约书籍、预约人、预约有效截止期,由AppointmentOffice
内部类分离而来
Book
:书籍类,存储当前书籍副本的id、SBN,目前所处状态(位置)、全部的移动轨迹,状态转移图如下:
在本单元的实现过程中,我发现设计建模与代码实现并非两个完全独立的过程,第一遍设计在极大程度上为后续的代码实现提供思路,但这种设计必然是不完全的,想要在设计阶段就完整地实现所有功能是不可能的。在代码实现的过程中既需要参考设计、也要思考设计中的疏漏并及时反馈到设计层面进行优化重构,在设计和实现的逐步推进下水涨船高,最终达到饱和状态即实现了目标功能
[Role]你是一个面向对象设计专家,擅长从业务场景中识别核心实体并构建对象模型。
[Objective]利用你强大的上下文信息捕捉能力,分析并抽象出关键的对象,提炼其相关的属性包装成类。注意任务的关键要求、需要抽象出的层次行为、类可能包含的成员属性
[Scenario]提供题设
[Expected Output]请你准确抽象出系统中的核心类和成员属性。
[Steps]你可以参考以下步骤:
1. 通读情景描述,识别核心业务实体对象
2. 按照对象共性的多少对实体进行分组,以抽象出分析模型中的实体类
3. 从描述中分析实体类的属性,不要使用程序化的语言精确定义属性和属性的类型
4. 如果发现复杂属性,则把这个属性抽象成为一个独立的类分离出去
[Role]你是一个面向对象设计专家,擅长从业务场景中识别核心实体并构建对象模型。
[mistake]之前的代码中没有出现主类
[Objective]反思并按格式输出类及属性,注意从准确性、完整性、必要性角度进行反思,其中核心是完整性
[Scenario]提供题设
[role]你是一名资深面向对象设计专家,擅长分析类之间的关系。现在要求你需要结合之前的公交运输管理系统需求说明和你提炼出的类,分析类之间的UML类图关系。你只需要考虑关联关系、实现关系、泛化关系。
[prompt]
你可以参考以下步骤完成:
step 1: 初步寻找关联关系
step 2: 检查找到的关系是否存在问题
step3: 修改并完善结果
step4: 按格式要求输出结果
[类3] aggregates (*)[类4]
step 5: 初步寻找实现关系
step 6: 检查找到的关系是否存在问题
step7: 修改并完善结果
step8: 按格式要求输出结果
类A名 implements 接口B名
step 9: 初步寻找泛化关系
step 10: 检查找到的关系是否存在问题
step11: 修改并完善结果
step12: 按格式要求输出结果
类A名 extends 类B名
[scenario]巩固题设
第一单元:第一单元的“多项式处理”并没有涉及到过多的设计,只是借鉴了往届同学的博客内容并结合自己的想法,边写边想。但是这样的处理方法也导致了后续第二次和第三次作业较大规模的重构,并且在迭代过程中出现了自己读不懂之前代码的情况,返工读代码导致耗时大大增加
第二单元:第二单元的电梯是我认为最难的一个单元,尤其是初次接触多线程这个概念,不用说实现、就连最基础的语法都难以理解。在这种buff叠满的情况下,继续沿用第一单元的“边想边写”显然是不现实的,于是我开始在草稿纸上手画设计思路,虽然较为简陋,但总体上与上文的正向建模法思路一致
第三单元:第三单元基本没有涉及到设计,因为官方的JML的架构已经十分完善,大部分的时间和精力都花在了性能提升上面。但是,第三单元初次将设计与实现分离开来,帮助我树立起了“设计很重要”这一意识,同时,官方的设计架构十分完善,也为我第四单元的设计与实现分离提供了具体思路
第四单元:本单元我正式与设计真正接触,在写作业的过程中我发现正向建模这一思想其实与我在第二单元的设计思路相差不大,只是利用更加工程化的方式将其真正地从实现中分离出来,但是正是一个UML的差距让两者的效果差别显著:第二单元中我的设计思路难以向室友传达,但在有了统一的表达语言之后,室友只需要看我的类图就可以明白我的大致思路,我想这应该就是UML提出的意义所在罢
第一单元:第一单元的测试我主要采用单步调试法,即利用某一个错误样例逐步查找代码的错误地方,虽然这样的方法可以更精确的找到代码的问题所在,但是相比之下效率极低且不一定可以找出全部问题。尽管效率不是很高,但是相比OOP课程时的“代码走查”还算是一个不小的提升
第二单元:第二单元的测试比较复杂,在多线程背景之下出现了BUG也无法用单步调试将问题复现,好在有比较强的室友搭建了自己的评测机,在多个样例测试的覆盖下,让问题的查找变得相对容易一些,但总体上来说没有其他方法,主要还是需要“代码走查”
第三单元:第三单元的正确性错误其实并不多,因为只要按照JML规格一步一步实现,正确性是一定可以保障的,所以问题主要集中在处理CTLE和性能提升上,同学们的基础部分实现都相差不大,所以只有个别开放性方法可能导致超时,这时不妨与同学进行实现方法交流,往往可以得出超时的原因(其实重点还是在于对JAVA语言本身的理解)
第四单元:第四单元的综合性比较强,也没有多线程这样复杂的机制干扰,所以我采用的是测评机测试与传统的“输出法”定位BUG,测试效果较好。当然,因为设计与实现的分离,架构方面导致的BUG几乎没有出现,这也是测试方便的一个重要原因
我觉得通过本学期对《面向对象设计与构造》这门课程的学习,我提升了自己JAVA语言编程能力,同时也收获了很多除知识以外的东西。
首先,通过每个单元的迭代作业,我逐步认识到代码架构的重要性。第一单元,由于边写边想的“敏捷开发”模式,我的后两次作业都进行了较大规模的重构,并且强测的成绩也差强人意,于是从第二单元开始我会在每次实现代码前想想后续作业中可能需要有所增添的地方,刻意提高代码的鲁棒性,比如在第二单元的第一次作业中,虽然并不需要总仓库-副仓库之分就可以实现要求的功能响应,但是在参考往届同学的博客之后我最终还是对其加以区分。虽然在这几个单元的少量迭代中效果不是很显著,但也为我省去了不少麻烦。
其次,为了更高的强测成绩和更好的DeBug,我学会了多种本地测试方法和DeBug调试方法,通过借用同学和室友的特殊测试样例进行测试找出了不少的问题。也学会使用测评机对代码进行覆盖性测试,确实让每次的强测成绩说得过去;互测是这门课程最有意思的部分。在互测过程中查看别人的代码让我了解的其他同学的代码风格,作为ABC房全部进过的人,我既佩服于A房大佬们代码的“固若金汤”,也因在C房“一刀中五”而高兴。在互测姓名公布之后,看到想象中“神一般”的同学竟然和我在一个C房,心中的失落也有所平衡。
在本学期的学习过程中,我也接机结识了不少原本不熟的同学,每当中测某个点过不去了,总是能在交流群中找到“同病相怜”的同学,在与他们交流的过程中,我总是可以感觉到来自计院同学的善意,我想这可以算是一大收货罢。
最后感谢幽默的荣老师、辛勤的蔡助教,还有给予我无数帮助的室友CB和WCX!