Contents

BUAA-OO-Unit4总结

Contents

总结本单元所实践的正向建模与开发,重点分析两阶类图在正向建模过程中的作用。

本单元实践的是典型的“先建模、后实现、再回溯修正模型”的正向开发过程。面对图书馆管理系统这种规则密集型场景,如果一开始直接写代码,很容易把借书、还书、预约、取书、阅读、归还、评分、续订、信用分、整理流程等逻辑揉在一起,后期新增规则时会不断进行重构。 两阶类图在这个过程中起到了不同作用: 第一阶类图主要偏向“设计蓝图”。它的重点并非一次把所有方法全部设计出来,而是从需求中识别核心对象,提前确定系统边界:哪些类负责保存状态,哪些类负责处理请求,哪些类表示图书馆中的物理位置,哪些类表示业务规则。第一阶类图的价值在于防止需求直接侵入主流程,使后续编码有稳定的职责划分。 第二阶类图则是实现中的修正。随着代码实现,原先抽象的职责会被细化,例如新增信用分后,User 不再只是持有图书和预约,还要维护 creditScore,并提供 canBorrow、canOrder、canRead 等判断;新增续订和逾期后,BookCopy 需要维护 dueDate、overdueDeducted 等状态;新增精品书架后,Book 要维护评分,Arranger 要根据评分把副本移动到普通书架或精品书架。第二阶类图的作用就是把最终代码中的真实结构反映回 UML,使 UML 不只是前期设计文件,而是可以和代码互相追踪的架构文档。

总结本单元作业的架构设计,并对比分析最终的代码设计和UML模型设计之间的追踪关系。

架构设计 RequestHandler 负责把官方命令分发为具体业务操作,并调用 PRINTER 输出结果。LibrarySystem 是系统核心,统一管理用户、图书副本、预约、各个图书馆位置以及移动记录。它对外提供 borrowBookreturnBookorderBookpickBookreadBookrestoreBookrenewBookgradeBookqueryMovingTrace 等接口。
图书相关对象被拆成两层:Book 表示同一 ISBN 的抽象图书,负责类别和评分;BookCopy 表示具体副本,负责副本编号、当前位置、预约保留、借阅期限、逾期扣分标记和移动状态。这样可以同时满足“按 ISBN 管理评分/类别”和“按副本管理流转轨迹”的需求。
图书馆位置类包括 Bookshelf、TreasuredBookshelf、BorrowAndReturnOffice、AppointmentOffice、ReadingRoom。它们承担容器职责,保存不同状态下的图书副本,并提供添加、移除、查询、借出等操作。Arranger 专门负责整理流程,包括清理过期预约、满足预约、将借还处/阅览室图书归架、按评分调整普通书架和精品书架。TraceRecorder 与 MoveRecord 负责记录和查询移动轨迹,保证查询流程不污染普通业务逻辑。
追踪关系
类名和领域概念基本一一对应。需求中的“用户、图书、副本、预约、书架、预约处、借还处、阅览室、整理、移动轨迹”等概念,都能在 UML 和代码中找到对应类。
方法和业务流程对应。UML 中的 borrow、return、order、pick、query、arrange、read、restore、grade、renew 等操作,在最终代码中分别落实为 LibrarySystem 和 RequestHandler 中的方法,并进一步委托给实体类或位置类完成状态修改。
关联关系和运行时依赖对应。LibrarySystem 聚合各个位置对象、用户集合、订单集合和图书副本集合;Order 关联 User 和被预约的 BookCopy;BookCopy 关联 Book;Arranger 依赖 LibrarySystem 完成跨位置移动;TraceRecorder 记录 BookCopy 的移动历史。这些关系既能从 UML 中表达,也能在代码字段中追踪到。
当然,最终代码相比初始 UML 通常会有一些演化。例如为了适配第三版官方包和新增需求,代码中加入了 TreasuredBookshelf、ReadingRoom、BorrowLimit、信用分、续订、逾期处理等实现细节。这说明第二阶类图不应机械照搬第一阶类图,而应反映实际开发后稳定下来的结构。

