OO第四单元总结

一、单元架构设计

1.类图(第二次作业)

2.设计思路

  本单元OO作业主要涉及两个过程,即先根据输入的elements数组建立UML存储模型,而后基于这个模型实现一系列查询判断功能。

  在类增设的考量上,我为每种有用的UmlElement都创建了类来管理,每条UML模型输入必然对应一个element的创建或信息添加,这样有利于厘清各element之间的关系。在存储结构上,汲取上单元的经验,容器的选择依据要求实现的查询判断功能而定,选择有利于加快查询判断速度的存储结构:为满足总体计数的要求,使用ArrayList存储全部元素,同时使用HashMap建立id到元素以及特定元素类型到数量的映射以满足类型计数的要求。对于涉及到递归的查找统计,采用记忆化的方式:每层都维护一个变量存储结果,当非第一次查找(该变量值不为null)时直接返回,加快递归速度。

  建模部分,我采用的算法只需对输入的elements数组进行一次遍历,速度较快。但所需解决的问题是:有时并不能根据输入的element确定UmlElement的类型。这就需要增设诸多用于暂存的数据类型存储中间态元素,比如第一次作业中的Base即为UmlClassUmlInterface的中间态,第二次作业中的Meta即为UmlEndpointUmlLifeline的中间态。当出现能将中间态元素转化为确定的UmlElementUML模型输入时再将其“转正”。

  这样的架构存在一定隐患:在中间态元素“转正”时,其本身的属性自然容易拷贝,但指向它的指针却容易被遗忘,造成指针的失效。这个bug困扰我相当长的时间,而后通过维护一个指针Map解决,在“转正”时将指针重置。

 

二、前三单元架构设计总结

  第一单元对多项式求导的子任务是输入合法性检查和多项式模型的建立。合法性检查依赖正则表达式实现,设置专门的InputHandler类,确保进入下一环节的输入是合法的。多项式模型则由多项式的自然组分确定,自顶向下分为多项式、项、因子等等。各层次的求导和输出依据各自法则进行。事实上,合法性判断也可以拆分到各个多项式组分中进行,提高内聚。

  第二单元则是多线程架构的实践。这一部分中,掌握一些固定的多线程设计模式能有效保证线程安全,避免忙等。但由于时间紧张,我都是依照自己的简单理解以及强行加锁的方式保证线程安全,牺牲了效率。大体按照生产者-消费者模型设计:输入处理类将处理好的请求放入缓冲区,电梯则从缓冲区中取出指令执行,通过锁缓冲区的方式保证同一时刻仅一个线程访问缓冲区。

  第三单元的架构设计体现在类增设的考量以及存储模型的建立方式。考量类增设时要厘清程序的层次关系(如地铁站—图—路径—边),并按照高内聚低耦合的原则增添类,使程序结构更清晰。在容器选择方面,一般使用ArrayList实现数组化存储,使用HashSet实现集合存储,使用HashMap建立id到元素,种类到数量等的映射,方便查找。三种容器的综合使用可以在各类查询中实现最速。此外,本单元还涉及到一些图论算法,使用邻接矩阵配合弗洛伊德算法及深度优先搜索完成各类要求。

 

三、对OO的理解的演进

  对于“面向对象”,我最初的理解是模块化设计——“类”的设定自然而然地体现出了模块化的设计思路。第一单元前两次作业将多项式根据符号拆解为各个组分,并归入模块的过程加强了我对这种设计思路的理解。而第一单元第三次作业由于多重嵌套的存在,无法像前两次作业那样简单的拆解。于是引入层次化的设计思路,构建好层次(多项式—项—因子)和各层次需要做的拆分之后,便可以通过递归解决嵌套的分解。此外,通过继承和实现机制,还可以抽象出诸多模块的属性特征和行为特征,实现同一基类派生的不同模块的统一管理。有了模块化,层次化的理解之后,就要考虑到模块的设计原则:实现模块信息、逻辑对外屏蔽,提高模块间的独立性,降低模块间依赖程度,便是“高内聚低耦合”这一设计原则的初衷。这点在第三四单元需要自己增设类的时候有所体现。此外,第三单元中介绍的JML规格语言是保证各模块正确性和构建测试的有利工具。

 

四、测试演进

  OO课程让我充分认识到完备测试之必要性,我的测试手段经历了如下演进:一开始,在脑海中随机生成数据,但这样产生的数据规律性很强,难以突破思维定式。认识到这个问题,开始针对特殊情况(如越界,个数为0等)构造测试集,但这种方式无法稳定地检测出结构问题。针对这个问题,手动构造尽可能覆盖程序分支的测试集。综合三者便能测出一些较为浅显的bug。但当程序逻辑复杂,分支数多时,还需自动测试进行覆盖。对于结果固定的程序,可以使用随机生成的数据对拍,而对于无法对拍的情况便只能从功能上验证各环节的正确性了。这里基于JML的JMLUnit,TestNG等提供了行之有效的规格化测试方法。

 

五、课程收获

  OO这门课让我对写代码有了全新的认识。写码前清晰的架构设计,写码时诸多细节的控制以及充分的测试对于一个工程来说都非常重要,缺一不可。另外,通过这门课我了解了面向对象这种强大的设计方式,其优势便是将巨大的project拆分为可解的部分实现,利用语言特性实现简化管理。这种breakdown的处理方式解决计算机问题往往非常有效。正如Butler Lampson所言:”All problems in computer science can be solved by another level of indirection.”

 

六、改进建议

  1、由于每次作业一周的时间比较紧张,往往不敢尝试固定的设计模式而自行摸索。因此建议课上内容增加对设计模式的讲解,或给出更为明确的参考资料。

  2、建议给出自动测试的实现思路。帮助同学更充分地测试。

  3、提供更加方便的在线浏览优秀代码的方式。

 

posted @ 2019-06-24 21:54  CapFreddy  阅读(189)  评论(2编辑  收藏  举报