275
社区成员
发帖
与我相关
我的任务
分享当指针划过凌晨三点的代码编辑器,屏幕上图书馆系统的状态迁移图终于完整闭合 —— 从书架上的书籍被预约,到用户取书时的状态变更,再到逾期未取的自动归还,每一条状态转换线都串联着三天来对架构设计的反复推演。本单元作业以图书馆管理系统为载体,在实现书籍借阅、预约、阅览等核心功能的过程中,我深刻体会到 UML 建模如何从抽象层面指导代码架构的搭建。这种从类图构思到状态图细化,再到顺序图验证的正向开发流程,恰似为复杂系统绘制精准的 "施工蓝图",让代码实现不再是盲目的逻辑堆砌,而是基于模型驱动的工程实践。
正向建模与开发是我从需求分析开始,通过创建 UML(统一建模语言)模型来设计系统结构和行为,然后依据这些模型编写代码的开发方法。在这个图书馆管理系统的开发中,UML 可以帮助我更好地理解需求、设计系统架构以及进行代码实现。下面我将结合提供的代码,详细阐述 UML 在设计过程中的作用。
类图用于展示系统中的类、类的属性和方法,以及类之间的关系。通过类图可以清晰地了解系统的静态结构,为代码实现提供蓝图。
从代码中可以识别出多个类,如Book、HotBookshelf、User、ReadingRoom、Bookshelf、AppointmentOffice、BorrowAndReturnOffice、Runner 等。每个类都有其特定的职责,例如:
Book类:表示图书馆中的书籍,包含书籍的 ID、ISBN、预约时间等属性。public class Book {
private final LibraryBookId libraryBookId;
private LocalDate appointmentTime;
private final LibraryBookIsbn libraryBookIsbn;
// ...
}
User类:表示图书馆的用户,包含用户的 ID、信用分数、借阅的书籍等属性。public class User {
private final String studentId;
private boolean isHasBBook;
private final HashMap<LibraryBookIsbn, Boolean> isHasCBook;
private final ArrayList<Book> books = new ArrayList<>();
private int creditScore = 100;
private final HashMap<LibraryBookId, LocalDate> borrowDates = new HashMap<>();
// ...
}
Runner 类与 Bookshelf、AppointmentOffice、BorrowAndReturnOffice、ReadingRoom、HotBookshelf 等类之间存在关联关系,Runner 类依赖这些类来完成图书馆管理系统的各种操作。public class Runner {
private final Bookshelf bookshelf;
private final AppointmentOffice appointmentOffice;
private final BorrowAndReturnOffice borrowAndReturnOffice;
private final ReadingRoom readingRoom;
private final HotBookshelf hotBookshelf;
// ...
}
public class Bookshelf {
private final HotBookshelf hotBookshelf;
// ...
}
LibraryBookState 枚举类型来表示书籍的状态,Runner 类中的 addTrace 方法记录了书籍状态的变化。import com.oocourse.library3.LibraryBookState;
import com.oocourse.library3.LibraryTrace;
// ...
public void addTrace(LibraryBookId bookId, LibraryTrace libraryTrace) {
if (!bookTraces.containsKey(bookId)) {
ArrayList<LibraryTrace> traces = new ArrayList<>();
traces.add(libraryTrace);
bookTraces.put(bookId, traces);
} else {
bookTraces.get(bookId).add(libraryTrace);
}
}
状态图可以清晰地展示书籍状态之间的转换条件,例如,当用户借书时,书籍的状态从 BOOKSHELF 转换为 USER;当用户还书时,书籍的状态从 USER 转换为 BORROW_RETURN_OFFICE。涉及的类
顺序图如下:

