面向对象课程总结
一、单元4架构设计
作业1
作业1,我在顶层采用了HashMap将类(接口)与其对应的内容进行一一映射存储,进而将查询操作向下分配给ClassDetails。在对类内方法的参数的存储上,我采取了相似的方法,即使用OperationDetails类存储,并将对方法参数类型的查询分配到该类内部。这是一系列可以用HashMap层层向下找的过程。
我还设计了一个单例类AllElements,这个类用来存储所有的id与UmlElement的映射关系,这使得程序从任何一个地方都可以根据id得到对应的UmlElement。此外为了方便,我还设计了一个单例类AllMaps,方便在ClassDetails类内部进行DFS操作时可以根据UmlClass或UmlInterface取得对应的Details。
作业2
作业2中,由于是对作业1进行扩展,即添加了新类型的Uml图,因此我将不同类型的图放到三个不同的package中,分别对三个图进行处理。当调用到对应图的方法时,由MyUmlGeneralInteraction类对下层的三个Interaction类方法进行调用。
这里沿用作业1的设计。
这里是对于顺序图的处理部分。
这里是对状态图的处理部分。
作业3
作业3则是在作业2的基础上添加对错误数据的检查,整体架构没有什么大的变动。关于错误数据的检查,也是层层分配到下一级的类中进行处理,直到分配到与该错误数据密切相关的层级进行真正的处理,并再逐层返回。由于整体架构与作业2一致,就不放UML类图了。
期末时间紧张,就不自己画UML图了,希望老师理解_(°:з”∠)_
二、架构设计与OO方法理解的演进
在上这门课之前,我对OO的理解就是封装、继承、多态。那个时候我以为,这一门课程就是会把封装、继承、多态的具体实现方式讲清楚。现在来看,我那个时候对OO的理解还是TOO YOUNG TOO SIMPLE。OO不仅仅是封装、继承、多态,还有架构设计、编程方法的相关内容。
第一单元是层次化设计,其实就已经把封装、继承、多态的核心内容讲清楚了。三次求导作业中,我主要思考的是我需要设置什么样的一个类,这个类是对什么事物的抽象。如何合适地设计一个可以实现要求所需功能的类,这便是我第一单元对架构设计的理解。此外,这个时候我接触到了TDD——Test-Driven Development。在开发代码功能之前,先将单元测试用例写好,这有助于在编程过程中对整体性的把握,可以避免在编程过程中的很多疏漏。但这个时候我还不太会用JUnit进行单元测试,因此没有付诸实践。不过,这是我所理解的OO编程方法的一部分。
第二单元是线程安全设计,这个单元是对多线程编程进行了一个初步的介绍。三次电梯作业中,我主要思考的是生产者-消费者模式的应用,进而拓展到对设计模式的应用。如何在自己的设计中合理的应用不同的设计模式,简化自己的代码,这是我第二单元对架构设计的理解。
第三单元是规格化设计,这个单元引入了规格的概念。这个单元中,结合OS课程的“抽象与权衡”的思想,我较为深刻的理解了抽象的思想。而规格,就是将编程过程中的行为抽象出来,将行为从具体的代码实现分离出来的一个表示方式。虽然JML不是很好用,但是将行为与代码实现分离的思想很符合面向对象的设计方法。我可以确定某个模块的行为,但是其具体实现却可以随意替换,只要可以实现该行为,我可以采用不同的容器、不同的算法、乃至不同的子架构,这对于我之后的编程具有十分积极的影响。
第四单元是模型化设计,即用UML来表示架构设计。UML图很直观,可以表示的场景也很多,果真不愧被称为“统一建模语言”。通过UML语言,便可以将架构设计与代码实现彻底地分离开来,我可以不用考虑使用Java还是C++,但是我却可以把我的程序架构设计出来,这就是UML的奇妙之处。此时我对于架构的理解就不再依赖于某一种编程语言,架构设计就是一个独立于编程语言的过程。
以上便是我对架构设计与OO方法理解的演进。
三、对测试的理解与实践的演进
测试是保证程序正确性的必要手段。没有人可以保证自己在写程序的时候从来不会写出bug,而测试便是消灭这些bug的重要方法。
第一单元,我看到有很多同学使用python和cmd搭建数据生成与自动对拍脚本,于是我也尝试搭建了一个。虽然数据是随机生成的,但说实话效果还真不错,我的第二次作业就在提交前一个多小时被发现了一个“敲错了一个字符”导致的bug,而且还帮助我在互测中收获了一些成果。这里的自动对拍脚本优点是可以自行进行测试,省去了人工测试的成本。缺点1是数据完全是随机生成的,没有针对性,需要补充人工构造的特殊样例,此外还有缺点2是搭建需要消耗较多精力,如果有新的项目,甚至于对老项目进行迭代,都需要对评测脚本进行修改,评测脚本的可移植性极差。
第二单元,由于是多线程,需要依照时间进行输入,我使用python的subprocess模块进行数据的处理与定时输入。这个单元我没有进行数据自动生成的工作。多线程bug的出现是偶然性居多,同样的测试数据运行不同次,结果可能都不一样,因此生成随机数据的意义就不是很大了。这一单元我主要采用手动构造测试数据,并使用python帮助我进行特定时间点的输入,因此在测试上是比较朴素的。
第三单元,我接触到了JUnit。JUnit与规格的搭配简直是绝配,我根据每个方法的规格,对这些方法的行为进行了大量的测试,效果非常好。从第一次作业的JUnit样例可以一直沿用到第三次作业,因此当我为了改善性能而对程序代码进行大批量修改时,就可以在修改完毕后再运行一次单元测试,这样便可以知道有没有改出问题来。第三单元我完全没有通过输入输出进行对拍测试,而完全将测试转移到对方法行为的检验上,感觉效果很好,用起来很舒服。
第四单元,由于临近期末,时间较为紧张,我的测试做的比较少。本单元的测试主要还是依赖于我对于极端情况输入数据的构造上,对与JUnit的使用不是很多。由于我比较仔细地构造了较多情况的样例,最后的强测结果还算可以。
四、课程收获
- 简单理解了面向对象的哲学思想(并不算深刻理解,还需在日后的学习中继续感悟)。
- 大致熟悉了Java语言的使用。
- 了解了git、Typora(MarkDown)、StarUML等一系列工具链的使用。
- 规范了自己的代码风格。
五、一点建议
- 希望上机实验可以有一些结果反馈。同样也希望每次上机实验的内容能再完善一些,尽量把一些令人疑惑与迷惑的内容都讲清楚。//(我知道上机实验是助教们根据教学过程中的需求,在开始实验前不久才确定下来的内容。这样的好处是题目的灵活性较强,可以随时根据教学情况进行调整。但是感觉有些时候实验题的严谨性还有一些值得商榷的地方。因此我想的是,是否可以将一些严谨性较佳的实验固定下来,在每年延续下去,使得部分实验在经历了不断地迭代之后,成为OO课程每年的「精选实验」。)
- JML单元最后的难度全部集中到了算法上来,对JML的学习反而是弱化了,所以感觉JML单元的内容可以再调整一下,减少一点关于算法的考察。//(光是Tarjan算法我就研究了一天半,结果最后还是出了点小错误,哭)
- 我不是很了解最后的总评成绩是如何计算的,不过感觉可以在总评成绩计算的时候可以考虑「去掉一个强测最低分」,因为感觉OO这么多次作业,即便是非常优秀的同学,也难免会出现「翻车」的情况。一次偶然的失误不应当对最后的总评成绩造成重大的影响,因此感觉去掉一个强测最低分是合理的。//(最高分就不要去掉了哈哈哈)
六、线上OO体会
个人感觉,OO是本学期线上课程中所受影响最小的一门课了。不需要现场上机(OS课设每周上机考试取消了),不需要期末考试(OS理论课期末考试线上开卷了),只需要按时完成每周的任务,实验课按时进行实验就好了。
对于我来说,我觉得线上的OO虽然少了许多和同学面对面的机会,却可以使我更加独立地思考如何去做每一次的作业、如何设计架构,对于OO的学习反而是更有帮助的。
此外在最后一次实验课上,我家里停电了,这应该算作我在线上OO受到的最大影响了吧。电力因素的不稳定,可能会对线上课程造成很大的影响。虽然概率很低,咋就恰好让我给碰上了呢?【无奈】
最后,感谢老师和助教这一学期的辛勤付出,正是因为你们的付出,才让我们的线上课程得以开展下去。也感谢一直在和我探讨问题的同学,正是在交流的过程中我解决了很多个bug,也正是在交流的过程中我们能够共同进步。
看上去OO课程已经结束了,但其实关于OO的一切才刚刚开始。加油吧!