根据使用大模型辅助正向建模的体验,总结分析如何引导大模型在复杂场景中完成架构设计任务。

使用大模型辅助正向建模时,关键不是让它“直接生成完整架构”,而是要把复杂场景拆成可验证的建模任务,并持续约束它的输出。 首先,要让大模型先读需求并提取领域词汇,而不是马上写类。比如本单元应先识别:图书、图书副本、ISBN、用户、预约、信用分、书架、精品书架、预约处、借还处、阅览室、整理、移动轨迹、借阅限制等核心概念。这样生成的类图才会贴近题目,而不是套用普通管理系统模板。 其次,要明确职责边界。可以要求大模型按“实体类、服务类、容器类、规则类、记录类”分类设计,并说明每个类为什么存在。复杂业务中最容易出问题的是职责混乱,例如把所有逻辑塞进 Main 或 LibrarySystem。通过提示模型关注单一职责,可以让架构更稳定。 再次,要让模型围绕变化点设计。本单元的变化点包括新增信用分、续订、逾期、精品书架、阅读流程等。因此在提示中应强调:“设计要便于扩展新请求类型和新图书状态”。这样模型更可能抽象出 RequestHandler、Arranger、BorrowLimit、TraceRecorder 等辅助结构。 最后,要用代码反向校验 UML。大模型生成的 UML 往往看起来完整,但可能和真实代码脱节。因此二阶建模时应要求它根据最终代码重新梳理类、字段、方法和关联关系,并检查需求关键词覆盖率。这样 UML 才能成为可追踪的工程文档,而不是一次性提交物。

总结自己在四个单元中架构设计思维的演进。

  • 第一单元,我只是根据课程组的提示和AI的教程,说我们需要一个Parser,所以就有了Parser Package;然后说还需要有一个Lexer,随后就有了Lexer Package。然后告诉我,你可以递归地去解析,于是就有了parseExpr、parseFactor、parseTerm。这里只是一步步地,按照“应该有什么”的思路组织代码,并没有一个统一的架构思维。
  • 第二单元,核心在于多线程编程。在面对“生产者-消费者”模型时,我第一次有了概念——哦,原来模块与模块之间,还可以这样交互。于是我便不只局限于某一个具体的功能、具体的方法,而是试着去想每个线程可以怎么交互,会出现什么样的问题。——这也给后来OS去理解同步、互斥、进程与线程等内容提供了基础。
  • 第三单元,面对长长的JML代码段,我意识到,原来写代码并不一定只能用自然语言去描述程序的行为、目标,还可以在写代码之前用这样的规格化设计来完成代码行为的约束。而且,这样的做法,在AI时代似乎更显露出他的用处——一段正确的JML,绝对可以严谨无歧义地告诉AI我们的代码需要实现什么样的功能。AI:终于不用对着人类那一坨自己都不知道在说什么的话猜来猜去了。
  • 第四单元,开始学着在写代码之前,通过画UML图来进行整体的设计,并在实现时对UML进行适当的细化和补充。这无疑是将“架构设计”这个事情彻底从写代码分离出来,变成一个我们在写代码前必须想清楚的事情。这,似乎就是“架构思维”吧。

总结自己在四个单元中测试思维的演进。

  • 第一单元,开始尝试使用AI构建数据生成器进行评测。
  • 第二单元,靠着AI和同学的帮助,使用多线程的评测机进行大量的压力测试。
  • 第三单元,在JML的基础上构建JUnit。

总结自己的课程收获。

  • 架构思维与迭代能力 课程中,随着每一次的迭代开发,架构思维和迭代能力有所提升。
  • Vibe Coding 使用AI的方法从开始直接扔指导书到后来学着写需求文档,用尽可能规范的语言把需要AI做的工作、工作的流程、需要遵循的规范、绝对不能做的事情有条理地表述清楚。