SCANNER 接收各种输入指令,包括图书馆的开门、关门指令,以及用户的借阅、归还、预约等请求指令。LibraryOpenCmd、LibraryCloseCmd、LibraryReqCmd 等),将这些指令精准地转发给 Runner 类中对应的执行方法,起到了将外部原始输入转化为对核心业务逻辑调用的桥梁作用。Runner 类承担了几乎所有核心的业务操作方法,如 handleBorrowed(用户借书)、handleReturned(用户还书)、orderNewBook(用户预约书)、handleOpenCmd(图书馆开门)、handleCloseCmd(图书馆关门)、handelQcsCmd(查询信用分)等。这些方法根据用户的请求和系统的状态,协调各个功能组件完成相应的业务逻辑。bookshelf:Bookshelf 类实例,负责管理馆藏图书,提供图书的获取和归还接口。它可以从书架上查找指定 ISBN 的图书,也可以将图书添加或移除书架。appointmentOffice:AppointmentOffice 类实例,处理预约图书的暂存和“待领取”状态。它接收用户的预约请求,当有可用图书时,将图书分配给预约用户,并管理预约图书的状态。borrowAndReturnOffice:BorrowAndReturnOffice 类实例,作为图书归还后的“临时隔离区”。用户归还的图书先存放在这里,在图书馆关门时,将图书重新放回书架。users:通过 HashMap<String, User> 管理所有学生用户的信息、借阅历史、信用分等。可以根据用户 ID 获取用户对象,对用户的借阅、归还、预约等操作进行管理。readingRoom:ReadingRoom 类实例,维护阅览室内的图书秩序。它管理在阅览室阅读的图书,确保一人一次只能在阅览室阅读一本书。handleOpenCmd 和 handleCloseCmd 方法是图书馆运作状态转换的关键节点。开门时,系统会处理预约过期的图书,分配预约图书,将热门图书移动到正确的书架;关门时,系统会将归还的图书放回书架,对未归还的阅读图书进行扣分处理。PRINTER 工具,向外界播报处理结果,包括借书、还书、预约等操作的成功或失败信息,以及图书的移动信息等。ArrayList<Book> 存储所有图书,提供了按 ISBN 查找图书的方法。同时,通过 HotBookshelf 管理热门图书。ArrayList<LibraryReqCmd> 存储预约请求,HashMap<String, ArrayList<Book>> 存储已分配给用户的预约图书。ArrayList<Book> 存储归还的图书。HashMap 管理用户的借阅信息和信用分,如 HashMap<LibraryBookId, LocalDate> 存储借阅日期,int 类型的 creditScore 存储信用分。ArrayList<Book> 存储在阅览室阅读的图书。Runner 类对应设计中的 Library 类,承担核心业务逻辑的调度和管理;Bookshelf、AppointmentOffice、BorrowAndReturnOffice、ReadingRoom 等类与 UML 模型中的功能组件层的类相对应,负责具体的业务功能实现;Book 和 User 类对应数据实体层的类,存储核心数据。Book 类在类图中定义了图书的基本属性,如 ID、ISBN 等,在代码中也有对应的成员变量和访问方法;Runner 类在类图中定义了各种业务操作方法,如借书、还书、预约等,在代码中都有具体的实现逻辑。Runner 发送预约请求,Runner 检查用户资格后将请求转发给 AppointmentOffice,AppointmentOffice 处理请求并分配图书。在代码中,Runner 类的 orderNewBook 方法实现了用户资格检查和请求转发,AppointmentOffice 类的 addReq 和 getOrderedBooks 方法实现了请求处理和图书分配。Runner 类调用 AppointmentOffice 类的方法,AppointmentOffice 类调用 Bookshelf 类的方法,这些方法调用对应了顺序图中的消息传递,确保了系统的交互逻辑正确执行。LibraryBookState 枚举类型表示图书的状态,Runner 类的 addTrace 方法记录了图书状态的变化,确保了图书状态的正确转换。
在使用大模型辅助正向建模的过程中,我发现引导大模型在复杂场景中完成架构设计任务需要一定的技巧。
首先,要明确清晰地描述问题和需求。在设计图书馆管理系统时,需要详细说明系统的功能需求,如书籍的借阅规则、用户的信用积分计算方式等。只有让大模型充分理解问题的背景和要求,才能得到更符合预期的架构设计。例如,我们需要向大模型说明不同类型书籍的借阅期限不同(如 B 类书籍借阅期限为 30 天,C 类书籍借阅期限为 60 天),以及用户信用积分的增减规则(如按时归还书籍加分、逾期归还扣分等)。
其次,可以通过提供示例和约束条件来引导大模型。在描述需求时,可以给出一些具体的业务场景示例,让大模型更好地理解系统的使用方式。同时,设定一些约束条件,如系统的性能要求、代码的可维护性要求等,帮助大模型生成更合理的架构设计。例如,在设计图书馆管理系统时,可以给出一些具体的借阅、归还场景示例,以及要求系统在处理大量请求时的响应时间不能超过一定阈值等约束条件。
此外,与大模型进行交互和反馈也是非常重要的。在大模型给出初步的架构设计后,要对其进行评估和分析,指出其中存在的问题和不足之处,并向大模型提供反馈。通过多次交互和调整,逐步完善架构设计,使其更加符合实际需求。例如,大模型给出的架构设计可能在某些模块之间的交互逻辑不够清晰,我们可以及时反馈给大模型,让其进行调整和优化。
经过四个单元的训练,我的架构设计思维经历了从基础的面向过程实现到基于UML建模的系统化架构设计的显著演进。这种演进不仅体现在代码结构的优化上,更反映了我对软件设计方法论的理解和应用能力的提升。
在表达式解析单元,我的设计主要基于面向过程的思维。核心思路是将表达式解析分解为词法分析、语法分析和表达式计算三个主要步骤。我使用了简单的字符串处理和递归下降算法来实现表达式的解析和计算。
这个单元让我深刻认识到良好的架构设计对于软件系统的重要性。面向过程的设计虽然简单直接,但在处理复杂问题时显得力不从心。我开始意识到需要引入更系统化的设计方法来提高代码的质量和可维护性。
在多线程电梯单元,我开始尝试使用面向对象的设计方法。将电梯系统抽象为电梯、乘客和调度器三个核心类,通过类之间的协作来实现系统功能。引入了生产者-消费者模式来处理乘客请求和电梯调度之间的关系,提高了系统的并发处理能力。
synchronized关键字、wait/notify机制)来处理多线程环境下的共享资源访问问题。第三单元围绕JML(Java Modeling Language)规格展开,我的设计重点是理解和实现JML规格定义的接口和方法。通过严格遵循JML规格,确保代码的正确性和可靠性。在实现过程中,注重使用合适的数据结构和算法来满足规格要求,同时考虑代码的性能和可维护性。
在第四单元的图书馆管理系统中,我全面采用了UML建模的方法进行架构设计。从需求分析开始,通过类图、顺序图和状态图等UML工具,对系统进行了全面的建模和设计。在实现过程中,严格遵循UML模型的设计,确保代码与设计的一致性。
在软件设计与实现能力提升的过程中,我的测试思维与方法经历了从简单到复杂、从零散到系统、从手动到自动化的显著演进。最初采用手工样例测试,通过编写简单测试用例、手动输入并验证结果来进行基础功能验证,但这种方式测试覆盖度低、依赖个人经验且重复测试效率低下,难以发现复杂交互中的问题。随着学习深入,我开始关注边界条件与异常处理测试,运用等价类划分、边界值分析等方法,结合自定义测试框架和断言机制,有效提升了代码的健壮性。
随后进入自动化测试框架应用阶段,引入 JUnit/OKTest 单元测试框架,实现测试用例的参数化与数据驱动,并借助测试覆盖率分析工具量化测试覆盖度,大幅提高了测试效率与覆盖度。同时,我还掌握了基于规格与模型的测试方法,依据 JML 规格驱动测试,利用 OpenJML 等工具验证代码与设计意图的一致性,建立了从需求到测试的完整追溯链。
当我按下文档保存键的那一刻,面向对象程序设计的课程之旅已悄然行至尾声。回望四个单元的代码交锋与架构思辨,OO 赠予我的早已超越编程语言的语法边界 —— 这是一场从线性思维到对象建模的认知跃迁,一次用类图与状态图解构复杂系统的思维淬炼,更是一段在代码迭代中触摸软件工程本质的探索之旅。那些深夜调试时 IDE 闪烁的光标、UML 图上反复修改的关联线、测试用例通过时的如释重负,都化作理解软件设计哲学的密钥。
在此,我要向课程组的老师们与助教团队致以诚挚谢意!是你们用精心设计的单元任务搭建起阶梯式的成长路径,让表达式解析的递归下降、多线程电梯的并发控制、JML 规格的形式化验证、UML 建模的正向开发依次成为思维进阶的里程碑。尽管赶作业的日子里常与凌晨的代码编辑器相伴,但当看到图书馆系统的状态迁移图在屏幕上完整闭合时,方知那些为架构设计苦思的时光,早已内化为分析复杂问题的底层能力。
这趟 OO 旅程的终点站并非学习的终结,而是面向对象思维的新起点。当我开始用类的封装性思考模块边界、用状态图推演业务流程、用测试驱动验证设计意图时,便已察觉这门课赋予的不仅是编程技巧,更是用工程化思维拆解世界的认知框架。