OO - 第四单元总结 - 博客作业- 79066020 路凯

单元题目介绍和说明

在第 4 单元中,我们学习了 UML 的基本结构、类图、序列图和状态图及其关系。在本单元的作业中,我们设计并编写了一个图书馆系统。

第四单元作业图书馆内所有图书均采用“类别号-流水号”的形式进行编号,图书分为A、B、C三类,每类图书可能包含多本,每本图书可能有多本。在第四单元作业一中,图书馆开放时图书馆管理系统需要处理的请求包括:借书、还书、查询、预约、预约取书。在作业二中增加了续借、图书漂移等功能,在作业三中我们为学生实现了信用评分制度。在这篇博客文章中,我将分享我在第 4 单元的设计和代码,并总结我在面向对象编程课程中的经验。

第四单元的正向建模与开发总结

在第四单元,我们通过StarUML和UML语言完成了正向建模的作业。正向建模是一种在软件系统开发的早期阶段,基于需求和设计文档等资料,使用建模工具进行系统设计和建模的方法。这种方法根据需求、设计和代码之间的关系来构建模型,并图形化展示系统结构和行为。使用UML,我们可以在开始编写代码之前设计整个项目,这样我们能够更好地可视化类及其关系,更容易发现设计问题和挑战。在第三单元中,我们需要根据代码描述实现代码,而这次在第四单元的作业我们需要自己进行设计,然后尽量坚持设计,只为其实现代码而不做相关更改。

在我们的一节研讨课上,我们甚至讨论了这种系统设计方法是否与敏捷方法冲突(Agile Manifesto),大多数同学认为良好的系统设计是一种好的实践,尤其是在项目开始阶段,如果你在一个团队中工作,这对于同步所有人的实现和所需功能非常重要,如果设计做得不好使用敏捷方法也不会有很大的优化空间。

架构设计与分析

在第四单元的第一次作业中,我花了很多时间考虑和绘制不同的设计。我最初考虑使用StarUML开始我的设计,但发现最好先在纸上写下问题描述和相关细节,然后用笔绘制类和对象抽象。接着,我会思考每个类的职责。

在这里插入图片描述

在这里插入图片描述

只有在我对已有的类感到满意并知道每个类的职责后,我才开始在StarUML上设计它们的方法和关系。

在这里插入图片描述

我的计划是创建一个Transaction类,用于处理每个请求的数据。然而,当我查看官方包的代码时,我意识到这是不必要的。Library累将负责处理请求。Inventory累作为一个库存将保存预约柜台(ReservationDesk)、借阅柜台(BorrowDesk)和书架(BookShelf)的相关数据,而Student、Book和BookCopy类则是其现实生活对象的抽象。

第四单元的第一次作业

由于这是第四单元的第一次作业,尽管我对我的设计进行了大量思考,并且在最终确定之前进行了多次迭代,但初始的UML设计和最终的UML设计有很大差异。在编码过程中,我意识到我低估了系统的复杂性。使用库存和不同状态的图书映射来实现图书馆操作(借阅、预约和取书)效率不高。最终,我将系统分为预约区和借阅区,并决定将预约的副本存储在预约者内。到项目结束时,我对设计并不满意,感觉想从头开始,但临近的截止日期不允许我这样做。因此,我决定在为下一次作业实现新功能之前重构设计。

在这里插入图片描述

第四单元的第二次作业

在第二次作业中,我们需要添加图书漂移角、图书捐赠操作和图书续借。尽管这些是添加而非更改,但我最初的代码设计并不理想,所以我决定在开始实现新功能之前对其进行重构。这也使得第三次作业更加轻松。设计的主要变化如下:

  • 添加BookCollections对象:这有助于组织同一本书的所有不同副本。我们不再将List作为存储副本的HashMap的值,因为这样管理起来很复杂,而是添加了一个抽象层。
  • 添加Reservation对象:在上一次作业中,我使用LinkedHashMap将学生作为键、书籍列表作为值来控制预约。这很难管理并导致了一些错误,比如无法保证预约的顺序。现在,ReservationsDesk有一个Reservations列表,每个Reservation对象包含所有关于图书和预约学生的信息。这保证了预约的顺序。
  • 添加StudentManager:这个添加并没有对代码产生很大的影响,但它更好地划分了职责。现在,每次有学生编号发出请求时,我们将编号发送给StudentManager,它返回该学生。这样,我们就不必在Library类中检查学生是否存在并创建新学生。
  • 改进辅助方法和移除冗余方法

