BUAA OO UNIT4单元总结及学期总结

BUAA OO UNIT4单元总结及学期总结

 

本单元作业的架构设计

​   第四单元的主要内容是对于UML图的解析,学习的首要任务是要了解UML图的组成、结构以及其他的一些必要知识,掌握不同uml类型存储的信息。UML图的本质是将类之间的关系抽象为对象,按照一定的层次结构组织起来,构成没有二义性、逻辑严密的规范化语言描述。对于UML图解析器代码的编写,主要可以理解成三个任务的完成:第一个是存储,将读取到的内容用一定的数据结构存储起来;其次就搜索和查找,我们将在这里具体实现解析的动作。下面我就对于我在本单元的三次作业的代码架构进行分析。

第十三次作业

  本单元的第一次作业是我做得最为艰难的一次作业——因为是初次接触“UML图解析”这一问题,对于UML图的组成、结构以及具体内容缺乏了解,花费了一些时间进行自学。

  因为官方包中将UML类图中的每一个元素都抽象为了UmlElement的一个具体实例,且每个UmlElement中都存放了自身id和parentId。因此通过一个UmlElement的实例查找其parentUmlElement就可以轻易实现,但是这样无法完成查询childElement的操作。所以我就自己以官方包为基础,新建了将UmlElement进一步组织的类,从而使得通过父节点查询子节点的操作变得更加简单。

  而具体的存储数据结构也就是很常见且经常用到的树结构,例如在新建的MyUmlClass类中,我在其属性中设立了ArrayList<MyUmlAttribute>用以存储该类下的属性,而具体该属性的组织过程如下:首先我会对UmlELement进行一次遍历,将其中的UmlClass全部找出并完成实例化,在第二遍遍历中,我会将读到的UmlAttribute通过parentId寻找到其所属的类,最后我将该属性加入到该类的ArrayList<MyUmlAttribute>中。

  在该次作业中,我最初想到的是通过设置多个全局HashMap来进行数据存储,但这样给后续的查询和搜索操作带来了较大的麻烦,且使得我的解析器内部的代码变得十分冗杂。因此我最终决定采用上面所说的自建新类的方法。但是综合来看,仍然存在着一些不足:直接把存储的过程暴露在了UmlInteraction上,没有作任何的封装和处理,导致代码结构还是会变得冗长。

 

 第十四次作业

在第二次作业中,新增了处理顺序图和状态图的需求。因为这三类处理都是相互之间没有什么关联,所以我将解析器中的类图、状态图、顺序图三部分的解析内容都独立出来,分别实现了三个新类,并在解析器中分别调用三个类用于功能的实现。总体来说,实现过程较为简单。

 

 

第十五次作业

第三次作业主要是要解决“检查规格合法性”的问题,对于该问题,我在类图、状态图、顺序图的存储类中分别实现了相关的8种检查。本次作业的难点我个人觉得是相关方法的实现,例如R002(检查循环继承),由于接口具有多继承的特性,所以需要尽量低复杂度的查询算法,但是因为对于网上搜算到的较为高级的动态规划算法等算法不太熟悉且考虑到该检查在整个执行过程中只会执行一次,我最终选择了相对稳妥的dfs(深度优先算法);对于R003和R004同理。

 

 

 

四个单元架构设计和理解演进

第一单元设计和思想

  第一单元的任务是实现多项式求导。由于指定的输入从本质上来说为一串字符串,我们的任务就是要将该字符串处理成为计算机能理解的有意义的多项式并可以进行求导运算。而这就带来了一个重要的概念——层次化设计,由于多项式是由一些最基础的单元组成的,所以在多项式中我们可以构建出一个树状结构,从而可以实现多项式的一个自上而下的分解。而求导的思想则是对于这个自上而下分解的树状结构的叶子节点进行求导后,再进行自下而上的合并,最终得到需要输出的最终结果。

  在第一单元的三次作业中,最为核心的思想就是“递归下降分析法”,利用这个思想我们可以较为轻松地将多项式分解。

  总之,第一单元的学习使我对于层次化设计和代码可扩展性的重要性这两个问题有了更深地了解和掌握。

 

