BUAA OO第四单元及课程总结

总结本单元作业的架构设计

参考了一些往年的博客,发现主要有两种完成作业的风格:

  1. 根据UML的形式,建立起建立每一种umlelement子类的“加强版类”,并在构造函数中建立好每个类的联系,其余用来
  2. 不建立实际的umlelement之间的关系,而是根据所需要的功能指令,用抽象的方式直接实现。

后者的优点是编码量小,类的数量也会很少。

而前者,虽然构造函数会导致代码量非常大,但是扩展性好,代码架构也更为直观。综合考量之下,笔者选择了前者。

优点是,可以把类的数量控制在一个比较,代码比较简洁,编写起来比较容易。缺点就是MyImplementation就需要负责大部分功能的实现,这个类的复杂度会比较高。

第一次作业

类图如下:

由于各个umlelement具有依存关系,故按以下顺序读取对应的类

UmlClass
UmlInterface
UmlAttribute
UmlGeneralization
UmlInterfaceRealization
UmlOperation
UmlParameter

第二次作业

第二单元增加了顺序图和状态图。

类图如下:

读取的顺序如下:

//v1
UmlClass
UmlInterface
UmlStateMachine
UmlInteraction
UmlCollaboration
//v2
UmlGeneralization
UmlEndpoint
UmlLifeline
UmlRegion
//v3
UmlAttribute
UmlMessage
UmlState
UmlFinalState
UmlPseudostate
//v4
UmlInterfaceRealization
UmlOperation
UmlParameter
UmlTransition
UmlEvent

有一些不需要“加强”的类,就直接用Umlxxx的对象使用了,可以说有效降低了构造时的代码复杂度。

尽管如此,编写代码当中出于保险起见,还是建立了一些最终也没有用上,只在构造函数中构造了一下的类如Myregion。

第三次作业

第三次作业是实现有效性检查。我的大致思路是在原有的构造函数上增加一些判断条件,如果发现会出现错误,则将一个标记属性变为true,有效性检查时直接对标记属性进行检查,判断是不是要抛异常即可。对比较复杂的异常,通过遍历MyImplementation中特定的元素,收集他们出错的有序对,如果不为空则抛异常。

由于之前为了省事,其实并没有读入umlAssociation,所以增加了umlAssociation的读入。

读取的顺序如下:

//v1
UmlClass
UmlInterface
UmlStateMachine
UmlInteraction
UmlAssociationEnd
UmlCollaboration
//v2
UmlGeneralization
UmlEndpoint
UmlLifeline
UmlRegion
UmlAssociation
//v3
UmlAttribute
UmlMessage
UmlState
UmlFinalState
UmlPseudostate
//v4
UmlInterfaceRealization
UmlOperation
UmlParameter
UmlTransition
UmlEvent

由于没有构建新的类,这一阶段的类图同上。

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

第一单元

开幕暴击。一开始采用<指数,系数>的hashmap存表达式,后来要求提高了,开始remake,架构变为将表达式、项、因数、底数几个层次。

这一单元困扰我的方法是如何向上传输化简后的表达式,可以说最终的实现方式还是比较强行的,并不是递归地调用,而是直接根据已有的表达式关系,生成新的表达式图,然后把原来的表达式弃掉。所以说,第二次作业后的代码就变得非常不优雅了。

现在回想起来这一单元其实实现得很混乱。

第二单元

这一单元,我开始了解一些固定的面向对象模式,这一单元就采用了生产者-消费者模式,由于采用了既有的清晰的框架,所以整个架构基本没有变过,很快乐。

第三单元

第三单元的任务主要就是对JML规格的翻译,应该也玩不出什么花样了。

第四单元

将官方给的umlxxx变为加强版的“Myxxx”,建立和UML相同的管理网络,然后在"Myxxx"的类里面写功能,系一种“适配者模式”。

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

测试的理解

测试可以分为两个板块:正确性测试和性能测试。

正确性测试

测试一般有两个思路:

  1. 由于程序具有通用性,所以只需测试几个边界的、特殊的情况即可保证程序的正确性
  2. 通过随机指令测试程序正确性

