309
社区成员
发帖
与我相关
我的任务
分享本单元与前三个单元的任务流程不同,需要先从需求出发进行正向建模,再让逐步实现代码。第13次作业中,系统从图书、用户、预约、书架、借还处、预约处等基本概念出发,先建立类图,再实现借阅、归还、预约、取书、查询和整理流程。到第14、15次作业,需求继续扩展,加入精品书架、阅读室、评分、信用分、借阅期限、续借、状态图和顺序图,整个开发过程体现了“需求分析 -> 模型设计 -> 代码实现 -> 模型修正”的正向开发路径。
两阶类图在这个过程中起到了很重要的约束和反馈作用。第一阶段类图更像是开发前的架构蓝图,它要求我们在写代码前先识别核心实体、职责划分和对象之间的关系,避免一开始就陷入过程式实现。第二阶段类图则承担了一致性校准的作用:当代码实现过程中出现新增类、方法调整、状态扩展时,需要把最终实现重新反映到 UML 中,使模型不只是前期设想,而是可以追踪到最终代码。
两阶类图的意义不在于机械地画两张图。第一阶段帮助建立抽象,第二阶段帮助验证抽象是否经得起实现。二者之间的相似度检查也促使我们不能提交空泛模型,而要保证前期设计和后期实现之间存在真实延续关系。
本单元最终代码整体采用了比较清晰的分层与职责划分。MainClass 负责与官方输入输出包交互,是系统和评测接口之间的适配层;LibraryManager 是核心调度类,统一处理开馆、闭馆、借阅、归还、预约、取书、阅读、评分、续借和信用查询等业务;Book、User、Reservation 是主要领域对象;BookShelf、TreasuredBookshelf、BorrowAndReturnOffice、AppointmentOffice、ReadingRoom 则分别表示图书可能处于的不同地点或业务部门。
从作业演进看,第13次的架构主要围绕普通书架、预约处、借还处和用户展开;第14次在此基础上扩展出精品书架和阅读室,并用评分影响整理后的图书归属;第15次进一步把用户信用分、借阅期限、逾期扣分、续借等状态放入 User 中,使用户不再只是“持有哪些书”的容器,而成为拥有行为约束和信用状态的核心对象。
最终代码设计和 UML 模型之间有明确的追踪关系。类图中的类基本对应代码中的 Java 类,属性和方法也大体反映了实现中的核心状态和行为。例如,LibraryManager 在 UML 中包含各地点类、用户表、图书表等属性,对应代码中对系统全局状态的管理;User 中的 borrowedBooks、dueDates、creditScore、penalizedOverdue 等属性,对应第15次作业中信用和借期规则;Book 中的 curLocation 和 movingTrace 对应图书状态与移动轨迹查询。
状态图则从另一个角度追踪 Book 的位置变化。最终模型中的 BS、TBS、BRO、AO、RR、USER 分别对应普通书架、精品书架、借还处、预约处、阅读室和用户。代码中 handleBorrow、handleReturn、handlePick、handleRead、handleRestore、arrange 等方法正是这些状态迁移的触发点。顺序图则重点描述预约和取书流程,例如从用户请求到 LibraryManager,再到 AppointmentOffice、User、Book 的调用链,体现了对象间协作关系。
UML 模型负责表达架构和设计意图,代码负责完成细节实现。关键在于二者的核心职责、状态变化和协作关系能够互相追踪。
使用大模型辅助复杂场景下的正向建模时,应当注意不能让它“直接给代码”,而应该引导它先完成需求拆解和架构抽象。比较有效的方式是先要求大模型从题目中提取实体、状态、操作、约束和业务不变量,例如图书有哪些状态、用户有哪些限制、预约何时失效、信用分何时变化等。只有这些规则被明确列出后,再让它设计类、职责和对象协作。
在提示大模型时,可以让它分阶段输出:先给对象和职责划分,再给类图设计建议,然后给状态迁移和顺序图场景,最后再进入代码层面。对于U4这种复杂规则系统,还应要求大模型建立“需求到设计”的追踪,例如某条需求由哪个类负责、由哪个方法处理、会改变哪些状态。这样可以减少它遗漏规则或把职责放错位置的概率。
同时,大模型容易出现两个问题:一是设计看起来完整但缺少边界约束,二是模型和代码之间前后不一致。因此,在使用时需要不断让它自检:是否违反借阅数量限制、预约状态是否会被清除、逾期扣分是否重复、状态图中的迁移是否都能在代码中找到对应方法。也可以把已有代码或 UML 片段交给大模型,让它反向检查“代码是否偏离模型”、“模型是否漏掉实现类”。
总体来看,大模型更适合充当架构讨论伙伴和一致性检查工具,而不是完全替代设计者。真正有效的使用方式,是由人提供明确需求、约束和设计目标,让大模型生成候选架构、补充边界场景、检查 UML 与代码的追踪关系,再由人进行取舍和修正。这样才能在复杂场景中既利用大模型的归纳能力,又保持设计的可控性和准确性。
第一单元(表达式化简),整体来说架构很清晰,就是遵循递归下降的解析方式即可。而且有了大模型的辅助,我们代码设计的重心也转移到了设计更优的化简策略上面。如何把递归下降的主体和具体细节的算法设计良好地分离与结合是比较关键的问题,如果处理不当,自己稍加改动或者稍微让大模型进行改进便会变成屎山,容易写出bug不说,主要是会让之后的迭代非常痛苦。
第二单元(多线程电梯),初次接触到多线程的架构设计,自己整体一小半时间在处理架构的设计策略,即合理地安排基础的电梯管理方式。大半时间都在设计更优的调度策略,这使得我的架构有些混乱,在ai的加持下出现了严重的过度设计。
第三单元没有很明显的架构问题,主要是“翻译”和算法。
第四单元的架构设计则又要花费一番心思,如何做好高内聚低耦合,把各对象进行合理建模、统一管理,处理好各个流程之间的关系,这都对架构设计提出了要求。我在实现的时候,也在有意注意避免前几个单元踩过的坑。
关于测试思维,我认为测试主要可以分为三方面。第一方面是单元测试,利用Junit测试我们各个方法、分支的正确性,架构设计、算法设计的合理性。第二方面是随机数据测试,这部分利用大模型搭建评测机可以非常高效地完成,可以帮助我们进行最基础的正确性检查。第三方面是边界压力测试,也是最重要、最能影响正确性的测试方式。如何针对每次作业设计出合适的边界数据,这并没有一种统一的方式,且大模型往往不能在这方面提供很好的帮助。稍微还算通用的构造方式就是尽量在课程组给的各个数据范围的边界进行特殊测试与构造。
一学期的OO课程终于来到了尾声。回顾自己一学期的学习,收获自然是丰富的:进一步深入理解递归下降算法,接触到复杂多线程的实际设计,学习到JML、UML等实用工具。能明显感觉到,自己面向对象编程的能力以及对这一编程范式的理解都有了比较深刻的提升与进步,尤其是在AI的帮助下,我得以更为深入地学习到一些有关Java的底层知识,能够更为便捷地编写测试工具,能够与AI探讨出更优的解题策略,自己使用AI的能力明显提升,对于如何利用AI更好地编写代码也有了更真切的体会与感悟。不过遗憾也是有的,最重要的遗憾是我的最后一次作业的强测竟然爆掉了...导致我之前所有作业强测0错误的纪录被打破...这是我未曾预料的,不过也是情理之中的,因为我最后一次作业过于相信大模型,也没有做足测试便草草提交。但不管怎样,这份遗憾亦算是收获,让我更加清楚地认识到人与ai到底应该怎样协作。
作为6系最经典的课程之一,OO带给我的不仅是知识储备上的增长,更重要的是对思维模式、学习模式的转变与探索,以及代码能力的提升。什么样的代码是高效的,什么样的架构是清晰的,什么样的算法和数据结构是最优的,什么样的人机交互方式是合适的,怎样完成任务需求,怎样学习新知识,怎样理解知识、理解代码、理解需求、理解世界。细细想来,在一个学期的学习过程中,我确实遇到了很多之前不曾遇到过的问题,思考了很多之前没有想过事情,对很多事物的认知有了新的看法、新的感悟。这些都是OO带给我的宝贵财富,让我收获良多,受益终生。
感谢OO这门独特而有趣的课程,感谢课程组、老师、助教们的付出!