OO-U4


OO第四单元UML&总结篇

0 前言

本单元是oo的最后一单元,本单元的大体要求是设计一个图书馆管理系统,完成图书馆所支持的包括借书、预约书、捐书、还书等基本操作的模拟,本单元注重从UML到java代码的正向建模与开发,总体难度不大。

1 正向建模与开发

正向建模与开发的思想实际上我们一直在使用,但是可能建出来的模不是那么正规,也没有一个确定的呈现形式。比如我们可能会自己花一些草图或者大致的类的设计。更加确切地说,我们在计组中使用的设计文档实际上是正向建模非常好的一个实践,首先通过借鉴ppt或者学长博客来完成设计文档,然后开始设计verilogcpu,或者说那个logisim是不是也算是一种模型呢,可莉不知道呢

而UML则更多是提供了一个在团队开发中统一的建模工具,方便团队不同成员都能看得懂。

而正向建模与开发的实际含义则是:正向建模与开发就是首先创建模型,并以此模型为基础对系统进行开发和调整的方法。

可见正向建模并不是一簇而就,而是在其中进行了不断的调整和完善。

简单的说一下正向建模对我这个单元作业的帮助。

在第一次作业还是有比较完善的正向建模尝试,但是第二次作业因为os理论考试拖了一会,最后疯狂赶ddl,期间也有不少思路上的思考,第三次作业由于在我那个架构下几乎不需要什么调整(好像也在赶ddl),所以也是直接就开始修改了(几乎不需要添加什么新的类和方法)。

由于第一次作业在UML的使用上似乎有一些感想,我在之前已经有过一次研讨课分享的情况下又去进行了一次分享(ps:分享加分只有一次,不然得卷死去)。

如何更好的使用UML类图

