OO 第四单元总结 & 课程回顾

彭程-24373403 2026-06-19 20:03:06

OO 第四单元总结 & 课程回顾

一、正向建模实践:两阶类图的角色

第四单元要求先画一阶类图(uml_pre.mdj),再写代码,最后修正为二阶类图(uml_ultimate.mdj)。这种"先设计后实现"的流程与前三单元"拿到规格直接写代码"截然不同。

一阶类图的作用是"骨架设计"。在还没写代码时,我需要思考:图书馆有哪些核心实体(书、用户、书架)?它们之间的关系是什么?谁来管理移动?这种思考迫使我先理清类之间的职责边界——比如"信用分管理"是放在 User 里还是抽一个 CreditManager?一阶类图阶段我选择了后者,因为信用分的阈值、增减规则是一套独立逻辑。

**二阶类图的作用是"修正与对齐"**。写完代码后回头修正类图,我发现一阶设计中有不少遗漏:BookCopy 需要 dueDate 字段(借阅期限),User 需要 currentReading 字段(阅读状态),LibraryManager 需要多个 arrange 辅助方法。这些是在编码过程中才暴露出来的细节。

两阶类图的核心价值在于:一阶定方向,二阶校细节。一阶防止"想到哪写到哪"的混乱,二阶保证"图与代码一致"。R5 的关联关系检查(代码有引用则类图必须有线)尤其体现了这种一致性约束。

二、架构设计与 UML-代码追踪

本单元的核心架构:

Main → LibraryManager → { Bookshelf, TreasuredBookshelf, ReadingRoom,
                           BorrowAndReturnOffice, AppointmentOffice }
                      → CreditManager
                      → Map<Isbn, Book> BookCopy
                      → Map<String, User>

设计要点

  • LibraryManager 作为中心调度者:所有请求(借/还/预约/取/读/归还/评分/续订)都由它分发到各地点类处理
  • 地点类职责单一:Bookshelf 只管理书的进出,ReadingRoom 只管理阅读状态,AppointmentOffice 只管理预约和保留期
  • CreditManager 独立:信用分阈值和增减规则与图书馆业务解耦,便于修改阈值
  • Request 继承体系:BorrowRequest、ReturnRequest 等 9 个子类统一继承 Request,Main 中 switch 分发

追踪关系对比

UML 元素代码实现一致性
LibraryManager → Bookshelf (1:1)private Bookshelf bookshelf
Request ← BorrowRequest 等 9 子类extends Request
Book → BookCopy (1:1..*)List<BookCopy> copies
User 属性 creditprivate int credit
CreditManager 方法 canBorrowOrOrder()credit > 80 判定

UML 类图最大的价值是让人一眼看清类之间的依赖关系。不用读代码,看类图就知道 LibraryManager 依赖 7 个地点类和 User/Book 两类数据。

三、大模型辅助正向建模的体验

本单元我使用大模型辅助 UML 绘制和代码调试。

有效的使用方式

  1. Mermaid 生成类图骨架:用 Mermaid 语法描述类和方法,通过 StarUML MCP 一键生成类图
  2. 增量补丁:Mermaid 无法生成的 UML 模型元素(navigable、multiplicity),用 Python 脚本批量修补
  3. 随机测试脚本:让模型写 Python 评测机,自动生成随机输入并验证业务逻辑一致性

踩过的坑

  • 大模型容易过度修改。我让它修一个 bug,它却重构了整个 arrange 方法,引入新错误
  • StarUML Mermaid 导入的属性名/类型会反转(int credit → name=int, type=credit),需要 Python 脚本修正
  • 大模型在某些边界条件上的判断不准确(如 overdue 触发的时机是 date > dueDate 还是 date >= dueDate),需要人工仔细阅读规格

引导大模型的策略

  1. 分步骤给任务:先画类图结构,再补方法,最后修关系,不要一次全给
  2. 读指导书后再提问:让模型先通读规格,再问具体问题,减少凭空猜测

四、四个单元架构设计思维的演进

单元主题核心设计思维
U1表达式解析递归下降 + 数据结构抽象(TermBasis),学会"用什么数据结构表示复杂对象"
U2多线程电梯生产者-消费者 + 锁粒度控制,学会"并行系统的职责划分与同步"
U3JML 社交网络规格驱动开发,学会"先定契约再写实现",数据结构优化(HashMap 代替遍历)
U4图书馆 UML正向建模 + 两阶类图,学会"先设计架构再编码,图示化设计思维"

演进趋势:从"实现一个算法"→"设计一个并发系统"→"按照规格实现"→"自行设计架构并建模"。U4 是前三个单元的集成:需要自己定义类(U1 的抽象思维)、需要处理状态迁移(U2 的并发思维)、需要精确满足规格(U3 的契约思维)。

五、四个单元测试思维的演进

U1(表达式解析):手动构造边界测试 + 互测 hacking。测试方式是"猜别人哪里会出错"。测的是正确性性能(TLE)。

U2(多线程电梯):随机测试 + 死锁检测。多线程的 bug 不是稳定复现的,学会了跑大量随机线程调度来暴露竞态。测的是正确性线程安全

U3(JML 社交网络):JUnit 白盒测试。从 JML 规格直接翻译出测试用例。还学会了构造极端数据(10^5 条边)测性能。测的是规格一致性时间复杂度

U4(图书馆系统):交互式评测 + 随机自动化测试。评测机动态生成还书/取书/续订请求,要求程序输出必须与自身状态一致。我写了 Python 测试脚本,自动生成随机图书馆场景并验证业务规则(信用分、逾期、借阅限制),帮助快速发现逻辑漏洞。

演进趋势:从"自己构造测试"→"随机压力测试"→"规格翻译测试"→"交互式自动化测试"。测试从手工到自动,从局部到系统级。

六、课程收获

  1. 面向对象的核心是"职责分配"。四个单元下来,最大的感悟是:不是把代码写成类就是 OO,而是每个类有清晰的职责边界,类之间的协作方式体现了系统架构。U4 的 LibraryManager 如果不拆出 CreditManager,所有信用逻辑堆在一个类里,就是伪 OO。

  2. 规格与实现分离。U3 的 JML 和 U4 的 UML 都在强调"先说清楚要做什么,再动手做"。这种思维对大型项目尤其重要——需求变了的代价远大于实现错了的代价。

  3. 测试是设计的一部分。U2 的随机测试让我意识到,好的测试框架本身就是一个迷你系统。U4 的交互式评测让我学会了用代码验证代码——评测机的动态请求生成对程序逻辑的完整性和一致性提出了更高要求。

  4. 大模型是好的辅助,但不是替代。大模型帮我找到不少bug,但有一些关键 bug(逾期罚分时机、overduePenaltyApplied 标记跨用户污染)需要人工分析才能发现。AI 擅长"加速已知流程",不擅长"发现未知问题"。

  5. 迭代优于一次到位。两阶类图的设计哲学——先画一阶、写代码、再修正二阶——本身就是迭代思维的体现。U1 的 TermBasis 抽象也是从 HW1 到 HW2 迭代出来的。

...全文
7 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

308

社区成员

发帖
与我相关
我的任务
社区描述
2026年北航面向对象设计与构造
java 高校
社区管理员
  • 孙琦航
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