2019_BUAAOO_第四单元总结(课程总结)

 

2019_BUAAOO_第四单元总结(课程总结)

 

一、总结本单元两次作业的架构设计

  本单元的内容是对UML类图、顺序图、状态图进行解析,并且能够实现对其的查找功能。

  1. 第一次作业

  第一次作业只是要求我们对UML类图进行解析。对于每一个UMLElement都有其唯一的标识符id,所以为了便于查找和存储,我使用了HashMap的容器来存储,每次寻找只需要通过其id作为key来找出对应的元素即可。

  然而查询指令都是通过名称name来寻找相应的元素,如果只使用id作为key的话,就无法很好的适应这个场景了。但是如果用name作为key,在有些特定的元素,是可以存在重名的,比如UMLClass,所以我设立了一个HashMap<String, ArrayList<balabala>>的容器,name作为key,这个名称所对应的元素作为value,这样的话可以更方便的通过name来寻找对应的元素,并且判断重名也十分的方便,只需判断对应的arraylist的size是否大于1即可。

  UML类图的层次比较复杂,为了方便处理这些层次,我自己新建立了多个类,这些类里的属性里不仅有其原本的UMLElement所存储的信息,还存放了其他更加具体的东西,比如Class类,不仅存放了UMLClass元素,还存放了属于这个类的属性、方法、父类、祖先Arraylist等等。这样自己重新建立类,可以更好的将原本离散的一条一条信息,按其原有的层次存储起来,这样在查询过程中会简化许多。

  在UML类图的解析中,最复杂的步骤还是处理继承和关联关系。对一个类的查询往往也会涉及到其父类,因为它继承了父类的属性、方法等。所以在查询前,要先对这个类进行“找爸爸”的操作。在寻找其祖先类(接口)时,我使用了迭代的方法,找寻一个类的父类,若有,则将这个类的所有属性、方法添加到子类的数组(或HashSet)中。以此循环,直至所找寻的类不再有父类,停止迭代,再对刚才迭代的结果进行处理(去重等)。

  同理可以处理关联关系,只需要利用公式:一个类的关联 = 父亲的关联 + 自己的关联。

   2. 第二次作业

  在第二次作业中,增添了对UML顺序图和UML状态图的解析。对于两种新增图的查询并不难,但是难点是在UML规则的检查上,具体的算法实现需要进行一些斟酌。在判断R002规则时,采用了dfs算法,对每一个类、接口进行dfs递归,如果找到一个环,就先存起来,最后用HashSet去重后输出。

  在判断R003时,我采用的思路是,对每一个接口和类全部进行findAncestor()操作,操作的结果是,每一个Class和Interface类里存放了<所有祖先类(接口)数组>,是可以有重复的。这样我们判断的是否有重复继承的时候,只需要判断这个元素的<所有祖先类(接口)数组>是否有重复,如果有重复则说明该元素继承了两次同一祖先,所以将其存到输出数组里,最后进行去重操作,然后输出。

  在第二次作业的强测中,我被测试出了两个bug,原因是对UMLElement的了解不够充分。

  ① EndPoint可以传递Message,也可以作为接受的那一方。然而我只默认了他可以传递message,接受的一方只能是lifeline,所以如果有传向endpoint的指令,就会出错。

  ② 寻找后继状态的时候,使用了bfs算法,初始状态没有进行去重处理。若有两个相同的状态转移,则会多算一个后继状态。

 

二、总结自己在四个单元中架构设计及OO方法理解的演进

  在最开始的设计(假期预习)中,我采用了“一main到底”的设计方法,在第一单元的求导中,虽然新建了类,但是也并不能很好的理解层次化的含义,也不知道该如何做到层次化设计。 最终的目标只是能够AC即可,没有考虑复杂度和代码可读性等,只注重了准确性。因此在第一单元的新作业的发布时,我总是开始重构,重新写代码,因为代码的耦合性太强,“牵一发而动全身”,所以就索性不改了,重写代码。

  第二单元的电梯多线程,通过生动形象的“消费者——生产者”模型,我开始对层次化设计产生了一些理解,也理解了抽象的含义,以及开始更注重代码的可扩展性和可读性。由于采用了CollentionSychonized的对容器的加锁方法,在实现同步上简单了很多,让我深刻体会到了java内置类的强大和多样性。

  到了第三和第四单元,我开始从每单元的第一次作业就注重层次化的架构设计,所以在一次一次的新需求添加时,我没有重构,只是在原来代码的基础上做少量修改和扩展。由于不需要重构,可以直接使用上次作业写好的东西(算法,方法等),所以写代码的效率也有了很大的提高。

 