感觉ppt做得挺好的,反正也是我做的,直接贴图(应该问题不大吧,可怜.jpg

这里简单提一下,虽然有UML这个东西进行过渡,但是如果仅仅是从我的手稿来开始打代码,似乎对我自己没什么影响,但是如果换个别人来看我那个抽象的手稿,似乎就很难沟通,或许这就是UML的巨大意义吧,怪不得叫做统一建模语言。

还有一个点是starUML太难用了,每次添加一个方法,默认添加在最下面,然后得自己手动一个个挪。。

2 本单元架构设计

本单元最终的UML类图如下:

对比第一次的架构:

这里架构差别比较大,是因为我在第二次作业的时候进行了remake,最后直接烂了(哭

2.1 第一次架构设计

第一次设计的时候认为功能相对简单,也是在上面提到的,认为只需要设计几个基本的机构就行。而且但是也分析了要不要设置一个Office的父类,让这些机构来统一继承这个父类,当时认为AppointmentOffice的功能和其他的差别挺大的,就没有强行拼凑在一起。

然后第一次作业为了模仿数据库的想法,还制作了一个DataBase的类,希望管理每个学生,实际上这里如果把StudentHashMap放在Library里面是一样的。

同时第一次我也想过,因为要画UML类图是不是还是类越少,图越好画。但是似乎对于面向对象架构的追求不允许我这么干,就是这里完全可以只有一两个类,所谓的Bookshelf这些本质上还是一个容器,那Library自己管理不就可以了(

第一次的架构整体还是非常简单的,而且在做的时候感觉跟OOpre好像啊。

2.2 第二次架构设计

第二级相对与第一次修改几个点,对整体架构影响很大

  1. 希望建立自己的Book类,这个Book是有自己的uuid,保证了不同书是不同的
  2. DataBase中管理我自己建立的Book,通过设置getBook()来通过课程组给出的LibraryBookId来获取到相应的Book
  3. 希望统一所有的机构,建立Office类,来让其他机构全部继承这个类

那么这个的设计遇到了几个难点

  1. Office的设计时,还是考虑了AppointmentOffice的功能和其他的不一样,因为需要管理已经预约的书,这个不是实体的书,就不好处理。当时是想到了图书馆有那个书车的东东,而且新北三楼南时羽的那个小车跟我这个希望实现的很像,就是先有一个预约请求就在这个车上,然后有预约就归这个车来存起来。

    虽然但是,当时忽略了这里的书需要保存是给哪个学生预留的,所以还是不能够做到统一化的管理,如果只是用一个空的student来强行统一就太怪了。

    而且这里还需要用一个有序的容器,以保证是实现了这个学生的第一个预约

  2. DataBasegetBook老是返回一个null,就是没有get到,这里花费了好久的debug的时间。

而且我这里的Office还有一个有意思的东西

/**
* 将通过getMoveBooks获取的书根据情况移动到office1或者office2中
    *
    * @param office1   前一个office
    * @param office2   后一个office
    * @param moveInfos 移动信息
    */
public void moveBook(Office office1, Office office2, ArrayList<LibraryMoveInfo> moveInfos){
   	...
       Office target = moveToFirst(bookId) ? office1 : office2;
   	...
}
   /**
    * 当有两个地方可以移动时,根据情况来确定移动到哪里
    *
    * @return 是否移动到office1
    */
   public Boolean moveToFirst(LibraryBookId book)

本来是打算如果还有其他情况要可能移动到两个地方的时候用的,后来发现只有AppointmentOffice用到了。如果还有其他地方用到,那么就只需要重写moveToFirst就可以了。

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

经历了oo四个单元,从层次化设计,到多线程程序设计,到JML规格化设计,到UML正向建模设计。

  1. 层次化设计单元中,我明白了把复杂的问题分解成更小、更管理性的部分的重要性。通过划分不同的层次和子系统,可以更好地组织和理解软件系统。我感到这是设计大型和复杂系统的一个关键策略。在这里学到了非常关键的一点,就是如何明确数据结构和功能结构,从数据的角度来看,是怎么一个层次结构;从功能的角度来看,是怎么一个层次结构。这个确实很重要,也是我后面单元开始设计时首先思考的点,我需要的数据结构是什么,我需要实现的功能是什么,等等,对我的代码架构设计思维有很大的帮助。
  2. 多线程程序设计单元带给我全新的视角,让我看到同时处理多个任务的可能性。了解到并行和并发的概念后,我开始思考如何利用现代多核 CPU 的全部潜力。不过,这也带来了一些额外的挑战,例如需要处理的同步和数据竞争问题。这一章确实是很难,我也感觉自己其实没有学到位,似乎是可能时间不太够的原因罢。可恶的超算!!
  3. 在学习JML规格化设计的过程中,我接触到了使用形式化语言为软件组件编写规范的实践。这使我深切地意识到清晰、恰当的规范对于开发和维护高质量的软件的重要性。同时,我也理解了自动化检查和验证工具在确保软件质量方面的重要性。这一单元难度倒是不大,对于架构设计也没有什么要求,但是却是对我的算法有比较大的提升,感受到了用java写算法的方便,有了一个好的数据结构尝试起来确实方便多了hhh~
  4. 最后,在UML正向建模设计的单元,我学习了使用统一建模语言进行系统建模和设计的技巧。UML图对于理解和沟通复杂的系统设计有着极大的帮助,这使我明白了良好的可视化工具在软件开发过程中的作用。这一单元让我第一次开始从最宏观开始思考代码架构,这一单元对于架构的思考占据了我大多数的时间。

总的来说,我对这四个单元的学习体验感到非常满意。他们覆盖了软件开发生命周期中的各个重要阶段,并且都与现实生活中的工作场景密切相关。通过这个过程,我对软件设计和开发的各个方面都有了更深更全面的理解。

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

在经过这四个单元的学习与实践,我的测试思维经历了显著的演进。

层次化设计单元,我开始理解到在每个层次进行适当的测试的重要性。我学会了创建对各个子系统进行单元测试的测试用例,并理解了如何通过做更全面的集成测试来验证各个部分和整个系统的交互。这里我开始尝试搭建评测机,也是对于黑箱测试的第一次尝试(之前都有过想搭评测机,但是都浅尝辄止。。

然后在多线程程序设计单元,我进一步意识到了并发问题对于测试的挑战性。我学会了很多关于如何设计并发测试,并理解了如何发现及处理可能的竞争条件和同步问题。在这个过程中,我对于复现和解决多线程中出现的错误有了更深入的理解。但是有一说一,为什么评测机上面RTLE的概率更大我还是不懂。

前两个单元用到的主要还是黑箱测试,就是放到评测机上面跑。

JML规格化设计单元中,我的测试思维再次得到提升。通过学习规格化设计,我开始注意到先设定清晰的期望和规范,然后对实现进行验证的重要性。此外,我也理解到了形式化验证工具在检验软件符合预期行为方面的重要性。这里用到了神奇的Junit来进行测试,也就是单元测试,单元测试让我重新认识了Junit这个东西,原来还包括了数据自动生成和进行形式化验证的东西,和我在oopre接触到的单元测试完全不是一个东西,感觉oopre对于junit的强调应该进一步加深!

最后,在UML正向建模设计单元,我学会了如何基于模型设计测试。通过创建和分析UML图,我能确定系统的关键操作,并据此设计出覆盖主要功能和交互的测试。这一单元的测试似乎有很多是正向建模的时候(或者是画好了真正的UML类图,亦或是自己的草图),实际上都是很多在这一阶段思考是否能够正确完成功能,没有想太多关于具体实现的问题。在具体实现完之后还是我们非常重要的进行黑盒测试。

单独把测试拎出来讲的话,我对于一个我写好的代码的测试主要分为以下几个阶段

  • 基本功能测试,这里是为了把指导书中提到的可能的情况都试一下,搓一下只有几行的简单数据
  • 极端情况测试,这里可能会搓一些比较极端的数据进行测试,比如数值大小,0,多个reset等等
  • 黑盒测试,感觉差不多了就可以放到评测机上面跑,这个实际上是主要的阶段。
  • 基本完成后,还可以和同学交换代码进行相互的走查,也就是所谓的白盒测试。

但是,这些,对于我这么一个赶ddl的人来说,主要的还是跑一跑评测机罢了。。

5 课程收获

我的oo真是一场豪赌,在这场豪赌中,我倾尽了几乎所有的时间,换来了一个烂完了的结果。

反思又反思,还是与我时间管理有问题,常常把任务拖到后面才开始做。但是这里更加根源性的问题实际上是给自己找的事情太多了,比如前两个单元但凡有烂的,必然是因为超算那边的事情。后面唯一一个出问题也是因为为了复习os理论,把oo作业稍微往后拖了一下,结果还想着remake,结果炸了。

在相对清闲的时间里,我还是能够快速完成作业,然后留有更多的时间来检查和测试的。

但是总归是一场有终止的赌博,在这场战争中,或许已经浑身是伤,但是至少有所长进。

鸣谢

鸣谢环节~

首先是感谢助教哥哥和助教姐姐们,讲实话很多时候都给了我很大的帮助,让我对于问题有了更加清晰的了解。

然后是感谢一路以来的同学们,包括syf、wxm、zyt、wxf等都对我帮助很大,包括讨论区其实也有很多很好的点子,非常好的氛围,让我受益匪浅。没有wxm和zyt的嘲讽,我也不会这么。。(额,编不出来,艹

最后其实,可能看到很多人其实都没有特别关注,我还是很感谢课程组的课程设计的。无论是对架构设计的重视,还是对于实践的重视,包括可能希望实现的oo理论考试,加上对于理论的重视,都让我感觉非常用心。

或许有很多人能够尖锐地指出课程组的问题,但我常常会带着一种学习的心态来看看待这些问题,带着解决问题的想法来看待这些。正是有问题存在,才需要一批又一批人来进行迭代。

比如我觉得co就没啥问题,或者有问题但是我无力解决,我就没有报名co助教(x扯远了,樂


文章作者: hugo
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 hugo !
  目录