面向对象第四单元总结博客
面向对象第四单元总结博客
本单元的架构设计
第十三次作业
本单元需要完成的大概就是给出 UML
图形架构,经过官方给的处理代码的处理,转化为 UMLElement
,并对它进行一系列分析。本单元理论教学的主要目的是让我们学习 UML
图的使用,但是这个作业和这个教学目的到底有啥关系。基本上在官方包给出了所有 UML
图中的元素后,剩下的就是一些稍微复杂一点大模拟了,说实话写完这次作业后我还是不会看 UML
类图。与这次作业相关的那次实验倒是真的让我学会了了看 UML
图,所以干脆直接把这单元考核方式换成理论考试效果不是更好?
先放本次作业代码的 UML
类图:
言归正传,在本次作业中,需要解析的主要目标 UML
类图,UML
类图中涵盖了类(UMLClass
),接口(UMLInterface
),方法(UMLOperation
),属性(UMLAtrribute
),参数(UMLParameter
)这些都是显性的成员类型,剩下还有如(UMLGeneration
,UMLAssociation
,UMLGeneralization
,UMLinterfaceRealization
)这些描述一种关系的隐性的关系,这些类都继承了 UMLElement
类。既然谈到类图,那肯定需要表示一下“类”,我新建了一个MyClass
来表示类,还需要一个 “接口”,所以我又建了一个 MyInterface
来表示接口,每个类和接口中,都可能有方法,所以我自己建了一个MyOperation
用于表示方法。方法中有参数,所以将 UMLAtrribute
作为 MyOperation
的属性。类中有属性,方法,继承的父类,实现的接口,具有的关联以及一个 UMLClass
存储它本来的属性。MyInterface
与 MyClass
相比只是少了关联和属性,其余不变。我实现的每个类中,用于存储信息的容器基本上都是HashMap
,左边存 id
,右边存具体的对象。各个属性中都需要添加可以扩充相关属性的方法。比如 MyClass
中有 addOperation
这个方法。
剩下的就是初始化问题了,这个我参考了标程的做法,在 MyUmlInteraction
类中分别实现了 initialxxx
的方法,然后按照先成员 element
,再属性 element
的顺序依次初始化。具体参考下图:
剩下的就是那几个询问了,除了一些比较基本的就成员本身性质的询问以及很基本的递归就能实现的递归以外,还是存一些难度比较大的询问的比如查询 “类的操作的参数类型”,但是说着难,其实就是实现起来特别繁琐。首先套路性的找类 \(+\) 判断是否合法,之后遍历类将同名方法找出来放到一个容器中,之后暴力遍历判断是否属性都合法,之后暴力二重循环枚举每个类,遍历这两个类,用两个 HashMap
分别存这两个方法的参数列表,之后判断两个 HashMap
是否相等来判断是否存在重复的情况,结束,完结撒花,是不是很暴力。但这单元代码部分整体基调就是暴力,对我这种码力不行的人真难受~
第十四次作业
本次作业的 UML
类图:
这次作业就多加了一个对于 UML
顺序图和状态图的分析,一共多了 9 个UMLElement
元素,其中,属于状态图的有:UMLStateMachine
,UMLRegion
,UMLState
,UMLTransition
,UMLEvent
,属于顺序图的有 UMLInteraction
,UMLLifeline
,UMLEndpoint
,UMLMessage
,状态图的从属关系是 UMLEvent
\(\to\) UMLTransition
\(=\) UMLState
\(\to\) UMLRegion
\(\to\) UMLStateMachine
,其中保证了 UMLStateMachine
中只会有一个 UMLRegion
,那还要它干嘛
顺序图的从属关系是 UMLMessage
\(=\) UMLEndpoint
\(=\) UMLLifeline
\(\to\) UMLInteraction
。这里需要注意的就是 UMLEndpoint
和 UMLLifeline
是同级的,UMLMessage
的两端又可能是 UMLLifeline
有可能是 UMLEndpoint
。理清这些东西后,剩下的就是和上一次作业差不多的东西了。
对于状态图分别建出 MyStateMachine
,MyRegion
, MyState
其中,MyState
中存储与之可以相互转化的 MyState
,MyRegion
中存放所有的 MyState
以及转移 UMLTranstion
,以及每个转移对应的 Event
组,这些都可以使用 HashMap
来存储。
对于顺序图,建出 MyInteraction
,MyLifeline
和 MyEndpoint
,后两者中分别记录所有可以与之传递 UMLMessage
的 ELement
以及对应的 Message
。MyInteraction
中将归属于这个 UmlInteraction
的 MyLifeline
和 MyEndpoint
用 HashMap
存储。
初始化时,由于我考虑到可能会出现超过 500 行而过不了 CheckStyle
,所以我直接另写了两个类分别用于初始化类图以及顺序图加状态图。初始化方法类同于类图。
这几个询问,在理清成员后就没什么难的了,考察了对于图的 dfs
,数据结构课都教的很多了,8说了。
第15次作业
本次作业的 UML
类图:
这次作业加了对于异常的判断。这次作业的指导书写的真的是十分清(hu)楚(nong)呢。这次作业加的几个异常显然不能写在 MyUmlGerenalInteraction
中,必超出 500 行,所以我采取了继承的方法,在一个 CheckUml
类中初始化整个 Uml
图,并判断 8 个 Error
是否被触发。
关于8个 Error
的实现,大概最大难度就在看懂谜语人指导书吧。其中有判断是否存在环路继承,我采取了拓扑排序的方法,\(O(n)\) 快速找出在环里的点。对于重复继承的判断,我直接采用了 dfs
的方法,扫到重复的就算多重继承。对于 R007
,比较难以理解,对于每个 Lifeline
需要找到它的 represent
对应的 attribute
并判断这个 attribute
的parentId
是否和 lifeline
所在 Interaction
的 parentId
相同即可。
总结四个单元的架构设计和OO方法理解的演进
一开始:面向对象是个啥?俺没有找对象
after Unit2:在一学期的学习之后,我理解的面向对象更像是一种设计思想,从一开始设计面向过程语言而注重将问题“流程化”,到现在将问题“部分化”,“层次化”。做个不恰当的比喻,我感觉面向对象和面向过程两种方法和组合数学中的 “加法原理” 和 “乘法原理” 有些类似。“加法原理”中的是将问题分成许多相互独立的面,而面向对象变成中所强调的 “对象化” ,正是将需要解决的问题交给许多独立的对象分别完成。因为我们做出了分工,所以才能“封装”。每个对象相互独立,我们才能利用彼此之间的联系,简化我们对象设计。“多态”实际上就是利用了对象间的相关性再做一次封装,增强了代码的层次性和灵活性,相当于为零件装了相互契合的“接口”,无论怎么改,都能相在结构上相互契合。面向对象的“零件化”设计决定了它在工程应用中的高效率,因为它方便修改。比如第一单元中所有表达式中的元素(sin(x),cos(x),x的幂)可以随意的增加和删除,因为它们都继承自同一个类,对于新增加的多项式元素,只要完成相应的求导方法即可。第二单元中,电梯,调度器,策略规划类相互配合,各司其职,每个对象做好自己的事,就能最终完成一个复杂的任务(电梯调度)。所以,第一二单元让我全面的认识了面向对象的编程方法,收获满满。
现在:这个第三第四单元,emmm……,我觉得理论相比实践更加重要,这两个单元的作业我觉得对于学习这两种只是帮助不是很大,还不如实验来的直接,这点比较失败。Jml
和 Uml
一个是从形式逻辑的角度分析代码,一个是从图形逻辑的角度分析代码,课程教授这两个知识旨在让我们明白代码的规范化。说实话我体会比较浅,比起深入理解这两种知识,我感受到的更多的是实验和理论的脱节。第三单元作业过于水,而且 Jml
语言到底是什么年代的描述逻辑,这么复杂真的有实际应用性吗?第四单元不让我们自己画图,每次把现成的图给我们展示好,然后作业纯属复习图论,这怎么可能对 Uml
有理解深刻呢?
总结自己在四个单元测试与实践的演进
感觉关于测试,从头到尾我都是使用编写的评测机进行与评测,对于像第三单元这种比较难以判断正确的,基本上也是使用自动相互对拍的形式进行测试。当然在自动测试之外,还有自己手造一些“边界”数据。所谓“边界”数据,无非就是针对空间,时间,特殊极端情况创建数据。
所谓对于代码的测试,本质上就是要判断正确性。判断正确性的方法无非两种:和标准答案做对照或者和足够多的人进行对拍。但是如何获取标准答案呢?可以利用一些现有的已经被验证完全正确的代码库:比第一单元的利用 python
中的计算库计算求导。也可以输出的答案出发模拟一遍过程看看是否逻辑能够自洽,比如第二单元的电梯。
但是无论怎样,我觉得在“形式化验证”的方法真正能够完美的判断代码的正确性前(虽然我认为不可能实现),最可靠的方式还是“黑盒”测试,加上“白盒”测试。提高测试数据的质量,增加测试数据的规模才是提升测试准确度的不二法则。
总结自己在四个单元的收获
第一单元中我最初接触了面向对象编程,初步建立起了对于面向对象编程的理解。但是此时我理解的不够深刻,所以第一单元中其实很大程度上我还是用面向过程式的思想实现的,层次和封装意识很薄弱。
第二单元中我接触到了多线程编程,理解了多线程的实现过程,算是将 OS
课中教的用代码的方式实现了一遍。多线程编程大大提高了程序的效率,同时扩充了程序可解决问题的范围,属实十分的强大。但是单元对我来说最大的收获还是我真正理解了面向对象编程,明白了各个对象各司其职能够产生的巨大作用。
第三,四单元中我了解到了两种描述程序代码的语言。Jml
强调了“按照规范和要求编程”,是一种契约式的思想。Uml
中强调了结构图的规范,用一种规范化的图形语言展现出代码的整体架构。
对于课程的改进建议
- 建议去掉非合并修复,统一bug修复的方式。现在的“非合并修复”的方式,实际上并没有人会去选,因为无论怎么样合并修复带来的受一定要大于“非合并修复”,那为什么要设立这个呢?不如统一 bug 修复能够挽回的扣分比例,比如,扣分减少 50% 之类。
- 还是建议将第三单元和第四单元的内容互换,第四单元的时间与烤漆完美契合,但是第四单元的代码实现相较于第三单元明显繁琐很多,放在烤漆很影响学生的复习其它科目的时间。
- 建议统一强侧测试点的个数,这样每次强测成绩都能有个统一的参考,统计成绩不是更加容易吗?建议都设置成 20 个,有些作业明显太少了(比如第一次作业才10个),这样会显得数据很水。
- 说个不太可能的建议,建议将第四单元换个形式考核,第四单元那个作业,不是我说,活该到了毕业设计的时候一堆学生还是不会画
Uml
类图,每次作业都把UML
图解释的部分留给了官方的解释代码,缺少我们自己阅读的部分,然后询问基本都是写数据结构的知识,真能学会真有鬼了。正好第四单元和烤漆重了,正好可以把最后两次实验改成理论考试的形式。Uml
图写这代码有啥用,当然要看和做题,甚至画一个才有用啊。 - 第三单元
Jml
换掉,课程组有无考虑过Jml
语言这种繁琐的语言是否真的有实际运用价值?如果想要向我们传达“契约式” 编程的思想,完全可以采用一种表达简洁的形式化验证语言。每次看第三元的作业我都心疼助教,工作量比我们还大……当然,Jml
确实是和我们大一学的离散数学中的逻辑相类似的语言,采用这种语言可能更容易我们理解。但是在OO课的学习中我还是希望看到更多和实际工程相关的东西。 - 第二单元每个测试点多测几次花不了多少钱吧?每次第二单元互测,房间一测一个死锁,但是交十几次都到不掉你们知道是什么感觉嘛,弄得我后面都不想参与互测了。
- 指导书前几个单元和后几个单元的严谨程度差的也太多了吧,第四单元完全就是看讨论区获取信息啊,助教工作的时候啊还是要善始善终啊
学习体会
从这篇博客结束,我的面向对象课就算正式结课了。真相感叹一句“6系得专业课每次都能整出点新花样”。总体来说,尽管上面骂了这么多,OO课得体验真心不错,而且我有预感,这可能是本科中为数不多真的能对以后工作有帮助的课了吧。来日方长,希望在OO课中学到得东西能使我终生受益吧。