下面是单元第二次作业的UML累图
在这里插入图片描述

以下是重构后一个方法变得多么简单和清晰的一个示例, ReservationDesk把过期预约的书退回BookShelf的moveBooksToInventory方法:

改代码前

public Collection<? extends LibraryMoveInfo> moveBooksToInventory(LocalDate date) {
        List<LibraryMoveInfo> moves = new ArrayList<>();
        Iterator<Map.Entry<Book, List<BookCopy>>> iterator =
            reservationAreaBooks.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<Book, List<BookCopy>> entry = iterator.next();
            Book book = entry.getKey();
            List<BookCopy> copies = entry.getValue();
            Iterator<BookCopy> copyIterator = copies.iterator();

            while (copyIterator.hasNext()) {
                BookCopy copy = copyIterator.next();
                if (copy.isOverdue(date)) {
                    inventory.receiveReturnedBookCopy(copy);
                    moves.add(new LibraryMoveInfo(copy.getBook().getBookId(), "ao", "bs"));
                    copyIterator.remove();
                }
            }

            if (copies.isEmpty()) {
                iterator.remove();
            }
        }
        return moves;
    }

改代码后

public Collection<? extends LibraryMoveInfo> moveBooksToInventory(LocalDate date) {
        List<LibraryMoveInfo> moves = new LinkedList<>();
        for (Map.Entry<Book, BookCollection> entry : reservationAreaBooks.entrySet()) {
            BookCollection collection = entry.getValue();
            List<BookCopy> overdueCopies = collection.getOverdueCopies(date);
            for (BookCopy copy : overdueCopies) {
                inventory.receiveReturnedBookCopy(copy);
                moves.add(new LibraryMoveInfo(copy.getBook().getBookId(), "ao", "bs"));
            }
        }
        return moves;
    }

这个重构过程非常重要,不仅使第二次作业的添加更加清晰和易于实现,还对第三次作业产生了巨大影响。

第四单元的第三次作业

由于我已经对第二次作业的代码进行了重构,在第三次作业中,我基本上不需要修改代码,只要添加新的辅助方法,并根据作业要求在处理请求之前实现了信用评分系统检查。大多数添加都在Student类中,以跟踪学生的分数及其最大限制。在这次作业中,对预约要求进行了更改,我们必须确保学生不能对同一本书有多个有效预约。为了处理逾期归还图书和扣分问题,我添加了一个returnDueDateMap来跟踪图书应归还的日期。如果它们被续借或归还,地图会更新。通过在开馆和闭馆时间检查所有早于“今天”的日期键,我们可以从这些学生的分数中扣除。

在这里插入图片描述

课程收获

这个学期,我学到了很多,不仅是关于Java编程、UML和JML,还包括代码开发设计、问题解决、重构和调试。我尝试独立学习一些设计模式,但由于作业的截止日期紧迫,在这方面很难取得太大进展。我优先学习了重构和良好的实践。对于其他希望学习这方面的学生,我强烈推荐 Refactoring and Design Patterns。我买了他们关于设计模式的书,计划在暑假期间阅读。

我们的实验课是熟悉每个单元内容的好机会,然后再提交我们的作业代码。由于大多数实验要求我们完成代码,我们学习阅读和理解他人的代码,有时从实验代码中获得实现作业的想法。在讨论课上,我们有机会与其他同学讨论在编写作业代码时遇到的挑战,并分享我们解决问题的想法。

在我看来,结合我从其他学生那里听到的意见,面向对象编程是计算机科学中最难的课程。这是一个紧张的学期,我们面临着按时完成作业和不遗漏截止日期的巨大压力。我相信我学到了很多,如果我能向我们的教授提出一个建议,那就是改变我们学习单元的顺序。将JML作为第一个单元将帮助学生理解设计和编码实践,然后使用UML设计我们自己的系统。在这两个单元之后,设计第一单元的解析器和处理第二单元的线程将会容易得多。

  • 19
    点赞
  • 48
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值