性能测试

性能测试也有两个思路:

  1. 通过特别刁钻、耗时较长的数据,对程序进行测试,对比发现运行速度较慢的程序
  2. 通过大量的随机数据,对程序进行测试,对比发现运行速度较慢的程序

实践的演进

测试的演进

第一、第二单元期间,主要采用第一个测试思路,比较费神,且很难覆盖所有的测试数据,基本每次作业难免都有或大或小的bug。

在第三单元之后,则开始采用随机数据生成的思路进行测试,正确性也有了提高,但仍然出现过由于数据覆盖面的问题出现过重大漏洞(第三单元第三次作业)。

或许最佳的测试方式,是将两者进行结合进行测试。

对面向对象的演进

最初通过面向对象进行表达式的处理的时候,我感觉它比直接处理字符串要麻烦很多,光是重新构建出各个类的关系网络就已经相当麻烦了,更不要说后面还有各种功能的实现。

但是随着程序的迭代,我意识到面向对象是提高代码抽象以及可扩展性的一个很重要的思想,对代码的封装可以有效地让编码的思路更加清晰,保证编码的正确性,debug也更加有迹可循。

再后来接触JML,了解了什么是“防御式编程”,逐渐认识到,对于程序员来说,最重要的也许不是代码的简洁性,而是代码的正确性。宁愿在代码编写的过程中出现很多冗余的信息,但保证代码的正确、程序覆盖范围的全面、以及多个程序员之间交流的准确才是最重要的,面向对象在一定程度上,也是通过增加一些也许会提高代码复杂程度和运行时间的方式,来保证程序员的思路清晰,以及代码的可拓展性、可读性。

后来在了解到了,也开始在代码中采用各种经典的传输数据的模式(如生产者-消费者模式在电梯中的应用),逐渐成为一个能够熟练写出冗长代码的人了(bushi)。

总结自己的课程收获

面向对象这门课,很透彻地把面向对象的思想教授到我们的编程思想当中了,已经很难想象不明白面向对象思想的从前的我,编程是该有多么瘸腿。

这门课程也顺便教会了我们进程同步的知识。电梯是一个很经典且很有趣的模型,课程组的选题确实十分优秀。这一知识也很快反哺了操作系统的学习,让我在进程调度部分的学习和通关更为顺利。

面向对象的实验内容包罗万象,四个单元各自囊括了不同的内容,也在和同学们的交流当中发现了其实每个单元的内容仍可以深挖,每个知识点的背后都有好几本著作可以深入学习,面向对象这门课程是我们通向更多编程思想的引路人。

体会到了面向对象层层调用的高明之处,将任务从大到小分为几个层次的思想,不仅对任务实现的严谨性有帮助。写代码的过程中,有些有一定复杂度的程序,在编码时也可以拆解成大任务与细分任务,编码过程如果很懵逼,也可以先在容器类中写“伪代码”,然后再在各个类当中编写各自的实现方法。

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

1

第四单元中,还是有很多的UML类实际上并没有用到(如umlRegion),或者比较强的数据限制导致这一结构层次并没有什么用。

可以让需要实现的指令尽可能覆盖到出现过的所有umlelement。

2

第四单元用单元作业push大家去真正理解UML的组织结构,我在学习的过程中逐渐发现自己之前写的类图多少是有些理解错误的。

私以为可以把第四单元放在第一单元,这样以后每次写博客,其实都是对第四单元这个内容的一次复习,感觉可以增强大家对uml图的感受。

3

理论课相比于平时的代码作业,进度有些滞后。基本上,当一次上机已经完成互hack了,理论课才讲到相关的知识,导致理论课上课讲的东西,我必然已经自学了个七七八八,不然不可能上手写代码。结果就是,理论课讲的都是我自学到可以应用在代码上、且经过hack验证过的东西,完全没有收获。

解决方式就是,让理论课放在比每次相同内容的实验作业的ddl稍前一些。

posted @ 2022-06-27 15:06  wooood  阅读(17)  评论(0编辑  收藏  举报