第二单元设计和思想

  这一单元的任务是实现一个电梯,基本要求也逐渐从开始的“单电梯ALS”到最终的“多电梯可换乘”。由于最终要实现多电梯同时运行,因此共享变量的互斥访问便是不可避免发生的事情,这就带来了本单元的核心问题——线程安全设计。在第一单元的层次化设计基础之上,我们需要实现一个主调度器对于所有输入的请求进行统一的处理,将请求分配给相应的子调度器,而每个子调度器则根据其所负责电梯的相关信息来即时处理电梯需要执行的请求的先后顺序和进出时间。线程安全方面,我并没有具体实现线程安全类,而是在每个线程里面添加同步块实现互斥,这样也给我带来了线程安全不好统一处理和管理这一问题。

  在多线程中,我体会到了这一领域“面向对象”语言相对于“面向过程”语言的优势——将线程抽象为对象的实例来进行处理。

 

第三单元设计和思想

  第三单元的架构设计比较固定,自己新建的类比较少,主要是理解JML规格的语法,并根据要求写出功能和规格都正确的代码。此外,还需考虑所实现方法的时间复杂度——在这一单元,我对于代码的低时间复杂度的重要性有了更深的理解。

  JML对于规格和方法可以进行没有二义性地限制,这让我对于程序建构和程序测试等一系列问题有了更深的理解。

 

第四单元设计和思想

  第四单元的架构设计已经在前一部分进行叙述。

 

 

测试理解与实践的演进

  第一单元我利用评测机进行了相关测试。数据为随机生成——由于作业给出了表达式的生成式,根据生成式随机生成就可以较全面地生成测试数据。但是一些极端情况的测试样例仍需要自己进行构建。

  第二单元我做的测试并不是很多,主要是针对线程安全问题自己手动构造了一些有一定强度的电梯请求序列,并测出了一些线程安全方面的问题;此外对于电梯的运行逻辑,也是手动构造一些特定的请求序列,观察电梯的运行状况。

  第三单元我实现了基于JML规格的测试——基于Junit这个工具,通过JML限定的条件可以对输入数据的种类进行一定的划分,降低了测试的盲目性,提高了测试数据的覆盖率,同时我也自己构建了一些高强度的测试用例对于代码功能的实现进行相关测试。总之,相较于其他单元,该单元的测试总体来说较为轻松。

  第四单元我体会到了白盒测试的重要性。在本单元我获得了如下的经验——在写代码的时候,可以对于自己不自信的地方进行标记(//TODO标记很好用),并在编写完成后立刻进行针对性的测试。同时因为本单元的情况较多,容易出现一些理解上的错误,我也和其他人进行对拍测试,测出了一些自己因为错误理解导致的输出错误问题。此外由于本单元对于各种情况进行了较为清晰的划分,所以也可以较为轻松地实现测试的高覆盖性。

 

 

课程收获

  1. 学会了面向对象的思想,而不只是用之前面向过程的思想取处理相关的问题;
  2. 寒假pre增强了我的语言自学能力;
  3. 第一单元作业使我理解了层次化设计和代码可扩展性的重要性,此外还学会了递归下降的分析思想,总结中也学会了基于圈复杂度等概念分析代码质量;
  4. 第二单元作业增强了我对于多线程的理解,并学会了进行线程安全方面的设计和测试;
  5. 第三单元使我学会了基于规格实现代码和进行测试;
  6. 第四单元使我学会了读UML图,部分掌握了UML中不同类别元素的关系和含义;
  7. 在写代码的过程中,我掌握了许多之前没有接触到的重要算法以及相关思想;
  8. 我报名了本学期我们班的第二次研讨分享,给同学们详细介绍了容器相关的知识。在提问环节,同学们提出的一些问题我自己在准备的时候也并没有考虑到,老师和助教在一旁的解答也让我收获很大。在讨论中,我感觉对于相关知识以及这门课程有了更多的理解和感悟;
  9. 除了老师和助教的帮助以外,还非常感谢这学期身边朋友们给我的帮助——我们在一起编写测试数据,一起debug,还有评论区里热心回答的同学们,给了我很多有价值的启发和帮助,让我受益匪浅。

 

 

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

  1. 可以适当分享优秀代码的实现过程供大家学习,有时候有时候只通过自己自行阅读互测屋中的代码,很难把握到其中的精髓;
  2. 理论课和实验有一些脱钩的感觉,希望可以有指导同学如何设计评测机以及如何具体应用工厂思想等重要设计思想的相关专题,可以多给同学们一些了解相关知识的渠道,有些同学对于这类知识很感兴趣但是没有太多渠道学习;
  3. 感觉当前第一、二单元的重点有些偏离面向对象的意思——有些同学花费了大量时间在性能优化上,而这和面向对象的思想并没有太多的关系,可以尝试在面向对象方面加强难度,而且刚开始就面对难度较高的问题,很多同学会有一些不适应。
posted @ 2021-06-26 19:37  for_wheat  阅读(55)  评论(0)    收藏  举报