三、总结自己在四个单元中测试理解与实践的演进

  最开始的测试,我只是在控制台进行输入,并手动对比输出。进入求导单元的化简时,这个方法就不可行了,尤其是三角函数的化简,是有多种答案的,用手算则会十分耽误时间,降低效率。于是我借用了python里的化简函数,对输入的表达式进行化简,然后再用python判断两个表达式是否相等。此外,在第一单元单线程的测试中,我还从同学那里了解了脚本评测,自己照猫画虎写了几个脚本,输入复杂的表达式,让脚本自动帮我评测(可以同时评测多个程序),也抓到了不少互测阶段其他同学的bug。但是更高级的操作——写数据生成器,我还没有研究,数据生成器都是借用大佬的。但是在阅读源码之后,我发现写一个数据生成器也不是特别的困难,只是需要更多的耐心去思考,如何写出一个能生成更随机化,更复杂的数据。在第二单元的多线程的测试中,由于存在时间戳以及每个人的电梯调度方法不同而导致的结果不同,无法使用单纯的脚本来进行自动化评测了。这个时候有大佬写出了通过输入请求,和结果来判断电梯送人是否正确,而不关注电梯是如何送人(过程)的java程序,来判断正确性。

 

四、总结自己的课程收获

  在本学期的OO课程中,我收获了很多。学会java编程只是一部分收获,更重要的是学会了层次化的结构设计,以及对问题抽象化的处理方法,也体验了在实际工作中如何应付需求的变化。以前我的代码风格是很差的,在变量的命名或者是函数、方法的结构设计上都欠缺,在经过了一学期的OO课程的训练打磨后,我在写代码的时候更加注意自己的代码可读性,让自己和别人都能看得懂自己的代码和逻辑。

  此外,在上文也提到了,我也学会了如何写一个脚本,如何用命令行进行编译、运行java,并推广到了C++和python;同时我也学会了如何使用gitlab,github,以及代码的上传、提交、修改、版本回退等操作;对于某些算法,我也进行了亲身实践,比如图的迪杰斯特拉算法、floyd算法、bfs、dfs算法等等;在设计多线程代码的时候,也帮助我更好的理解了另一门课OS操作系统的进程的调度;在平时的研讨课中,借鉴了其他同学的设计思路和逻辑,也可以有幸听到专业领域的牛人来给我们做讲座,让我们更好地了解到这些领域。

 

五、立足于自己的体会给课程提三个具体改进建议

  今年的OO课程改革的效果是显而易见的,大家都认为效果十分的不错,尤其是在测试方面,体验感很好,避免了以前会出现的种种问题和不愉快。

  对于课程的三个建议:

  1. 中测的强度有些偏弱,很多最基本的bug测试不出来,希望课程组以后可以适当的增加中测的强度。

  2. 上机实验课和理论课的课程时间的安排,今年大多是上午上完OO理论课,下午的实验课就对上午所讲的内容进行测试,会让很多同学感受到有些困难。

  3. 理论课所讲的内容可以穿插一些作业方面的,稍微具体一点的讲解和提示,以及可以适当降低性能分所占比例。这样可以减少同学们的作业压力,会让同学们有更多的时间和精力来思考如何构造一个好的架构,以及良好的代码风格。

 

  总体来说,改革后的OO称得上是一门“良心好课”了,感谢老师和助教们一学期的付出,祝愿课程原来越好。

posted @ 2019-06-24 18:16  zja1999  阅读(134)  评论(0编辑  收藏  举报