BUAA_OO_第四单元
一、作业架构设计
单元任务
第一个阶段是实现一个UML类图解析器UmlInteraction,可以通过输入各种指令来进行类图有关信息的查询;第二个阶段是扩展类图解析器,使得可以支持对UML状态图和顺序图的解析,并可以通过输入相应的指令来进行相关查询。同时在所解析的UML模型基础上,按照规定的规则检查模型中是否存在违背规则的情况,并输出相应信息。
第一次作业
本次作业主要分析类图,将官方包解析的内容设计结构来重新建模并存储。在作业中设计树形结构,以UMLClass类作为顶级节点,使用Map数据存储类型来控制树型结构中的结点聚合,具体的结构框图如下:
其中的标签为在程序中的Map内容,前者为键值,后者为具体的每个内容。同时针对类和接口的继承方法分别采用单对单和单对列表。
对于CLASS_COUNT,CLASS_ATTR_VISIBILITY等指令,直接从根节点开始索引到相应对象,进行直接查询操作;对于CLASS_TOP_BASE,CLASS_ASSO_CLASS_LIST等需要回溯的指令,优化的关键在于缓存,将每一次计算结果存储起来,在以后需要用到的时候直接取出而不需要再次计算。
本次作业中代码较为冗余,没有抽象出其他的类,因此只有Main类和MyUmlInteraction类,UML类图如下:
第二次作业
本次作业除了类图以外还增加了顺序图和状态图的管理和查询指令,同时给出了三条规则用以检验类图是否合法。这次的作业是在第一次作业的基础上进行修改:
-
将原本的MyUmlInteraction类改为ClassModel类
-
增加了StateMachine类用于处理状态图
-
增加了Collaboration类用于处理顺序图
-
增加了CheckClass类用于检验类图的合法性
-
增加了Tarjan类和AllPath类用于计算
状态图和顺序图中同样建立了树形结构,具体的索引在上一部分的图中作出展示,由于内容关联度不大,分别建类便于管理。在UML类图规则检查方面,第二个规则和第三个规则都是在解决图的问题,因此把类图中的类和接口当做图的点,继承关系和实现接口关系当做边,抽象成一个有向图。针对循环继承,采用Tarjan算法计算有向图强连通分量;针对重复继承,判断两点间是否存在多条路径。
本次作业的UML类图如下:
二、在四个单元中架构设计及OO方法理解的演进
架构设计:是人们对一个结构内的元素及元素间关系的一种主观映射的产物。架构设计是一系列相关的抽象模式,用于指导大型软件系统各个方面的设计。一个好的架构能够合理安排程序结构,不同类型之间的交互,让开发效率和质量都能够有所提升。
OO方法:是一种把面向对象的思想应用于软件开发过程中,指导开发活动的系统方法。面向对象就是基于对象概念,以对象为中心,以类和继承为构造机制,来认识、理解、刻画客观世界和设计、构建相应的软件系统。
第一单元
在第一单元主要做的是将面向过程的编程思想像面向对象的编程思想进行转变。从意识到每一单元的作业都是单元内层层递进的后,开始注意到架构设计的重要性。从第二次作业开始,便开始在动手码代码之前思考下一次作业可能会增加什么东西,从而留出可变空间,因此第二三次作业架构基本一致,并没有进行什么重构。
在编程方法方面,第一次作业也算是按面向过程的设计方法来设计的,一个类走天下;从第二次作业开始也逐渐有了面向对象的意识,能够开始将相似的数据结构来抽象成一个类,将一些运算的操作抽象成一个类,虽然抽象运算类也仅是调用类中的过程计算;第三次作业便已经开始抽象出父类开始使用继承了。同时也开始重写了许多原有方法,如equal和toString,新增很多get和set方法,这些给程序扩展功能提供了很大的便利。
当时存在的主要问题是:不会也不愿使用Java中其他的数据类型,比如HashMap等,只用自己用过的数据类型;代码风格很差,冗余度较高,想方设法地让每一个方法的长度正好控制在不扣分的范围内;对类的划分有的地方太细,有的地方就没有划分,出现了许多不必要的方法和重复代码。
第二单元
第二单元是为了学习了解多线程编程,最重要的是理解多线程的思想,这也是面向对象思想的一个方面。每一个线程直接是怎样协作的,理解了线程才能够更好地完成整个程序的控制,时刻记住线程安全,避免多个类对同一变量进行操作。
本次在架构的设计中也充分运用了工程化思想,增加设计的比重,将每一部分模块化,增加功能时只需要改变一部分,同时电梯的运行与控制分离,每个方法只负责一项功能的执行,避免一个类做太多的事情。第二次第三次增加功能没怎么改变架构。
但是代码冗余的情况在本单元仍然存在,同时没怎么使用继承和接口,数据抽象使用太少。对线程的控制仍存在一些不是完全清楚的情况,基本上只使用了synchronized块,没有使用过lock。
第三单元
本单元重点为规格的编写及阅读,面向对象编程适合团队合作完成,规格便是其中起到重要作用的一部分,使用正确的规格能够保证逻辑的正确性,保证团队的每个人能够实现一定的功能且保证了接口一致,优化代码风格。经过了一个单元的学习,在这方面有了很深的体会,虽然需要自己撰写规格的地方很少。
第三单元在OO思想中的体现主要如上,在架构设计中没有太多的设计,但是官方包的架构值得我们好好学习。一方面是官方提供了规格只需要我们填空,另一方面也经过了两个单元的训练,从本单元起再也没有考虑过方法长度会过长,每次都是一个方法只实现一个小功能。同时也尽可能地把所使用到的数据结构抽象出来。
第四单元
本单元虽说只有两次作业,但我觉得是三次作业的量合成到了两次里,不过经过本单元的学习,知道了UML基本的类图和状态图、状态图的规则方法,对面向对象语言的结构、状态变化等有了更深一层的理解认识。对于作业本身重点同第三单元作业一样,也在于设计高效的数据结构,如何将查询分别划分到不同的图类中,杂乱无章的元素应该怎样聚合在一起,构造层次关系。
本次作业完成起来在架构方面更得心应手,在设计的过程中自然而然地考虑可维护性和可扩展性,以及数据抽象。
三、四个单元中测试理解与实践的演进
第一单元需要对输入信息的格式作出判断,因此本单元测试主要为手工构造测试用例进行基础功能测试和边界测试,针对正确和错误格式的边界进行测试。不仅仅要对正确性进行测试,还要对错误格式的不同类型进行,如对同类型错误不同位置的多次测试。
第二单元除此之外还手动搭建测评机进行自动化测试,自动生成测试样例,读取测试并按时间延时输出模仿手工输入,并检查输出结果。由于本单元仅检查输出格式而不对具体内容作出限制,因此测评程序比较容易编写。同时多线程具有结果可变性,不一定能够复现问题,因此在测试出问题时,主要针对代码逻辑进行审查。
第三单元在正确性上的测试同上,课上也教过我们进行单元测试。出于对性能的需求,还要进行压力测试,通过自动生成不同强度的测试用例,测试程序能否在较大数据量的情况下继续正常运行,且判断是否会超时。在最后还使用了针对规格的测试,不仅可以检查规格,还可以基于规格生成测试样例。
第四单元的测试较为繁琐,步骤较多,在本单元的测试中又主要回归了人工,根据构造的各种各样的mdj,考察某一类的问题,每次针对于某一模型
四、课程收获
这门课的名称是面向对象设计与构造,除了面向对象的思想及架构设计等技能以外,我们还学到了许多在未来编写大规模软件时可能会用到的功能或者工具,如代码风格,监控线程以及JML规格语言和UML画图工具等,这些虽然在一开始接触时感到不耐烦“怎么每周都要用这么多新东西”,但在学习过后就能体会到它们起到的巨大作用,都能够帮助我们检查代码中的问题,帮助我们建立清晰的思路。
总的来说,经过一学期的学习:
-
架构设计能力有了很大的提升,不再是像最开始的时候需要考虑的时候再考虑架构问题,而是在开始实现代码之前就想好了未来可能的扩展方向。
-
面向对象思想有了更清晰的认识,数据及行为的抽象、专注于对象这一概念,进行类间及线程的控制。
-
代码能力及代码风格也有了许多进步,每次代码量少则几百行多则上千行,大量代码的编写提高了代码水平,和对代码的测试能力。同时每次要求的代码风格检查也让我体会到了写规范的代码的好处,一开始还总是会方法行数超出限制,再把方法割分,后来就没有出现过这样的问题了。
-
整合了所学的各方面的计算机知识,如操作系统中所学过的线程问题、离散数学或算法中所学到的图论算法都得到了应用。
-
学习了程序辅助工具的使用,如上面所说的监控线程以及JML规格语言和UML画图工具等。
-
-
实验课和讨论课结合,可以像后期的实验课一样,注重于查找发现和补充完整,前几次的课上写代码,时间实在过于紧张来不及好好设计,因此可以一个小时上机,半个小时进行一些解释同学们分享思路等。
-
可以每单元结束后提供一下合适的测试设计思路,对于一些消息闭塞的同学们来说,如何测试可能要靠自己一点点摸索,如果官方能够给出合适的建议那么将很好提升同学们的测试能力。