面向对象(OO)第四单元总结:正向建模与UML驱动开发

周林森-24373410 2026-06-20 16:42:16

面向对象(OO)第四单元总结:正向建模与UML驱动开发

前言

第四单元的主题是正向建模与UML驱动开发。与前三个单元截然不同——第一单元是"从零构建表达式引擎",第二单元是"多线程电梯调度",第三单元是"JML规格驱动实现"——本单元的学习目标是掌握从UML模型出发的正向建模方法,即先设计类图、状态图、顺序图,再依据模型实现代码。核心体验是:"模型即蓝图,代码是模型的忠实映射"

本单元以"图书馆管理系统"为场景,经历了三次作业的迭代:

  1. HW13:基础图书馆流通系统,借书/还书/预约/取书/查询,初次实践两阶类图的正向建模方法。

  2. HW14:引入精品书架、阅览室、评分系统,新增状态机(State Machine)建模,架构复杂度跃升。

  3. HW15:引入信用分系统、续借、逾期扣分,新增顺序图(Sequence Diagram)建模,功能体系趋于完整。


第一次作业分析(HW13)

1. 两阶类图:从"一阶"到"终极"

HW13 的核心任务不仅是实现功能,更是体验两阶类图的正向建模流程

  • 一阶类图(uml_pre.mdj:在阅读需求后、编写代码前,先设计初步的类结构。此时我采用了 Command 模式——设计了 Request 抽象基类及其五个子类(BorrowRequestReturnRequestOrderRequestPickRequestQueryRequest),由 LibraryManager.processRequest() 多态分发。这个阶段的核心目标是快速建立领域模型,将需求中的实体(用户、图书、书架、借还处、预约处)映射为类。

  • 终极类图(uml_ultimate.mdj:在代码实现完成后,根据实际代码结构对一阶类图进行重构。经过实践,我发现了 Command 模式在此场景下的问题——每个 Request 子类只包含极少的差异化逻辑,继承体系带来的抽象收益远小于其复杂度成本。于是进行了结构性重构:消除 6 个 Request 子类及其继承体系,将操作逻辑内聚到 Library 类中,直接暴露 borrow()returnBook()order()pick()query() 方法。

两阶类图的核心价值在于:一阶类图是"设计的假设",终极类图是"实践的总结"——两者之间的差异正是设计思维成熟的过程。

2. 代码架构分析

HW13 最终采用基于位置的委托架构(Location-Based Delegation)

Main (入口层)
  └── Library (Facade / 协调层)
        ├── Bookshelf          — 书架(FIFO队列)
        ├── BorrowReturnOffice — 借还处
        ├── AppointmentOffice  — 预约处(LinkedHashMap保序)
        ├── Map<String, User>  — 用户管理
        └── Map<LibraryBookId, BookCopy> — 全局副本索引

核心类职责

类名职责关键设计
Library外观模式协调器,管理所有业务操作开馆/闭馆整理、预约履约、借还调度
BookCopy图书副本,自身维护状态与轨迹moveTo() 实现状态转移 + 轨迹记录
Order预约订单生命周期管理状态机:PLACED → FULFILLED → COMPLETED/EXPIRED
User用户借阅规则校验封装 A/B/C 三类书的差异化借阅策略
Bookshelf按ISBN分组的FIFO队列ArrayDeque 保证先入库先借出
BorrowReturnOffice还书中转站简单列表容器
AppointmentOffice预约处管理LinkedHashMap 保证插入顺序

3. 关键设计决策:从 Command 模式到 Facade 模式

决策维度一阶类图(Command模式)终极类图(Facade模式)
请求处理6个Request子类 + processRequest()多态Library直接方法:borrow/returnBook/order/pick/query
类数量15个类9个类
扩展性新增操作需新增子类新增操作在Library加方法
可读性分散在多个类中集中在Library中,流程清晰

重构动机:Command 模式在此场景下属于过度设计。每个 Request 子类仅包含 1-2 行差异化逻辑,继承体系的抽象成本远超其收益。Facade 模式更贴合"图书馆"这一领域——所有操作都是图书馆这个聚合根的行为,不存在"命令对象"的独立生命周期。

4. 预约履约机制

预约在开馆/闭馆整理时统一履约,而非用户下单时实时处理。这是关键的架构决策:

  • 开馆前履约:有效期 4 天(fulfillDate + 4)

  • 闭馆后履约:有效期 5 天(fulfillDate + 5)

  • 过期后自动将图书从预约处移回书架


第二次作业分析(HW14)

1. 迭代演进:功能爆炸与架构承压

HW14 在 HW13 基础上新增了:

  • 精品书架(Treasured Bookshelf):通过评分系统(平均分 >= 4)动态分类

  • 阅览室(ReadingRoom):用户可在馆阅读,读完后归还

  • 评分系统(grade):用户对图书评分,影响精品分类

  • 状态机建模:为 BookCopy 设计完整的状态转移图

2. 代码架构分析

Main (命令解析层)
  └── LibraryManager (业务调度层)
        ├── Bookshelf (bs)     — 普通书架
        ├── Bookshelf (tbs)    — 精品书架
        ├── BorrowReturnOffice — 借还中转站
        ├── AppointmentOffice  — 预约管理处
        ├── ReadingRoom        — 阅览室
        ├── Map<String, User>  — 用户管理
        └── Map<ISBN, List<Integer>> — 评分数据

核心新增功能

  • 双书架 + 动态分类classifyBooks() 在开馆整理时执行,双向扫描 bs 和 tbs,根据 isTreasured() 判断结果迁移图书。使用 removeSpecific() 而非 remove() 来精确移除指定副本。

  • 阅览流程read() 从书架取书放入阅览室 → restore() 从阅览室取出放入借还处 → 开馆/闭馆整理时从借还处归架。用户同时只能读一本书。

  • 预约履约增强:履约时从 bs 和 tbs 两个书架查找,优先从 bs 取书。

3. 状态机建模:BookCopy 的位置状态

HW14 的核心突破是引入了状态机(State Machine)建模。为 BookCopy 设计了 7 个状态 + 14 条状态转移:

源状态目标状态触发器业务场景
InitStatebsinit()初始化入库
bsuserborrow()借阅
tbsuserborrow()从精品书架借阅
bsrrread()阅览
tbsrrread()从精品书架阅览
bsaofulfill()预约履约
tbsaofulfill()从精品书架履约
bstbsclassifyToTbs()升级为精品
tbsbsclassifyToBs()降级为普通
userbroreturnBook()归还
rrbrorestore()归还阅览
brobsarrangeToBs()整理到普通书架
brotbsarrangeToTbs()整理到精品书架
aobsexpire()预约过期

设计要点:所有从同一状态出发到不同目标的转移,Guard 条件互斥——通过 targetState 辅助变量实现。例如从 bs 出发有 4 条转移(borrow→user, read→rr, fulfill→ao, classifyToTbs→tbs),它们的 targetState 各不相同,保证了转移的确定性。

4. 一阶类图到终极类图的变化

维度一阶类图终极类图
BookCopy无 targetState新增 targetState + 12个@Trigger方法
Order单一 isExpired()拆分为 isExpiredOnOpen() + isExpiredOnClose()
AppointmentOffice单一 removeExpired()拆分为 removeExpiredOnOpen() + removeExpiredOnClose()
状态图新增 StateMachine1(7状态+14转移)

重构原因:一阶类图设计时,对"开馆/闭馆整理时的过期判断差异"理解不够深入。代码实现后,发现需要精确区分 isAfter(开馆)和 !isBefore(闭馆)两种过期语义,因此将方法拆分。状态图也是在一阶类图之后才设计的,因为一阶类图阶段对状态转移的全局视图掌握不足。


第三次作业分析(HW15)

1. 迭代演进:信用分系统与顺序图

HW15 在 HW14 基础上新增了:

  • 信用分系统:初始 100 分,上限 180,下限 0

  • 续借(renew):逾期前可续借 7 天

  • 逾期扣分机制:按时归还 +10,逾期 -15,预约过期 -15,闭馆未还 -10/本

  • 信用分分级权限:>80 可借阅/预约,>40 可读 A 类,>0 可读其他

  • 顺序图建模:为核心业务流程设计时序交互图

2. 代码架构分析

HW15 的架构在 HW14 基础上增量演进,核心变化集中在 LibraryManagerBookCopy

  • 逾期扣分去重BookCopy 新增 overdueDeducted 标记,processOverdueDeductions() 在开馆/闭馆时统一处理,防止同一逾期事件被重复扣分。

  • 预约履约四级查找fulfillOrdersFromAll() 从 bro → rr → bs → tbs 四级优先查找,而非仅从 bs/tbs。这保证了归还到借还处的书也能第一时间满足预约。

  • 预约排序:按 placedDate 升序 + seq 降序排序,确保先预约的用户优先得到履约,同时保证确定性。

  • 归还验证returnBook()restore() 增加了所有权验证(hasBorrowedCopy() / isReadingBook()),防止归还不属于自己的书。

  • 续借逻辑renew() 在逾期前可延长 dueDate 7 天,逾期后不可续借。

3. 顺序图建模

HW15 新增了顺序图(Sequence Diagram),为核心业务流程建模对象间的时序交互。以"借书"流程为例:

User → LibraryManager → Bookshelf(bs) → Bookshelf(tbs) → BookCopy → User
  |         |               |               |               |         |
  | borrow  |               |               |               |         |
  |-------->|  remove(isbn) |               |               |         |
  |         |-------------->|               |               |         |
  |         |   (null)      |               |               |         |
  |         |<--------------|  remove(isbn) |               |         |
  |         |------------------------------>|               |         |
  |         |              copy             |               |         |
  |         |<------------------------------|               |         |
  |         |                         borrowBook(date,days) |         |
  |         |---------------------------------------------->|         |
  |         |                         moveTo(USER, date)    |         |
  |         |---------------------------------------------->|         |
  |         |                 addBorrowedBook(copy)          |         |
  |         |---------------------------------------------------------------->|
  |   accept(cmd, bookId)     |               |               |         |
  |<--------|                 |               |               |         |

顺序图的核心价值在于将类图中的静态关系转化为动态交互:类图告诉我们"谁和谁关联",顺序图告诉我们"谁先调用谁,参数是什么,返回值是什么"。

4. UML 模型完整性

截至 HW15,UML 模型包含三类图:

图类型内容建模对象
类图(Class Diagram)9个核心类 + 关联关系 + 属性/方法系统的静态结构
状态机(State Machine)7个状态 + 14条转移 + Trigger + GuardBookCopy 的生命周期
顺序图(Sequence Diagram)多条生命线 + 消息传递核心业务流程的时序交互

正向建模与两阶类图的作用分析

1. 一阶类图:设计假设的快速验证

一阶类图是"先设计,后编码"的关键产出。它的核心价值不在于"正确",而在于"快速暴露设计问题"

在 HW13 的一阶类图中,我采用了 Command 模式。这个设计在画图阶段看起来合理——每种操作对应一个 Request 子类,符合开闭原则。但当我开始编码时,立刻发现了问题:每个子类的 process() 方法只有 1-2 行,继承体系的复杂度远大于其带来的收益。如果没有一阶类图这个"设计快照",我可能会在代码中陷得更深,重构成本更高。

一阶类图的作用总结

  • 领域建模:将需求中的概念映射为类和关系,建立对问题域的初步理解

  • 设计实验:低成本尝试不同的架构模式,在纸上(或工具中)而非代码中试错

  • 沟通工具:作为团队讨论的基础,让设计意图可视化

2. 终极类图:实践总结的精确记录

终极类图是"编码后,回过头来修正设计"的产物。它记录的不仅是"代码是什么",更是"为什么最终选择了这个设计"。

在 HW14 中,终极类图新增了 targetState 属性和 12 个 @Trigger 方法。这些是在编码过程中才发现的需求——状态机的 Guard 条件需要辅助变量来表达互斥性。如果一开始就试图在类图中设计这些细节,反而会陷入过度设计。

终极类图的作用总结

  • 设计文档化:为后续维护者(包括未来的自己)提供精确的代码蓝图

  • 设计审查:通过对比一阶类图和终极类图,发现设计决策的演变轨迹

  • 模型验证:确保代码结构与 UML 模型一致,作为自动化评测的基础

3. 两阶类图之间的"设计张力"

两阶类图之间的差异,恰恰是正向建模最有价值的部分:

差异类型一阶类图终极类图启示
架构模式Command 模式Facade 模式设计模式应服务于领域,而非教条
Order 过期判断单一 isExpired()拆分为 OnOpen/OnClose编码会暴露设计阶段的模糊假设
BookCopy 状态管理无 targetState有 targetState + @Trigger工具链需求(状态机评测)会反推设计调整
职责划分借阅限制在 BorrowLimit合并入 User信息专家原则:数据在哪里,行为就在哪里

架构设计与UML模型的追踪关系

1. 类图与代码的映射

本单元的类图与代码之间保持了高度一致的追踪关系。以下是核心类的映射:

UML 类图中的类代码中的类一致性差异说明
Library / LibraryManagerLibraryManager.java类图早期用 Library,代码用 LibraryManager,语义一致
BookCopyBookCopy.java属性、方法、@Trigger 全部对应
BookshelfBookshelf.javacopies 结构(Map<ISBN, Deque>)完全一致
BorrowReturnOfficeBorrowReturnOffice.java-
AppointmentOfficeAppointmentOffice.java-
ReadingRoomReadingRoom.java-
OrderOrder.javaState 枚举 + 状态转换方法完全一致
UserUser.java借阅规则 + 信用分方法完全一致

2. 状态机与代码的映射

状态机中的每个状态、转移、Trigger、Guard 在代码中都有对应的实现:

  • 状态LibraryBookState 枚举值(BOOKSHELFTREASURED_BOOKSHELFUSERBORROW_RETURN_OFFICEAPPOINTMENT_OFFICEREADING_ROOM

  • 转移BookCopy.moveTo() 方法调用,自动记录轨迹

  • TriggerBookCopy 中 12 个包级私有的 @Trigger 注解方法

  • GuardtargetState 属性的值,在每次 moveTo() 时自动更新

这种映射关系保证了状态机不是"画完就扔"的文档,而是与代码同步演进的活模型

3. 顺序图与代码的映射

顺序图中的生命线(Lifeline)对应代码中的对象实例,消息(Message)对应方法调用。以"借书"为例:

顺序图元素代码对应
:User → :LibraryManager.borrow()libraryManager.borrow(date, studentId, isbn)
:LibraryManager → :Bookshelf.remove(isbn)bs.remove(isbn)
:LibraryManager → :BookCopy.borrowBook(date, days)copy.borrowBook(date, days)
:LibraryManager → :BookCopy.moveTo(USER, date)copy.moveTo(LibraryBookState.USER, date)
:LibraryManager → :User.addBorrowedBook(copy)user.addBorrowedBook(copy)

4. 追踪关系的价值

保持 UML 模型与代码之间的追踪关系,带来了以下收益:

  • 自动化评测:课程评测框架可以直接读取 UML 模型文件,验证代码实现是否与模型一致。HW15 中大量的 fix_*.py 脚本正是为了修复模型与代码之间的不一致。

  • 设计一致性:当需要修改代码时,可以先检查 UML 模型,确认修改是否影响其他部分。例如,新增 renew() 功能时,需要同步更新类图(BookCopy 新增 renew() 方法)和顺序图(新增续借流程)。

  • 知识传递:UML 模型比代码更直观,新成员可以通过阅读模型快速理解系统架构。


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

1. 使用场景

在本单元中,我大量使用大模型(GLM/Claude)辅助正向建模的各个环节:

  • UML 模型生成:将自然语言需求描述输入大模型,生成初始的类图、状态机、顺序图结构(.mdj JSON 文件)。

  • 模型修复:当评测框架报告 UML 模型与代码不一致时,编写 Python 脚本(如 fix_uml_issues.pyfix_seq_back.py)自动修复模型文件。大模型在生成这些修复脚本方面效率极高。

  • 代码生成:基于 UML 类图,让大模型生成方法骨架,人工填充业务逻辑。

  • 模型验证:将 .mdj 文件和 .java 文件一起提交,让大模型检查两者的一致性。

2. 如何引导大模型完成复杂架构设计

经过本单元的实践,我总结出以下引导策略:

策略一:分层递进,逐步细化

不要一次性让大模型输出完整设计。应该分步骤:

  1. 先让大模型输出领域模型(有哪些实体,它们之间有什么关系)

  2. 再让大模型输出类图(每个类的属性和方法)

  3. 最后让大模型输出行为模型(状态机、顺序图)

在 HW14 中,我先让大模型分析"图书馆有什么?书架、借还处、预约处、阅览室、用户、图书...它们之间怎么交互?",等它输出领域模型后,再让它细化每个类的属性和方法。

策略二:提供约束和上下文

大模型在缺乏约束时容易"自由发挥"。在引导时,需要明确提供:

  • 外部库的 API(如 LibraryBookIdLibraryBookState 的类型定义)

  • 已有的代码结构(如 LibraryManager 的现有方法签名)

  • 特定的设计约束(如"必须使用 Facade 模式"、"预约履约在开馆整理时统一处理")

在 HW15 中,我让大模型基于 HW14 的代码生成 HW15 的增量设计,它能够准确识别需要新增的类、方法和属性,避免了重复设计。

策略三:利用大模型进行"设计评审"

将一阶类图输入大模型,让它扮演"设计评审者"的角色,指出潜在问题:

  • "这个 Command 模式是否过度设计?"

  • "Order 的过期判断是否需要区分开馆和闭馆?"

  • "BookCopy 的状态机是否完备?"

在 HW13 中,大模型指出了 Command 模式的过度设计问题,这与我在编码中的实际感受一致,加速了重构决策。

策略四:脚本化批量操作

UML 模型文件(.mdj)是 JSON 格式,大模型非常适合生成和修改 JSON 结构。在 HW15 中,我大量使用大模型生成 Python 脚本:

  • build_uml.py:完全重建类图中的所有属性和方法

  • fix_seq_back.py:修复顺序图中的消息方向

  • update_uml.py:为模型增量添加新方法

这种"大模型生成脚本 → 脚本修改模型 → 人工验证"的工作流,比手动编辑 .mdj 文件高效得多。

3. 优势与局限

优势

  • 快速原型:从需求到初始类图,大模型可以在几分钟内输出一个可用的设计草案,人工只需调整和细化。

  • 批量操作:修改 .mdj JSON 结构时,大模型生成的 Python 脚本可以一次性处理几十个字段,比手动编辑快 10 倍以上。

  • 一致性检查:大模型可以同时阅读 UML 模型和 Java 代码,检查两者之间的不一致,这是人工容易遗漏的。

局限

  • 缺乏领域深度理解:大模型对"图书馆业务流程"的理解停留在表面,不会主动考虑"开馆履约和闭馆履约的过期时间应该不同"这样的领域细节。这些细节需要人工补充。

  • 倾向于过度设计:在没有明确约束时,大模型倾向于使用各种设计模式(Command、Strategy、Observer),导致架构过于复杂。需要人工做"减法"。

  • 生成代码的"模型一致性"不足:大模型生成的代码往往与它自己生成的 UML 模型不完全一致——例如类图中定义了 targetState 属性,但生成的代码中没有使用它。这种不一致需要通过模型验证环节来发现。


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

第一单元:从"扁平化"到"树形结构"

第一单元的主题是表达式化简。我的架构经历了从扁平的多项式模型(Poly + HashMap树形的 AST 模型(Expr 继承体系)的转变。

核心收获:当问题域中存在"部分-整体"的层级结构时(如表达式中的嵌套括号),应采用组合模式(Composite Pattern)构建树形结构,而非强行扁平化。扁平化在简单场景下高效,但面对复杂嵌套时必然崩溃。

第二单元:从"单线程思维"到"并发协作"

第二单元的主题是多线程电梯调度。我的架构从"一个类搞定一切"的粗暴设计演进为生产者-消费者模式的多线程协作架构。

核心收获:并发编程的核心不是"让代码跑得快",而是"明确每个线程的职责边界"InputThread 只负责读取输入,ScheduleThread 只负责调度策略,ElevatorThread 只负责执行移动。线程间的通信通过共享的 RequestQueue 完成。这种职责分离 + 消息传递的思维,在后续单元中持续影响着我。

第三单元:从"我要做什么"到"规格要我做什么"

第三单元的主题是 JML 规格驱动开发。架构设计不再是"我想怎么设计",而是"规格规定了什么接口,我需要如何实现它们"。

核心收获契约式设计(Design by Contract)的思想——实现者只需且必须精确满足规格,任何额外的"智能"都是潜在的 bug。HW10 的三个 bug 全部源于"我觉得应该这样"的额外假设。这让我认识到:在规格驱动的场景下,架构设计的自由度被规格约束,但质量也被规格保障

第四单元:从"代码先行"到"模型先行"

第四单元的主题是正向建模。与前三个单元"先写代码,再画图(或干脆不画图)"不同,本单元要求先设计 UML 模型,再编写代码

核心收获模型是设计的"压缩表示"。一个好的 UML 类图比 100 行代码注释更能传达设计意图。两阶类图的方法论——一阶类图作为设计假设,终极类图作为实践总结——让我认识到:设计不是一次完成的,而是在"假设→验证→修正"的循环中逐步收敛的

演进总结

单元设计范式核心思维转变
第一单元递归下降 + AST从扁平化到树形结构,理解组合模式
第二单元生产者-消费者从单线程到多线程协作,理解职责分离
第三单元契约式设计从"我想做"到"规格要我做什么",理解规格的精确性
第四单元正向建模从"代码先行"到"模型先行",理解设计先于实现

贯穿四个单元的核心线索是:架构设计的能力本质上是对"复杂度"的管理能力。第一单元管理的是表达式嵌套的复杂度,第二单元管理的是并发协作的复杂度,第三单元管理的是规格精确性的复杂度,第四单元管理的是模型与代码一致性的复杂度。


四个单元中测试思维的演进

第一单元:手工测试 + 随机测试

第一单元的测试策略比较原始:手工构造边界表达式(如 0^0x^0(x+1)^50 等)+ Python 随机生成器。测试目标是"输出对不对",验证方式是"目测 + 与同学对拍"。

局限性:缺乏系统性的测试方法论,测试用例的覆盖度不可控,bug 往往在互测阶段才被发现。

第二单元:时序测试 + 并发正确性

第二单元引入了新的测试维度:时序正确性。除了验证"电梯最终到达了正确的楼层",还需要验证"线程安全"(无死锁、无竞态条件)。

核心策略

  • 编写压力测试脚本,生成大量随机请求,观察程序是否出现死锁或线程饿死

  • 使用时间戳日志记录每个请求的生命周期,验证"先到先服务"的调度策略

  • 人工构造边界时序(如同一时刻多个请求到达)

收获:并发测试比串行测试难得多——同样的输入可能因为线程调度的不确定性产生不同的输出。测试策略需要从"验证输出"转向"验证不变量"(如"电梯不会同时向两个方向移动")。

第三单元:JUnit + 规格覆盖

第三单元正式引入了JUnit 单元测试规格驱动的测试方法

核心策略

  • 为每个 JML 方法的 requires/ensures/signals 子句生成对应的测试用例

  • 使用 strictEquals 深度验证对象的所有字段,而不仅仅是 id

  • 使用大模型生成随机测试脚本,覆盖大量边界组合

收获:规格驱动的测试比"拍脑袋"测试更系统、更可靠。JML 的 ensures 子句直接给出了测试的预期结果,signals 子句直接给出了异常测试的触发条件。测试的"输入-预期输出"映射是由规格保证的,而非测试者主观判断。

第四单元:模型验证 + 脚本化测试

第四单元的测试维度发生了根本性变化:不仅要验证代码的正确性,还要验证代码与 UML 模型的一致性

核心策略

  • 模型一致性测试:编写 Python 脚本(如 check_seq_views.pycheck_statemachine.pycheck_structure.py)自动检查 .mdj 文件与 Java 代码之间的一致性

  • 场景覆盖测试:为每个业务场景编写测试用例(如 test_borrow_return_cycle.txttest_expired_reorder.txttest_treasured_late_return.txt

  • 边界值测试:信用分 0/40/80/100/180 的边界、逾期 0 天/1 天/7 天的边界、预约过期 4 天/5 天的边界

  • 大规模压力测试test_massive.txt 生成海量操作序列,验证性能和正确性

收获:模型一致性测试是第四单元独有的测试维度。在 HW15 中,我编写了大量 check_*.pyfix_*.py 脚本,形成了"检查 → 发现不一致 → 修复 → 再检查"的自动化测试循环。这让我认识到:测试不仅是"找代码的 bug",也可以是"找设计的 bug"——当 UML 模型与代码不一致时,要么是代码写错了,要么是模型设计有缺陷,两者都需要修正。

测试思维演进总结

单元测试方法测试维度核心思维转变
第一单元手工 + 随机输出正确性从"目测"到"对拍"
第二单元压力测试 + 日志时序正确性 + 线程安全从"验证输出"到"验证不变量"
第三单元JUnit + 规格覆盖规格一致性从"拍脑袋"到"规格驱动"
第四单元模型验证 + 场景覆盖代码正确性 + 模型一致性从"测代码"到"测设计"

贯穿四个单元的核心线索是:测试的层次不断提升——从"功能对不对"(第一单元)到"并发安全吗"(第二单元)到"规格满足吗"(第三单元)到"设计一致吗"(第四单元)。每一层都是对前一层的补充,而非替代。


课程收获

1. 设计先于实现

经过四个单元的训练,我最大的收获是"设计先于实现"的意识。第一单元时,我拿到需求就开始写代码,结果第二次作业不得不大规模重构。到了第四单元,我已经习惯先画 UML 类图,确认架构合理后再动手编码。这种"慢即是快"的体验,是 OO 课程给我最宝贵的财富。

2. 复杂度管理的艺术

好的架构不是"功能最多的架构",而是"在满足需求的前提下,复杂度最低的架构"。HW13 从 Command 模式重构为 Facade 模式,代码量减少了 40%,可读性大幅提升——这就是"做减法"的价值。过度设计与设计不足同样有害。

3. 模型的实用主义

UML 模型不是"为了画图而画图",而是有实际用途的设计工具。类图帮助我理清静态结构,状态机帮助我理清对象生命周期,顺序图帮助我理清对象间交互。当模型与代码保持一致时,模型就是最好的文档。

4. 大模型是"加速器"而非"替代者"

大模型在生成代码框架、修复模型文件、检查一致性方面效率极高,但它无法替代人的设计判断。架构设计的核心决策——选择什么模式、如何划分职责、哪些细节需要抽象——仍然需要人来完成。大模型的价值在于消除机械劳动,让人专注于创造性思考。

5. 迭代是设计的本质

没有哪个设计是"一次做对"的。一阶类图到终极类图的变化、HW13 到 HW15 的三次迭代、第一单元到第四单元的四次思维转变——都在说明同一个道理:好的设计是在迭代中逐步收敛的,而不是在初始阶段就完美的


结语

回顾整个 OO 课程,四个单元构成了一个完整的"面向对象能力培养链":

  • 第一单元教会我如何用对象建模复杂的数据结构(表达式树)

  • 第二单元教会我如何用对象建模复杂的并发行为(电梯调度)

  • 第三单元教会我如何在规格约束下实现对象(JML 契约)

  • 第四单元教会我如何在编码之前设计对象(UML 正向建模)

从"先写代码"到"先画模型",从"想怎么做就怎么做"到"规格说怎么做就怎么做",从"功能正确就行"到"设计也必须正确"——这一路走来,我学到的不仅是 Java 编程和 UML 画图,更是一种面向对象的思维方式:将复杂问题分解为协作的对象,让每个对象有清晰的职责和边界,在迭代中持续优化设计。

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

309

社区成员

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

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