BUAA_OO_UNIT4总结

唐锡浩-22373266 学生 2024-06-12 17:00:00

正向建模与开发

正向建模的定义:

正向建模是指在软件系统开发的早期阶段,基于需求和设计文档等资料,使用建模工具进行系统的设计和建模,根据需求、设计和代码之间的关系来构建模型和图形化展示系统结构和行为。正向建模方式通常用于新系统的开发、重构或重新设计。

即正向建模的要求是根据需求先进行建模,根据建模进行程序代码编写

本单元中要求通过UML的建模方式,先进行程序大体模型的构建,再进行代码编写,具体体现在每一次作业中:

第一次作业要求实现一个图书管理系统的雏形,需要我们先根据作业要求绘制UML类图,对如何通过各个类以及类与类间的关系实现相应功能进行初步的思考之后,再开始对照类图进行代码编写、

第二次作业要求实现图书捐赠和续借以及借阅期限等功能,此时书籍的移动已经颇具复杂,因此需要我们先绘制自己脑海中构想的UML状态图,体现书籍的状态转移及其条件等,有了状态图的帮助,可以让我们在编写代码的过程之中更好地理清书籍的状态移动与相应限制

第三次作业要求添加信誉分系统,用户信誉分不足时无法完成借书等动作,相当于对第一、二次作业中所完成的书籍的移动做出了一些限制,而这个限制过程就需要类与类之间的消息联合处理来完成,因此我们需要先绘制一个UML顺序图,展示用户和图书馆等类之间的消息传递,判断用户是否满足借阅的条件

可见,每次迭代都是目的鲜明,旨在帮助我们理解UML建模以及其重要性,因此,在正向建模与开发过程之中,能够选择正确的UML模型图对要求以及说明文档进行解释与归纳,对帮助程序开发是有十分重要的意义的

值得一提的是,UML图并非一成不变的,我们很难在真正着手于代码编写的过程之前就事无巨细地规划好所有相关信息以及细节,因此在代码编写过程之中,也需要对UML图进行更新与修改,一方面帮助我们理清代码编写接下来的发展方向,另一方面可以回顾之前的设计,减少出错几率,最终就会得到一份具有较强规划性的代码以及一张对代码进行明确说明的UML图,既方便自己事后进行迭代修改,也方便在大型开发过程之中与其他开发人员的合作

架构设计

对于多次迭代设计,我采用最后一次对架构进行说明,UML类图如下:

img

我将图书馆的各个部分分为多个类:BroOffice, DriftCorner, AppointmentOffice, Bookshelf,并将其统一归结于Library类进行管理,同时实现了Book, Student进行书籍和借书者的信息管理,作为信息载体保存在各个类之中。

分发处理

对每一条指令,我的大致处理流程如下:

  1. 由官方包解析得到command,交给Library的run()方法中进行分发处理,Library拥有各个指令对应的方法,只需要将command的信息在run()中传到对应方法,并对对应方法进行调用就可以实现分发处理

  2. Library实际上只是图书馆各个部分以及书籍、用户信息的一个载体,真正完成对应操作仍需要在各个部门类中执行。因此在Library的指令对应方法之中,只进行简单的信息处理,就将信息转至对应类的处理方法,如借书请求中,需要在Library的借阅方法中调用BroOffice中的借书方法。尽量让各个类各司其职,减少耦合度,增强可扩展性

  3. 在对应的部门类之中完成请求的执行

优势

总体来说做到高内聚低耦合的特点,迭代开发相对容易,修改的部分较少。只要减少耦合性,就可以为将来的迭代开发留出更多空间与自由度。同时,高内聚低耦合的程序往往拥有更强的鲁棒性,虽然没有直接关系,但易于维护的特点间接支持了这一点

缺点

由于中间进行了太多的分发执行,书籍的状态转移触发函数和条件都十分复杂,对状态图的维护与修改相对复杂,而且用户与Library之间的消息传递常常会牵扯其他的类,相当难以描述

模型追踪关系

由于我在完成作业时是遵循这样的步骤完成的:

绘制UML图 -> 完成一个功能块的编写 -> 更新UML图 -> 根据UML图完成下一个功能块编写 -> 再更新UML图 -> ......

因此我的UML图与代码之间的追踪关系相对较好,总体上可以认为UML图与代码符合

架构设计思维演进

第一单元

第一单元对架构设计的思维要求相对较高,在没有系统学习架构设计的前提下难免会出现重构等问题。得益于OOP的学习,我对面向对象程序设计还算入门,在第一次作业中经历了长时间的思考与许多次的推倒重来,选择了相对较合适的Poly - Mono架构,而之后的扩展之中,我充分认识到一个高内聚低耦合的架构的优越性,可以很好地完成迭代以及功能扩展的任务。

第二单元

第二单元对类的架构要求相对较低,类架构的要求几乎已经在要求中给出了,即策略类作为主控类,电梯类作为工作类,请求类作为信息类的形式。

然而,第二单元所实现的多线程需要我们对临界区及锁进行明确的规划,尤其是对共享对象的设置与互斥原子访问操作的设计。对锁的设置,可以选择所有线程按照固定顺序获取锁,虽然可能会占用更多的锁,但能够保证不出现死锁问题,而对共享对象的设置,可以考虑实现生产者——消费者模型中“托盘”机制,集中管理共享对象。

第二单元多线程的使用使我们的顺序debug方式不再可以使用,并且bug极其可能是单次或一定次数难以复现的,这就更需要我们采用稳定且安全的架构设计,从设计方面避免多线程相关的bug出现。

第三单元

第三单元JML语言不强调对架构的要求,我们只需要根据给出的JML语言的约束写出具体实现即可。

在我看来,这个环节更加像是已经设计好软件架构之后对代码的编写,将设计和实现分离,只需照着JML语言依照已有条件进行实现即可,即使在不同平台不同语言上也可以做到功能相同。由此也可以看出一个预先设计好的架构对程序编写的帮助有多大。

第四单元

第四单元的UML图更加强调软件编写前的设计,先将用户需求转换成一系列UML图,再根据UML图进行软件编写,过程中对UML图进行不断地修改,最后得到一份相互契合的UML图和程序代码

测试思维演进

第一单元

处于不太理解测试思维的阶段,对测试的理解仅仅停留在中测和强测,测试方法也只会断点debug测试和大规模数据覆盖

第二单元

由于断点debug测试无法应用于多线程程序测试,我采用了日志输出测试,即将线程相关信息输出到文件之中,可以根据输出日志判断线程当时所处状态,进而判断行为是否正确

第三单元

JML语言可以说是天生与Junit测试相附和,通过JML语言编写Junit测试,可以从功能块的角度对程序展开测试,较为方便地定位具体是哪个功能块引发了问题,确定好每个较小的功能块没有问题之后,再进行组合,之后如果出现问题,定位问题发生的范围也会缩小很多

同时由于这个单元考察算法与时间复杂度相关知识,引进压力测试也是十分必要的,可以有效判定程序运行时间是否符合要求

第四单元

我的第四单元的测试方法汇集了前三个单元的方法,对信誉分的实现我采用输出法,输出关键时间节点的信誉分值判断实现是否正确,对时间复杂度的预估我采用压力测试,集中对几个时间复杂度较大的方法进行压力测试,考量程序运行时间,最后进行大规模覆盖测试,保证程序整体正确性

课程收获

在这门课程之中,我首先依据Java学会了一些面向对象程序的特点,了解并实现了一些面向对象的程序并学会代码风格的维护,更为重要的是,我在这门课程中学会了许多关于程序架构设计的方法,懂得了一些软件工程入门的知识,我相信这对我在计算机领域的探索上一定会有巨大的作用,最后感谢OO课程组,感谢老师和助教的帮助!(如果能调换一下单元的顺序或者难度就更好了,又或者把第三单元或者第四单元的知识往前提一些,对复杂程度比较高的第一二单元应该也有帮助吧)

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

302

社区成员

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

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