课程总结博客
OO课圆满结束,完结撒花!
第四单元三次作业的架构设计
这两次作业我都采用了装饰者模式。原本的类功能比较单一,基本只支持对自己这个一个UmlElement的属性的查询,但是对各种对象之间的关系没有规定。于是我为每一个需要对其属性/方法/关系进行查询的UmlElement都创造了相应的MyUmlElement类,并让它们包含此前的UmlElement。最终在查询时只需要在相应的Interaction类中调用MyUmlElement类中的方法即可。而在MyUmlElement的设计时,我又在继承的层次上进行了设计。
这样做的好处是,每次增加新的需求时都比较方便,第二次作业在第一次作业的基础上增加了有关状态图和顺序图的类即可。具有较好的扩展性。
第一次作业
本次作业类图:
度量分析:
Type Name | Method Name | Implementation Smell | Cause of the Smell |
---|---|---|---|
MyUmlClass | getOperationNum | Complex Method | Cyclomatic complexity of the method is 11 |
MyUmlInteraction | MyUmlInteraction | Complex Method | Cyclomatic complexity of the method is 11 |
MyUmlInteraction | buildUmlMap | Complex Method | Cyclomatic complexity of the method is 16 |
出现了圈复杂度过大的问题。主要原因是在构建类图时需要对不同的ElementType进行判断,导致switch/if-else语句过多。这个问题不太容易解决,因为建立类图必然要考虑到不同的UmlElement
Type Name | NOF | NOPF | NOM | NOPM | LOC | WMC | NC | DIT | LCOM | FANIN | FANOUT |
---|---|---|---|---|---|---|---|---|---|---|---|
MainClass | 0 | 0 | 1 | 1 | 6 | 1 | 0 | 0 | -1 | 0 | 1 |
MyBroadClass | 7 | 0 | 18 | 18 | 54 | 19 | 0 | 0 | 0.777778 | 0 | 0 |
MyUmlAssociation | 5 | 0 | 7 | 7 | 31 | 7 | 0 | 0 | 0.428571 | 0 | 0 |
MyUmlClass | 3 | 0 | 12 | 12 | 138 | 37 | 0 | 0 | 0.333333 | 0 | 0 |
MyUmlElement | 7 | 0 | 10 | 10 | 43 | 10 | 0 | 0 | 0.3 | 0 | 0 |
MyUmlInteraction | 10 | 0 | 13 | 13 | 206 | 48 | 0 | 0 | 0.692308 | 1 | 0 |
MyUmlInterface | 2 | 0 | 9 | 9 | 70 | 19 | 0 | 0 | 0.888889 | 0 | 0 |
MyUmlOperation | 5 | 0 | 5 | 5 | 31 | 6 | 0 | 0 | 0.4 | 0 | 0 |
Type Name | Method Name | LOC | CC | PC |
---|---|---|---|---|
MainClass | main | 4 | 1 | 1 |
MyBroadClass | MyBroadClass | 3 | 1 | 1 |
MyBroadClass | addOperation | 3 | 1 | 1 |
MyBroadClass | addAttribute | 6 | 2 | 1 |
MyBroadClass | addAssociation | 3 | 1 | 2 |
MyBroadClass | getAssociationNum | 0 | 1 | 0 |
MyBroadClass | addInterface | 3 | 1 | 1 |
MyBroadClass | getAttributeNum | 0 | 1 | 1 |
MyBroadClass | getAssociatedClass | 0 | 1 | 0 |
MyBroadClass | getAttributeByName | 0 | 1 | 1 |
MyBroadClass | getInterface | 0 | 1 | 0 |
MyBroadClass | getNotHiddenInformation | 0 | 1 | 0 |
MyBroadClass | setVisibility | 3 | 1 | 1 |
MyBroadClass | getInterfaces | 3 | 1 | 0 |
MyBroadClass | getOperations | 3 | 1 | 0 |
MyBroadClass | getAssociations | 3 | 1 | 0 |
MyBroadClass | getNotHiddenAttribute | 3 | 1 | 0 |
MyBroadClass | getAttributes | 3 | 1 | 0 |
MyBroadClass | getAssociatedClassGetter | 3 | 1 | 0 |
MyUmlAssociation | MyUmlAssociation | 4 | 1 | 1 |
MyUmlAssociation | setEnd1 | 4 | 1 | 2 |
MyUmlAssociation | setEnd2 | 4 | 1 | 2 |
MyUmlAssociation | getEnd1Class | 3 | 1 | 0 |
MyUmlAssociation | getEnd2Class | 3 | 1 | 0 |
MyUmlAssociation | getEnd1 | 3 | 1 | 0 |
MyUmlAssociation | getEnd2 | 3 | 1 | 0 |
MyUmlClass | MyUmlClass | 5 | 1 | 1 |
MyUmlClass | getOperationNum | 29 | 11 | 1 |
MyUmlClass | findTopFather | 9 | 2 | 0 |
MyUmlClass | setDirectFatherClass | 3 | 1 | 1 |
MyUmlClass | getAttributeNum | 13 | 3 | 1 |
MyUmlClass | addAssociation | 6 | 2 | 2 |
MyUmlClass | getAssociationNum | 8 | 2 | 0 |
MyUmlClass | getAssociatedClass | 10 | 2 | 0 |
MyUmlClass | getOperationVisibility | 14 | 3 | 1 |
MyUmlClass | getAttributeByName | 13 | 4 | 1 |
MyUmlClass | getInterface | 15 | 4 | 0 |
MyUmlClass | getNotHiddenInformation | 8 | 2 | 0 |
MyUmlElement | MyUmlElement | 7 | 1 | 1 |
MyUmlElement | getId | 3 | 1 | 0 |
MyUmlElement | getName | 3 | 1 | 0 |
MyUmlElement | getParentId | 3 | 1 | 0 |
MyUmlElement | getParent | 3 | 1 | 0 |
MyUmlElement | getUmlElement | 3 | 1 | 0 |
MyUmlElement | getSons | 3 | 1 | 0 |
MyUmlElement | setParent | 3 | 1 | 1 |
MyUmlElement | addSon | 3 | 1 | 1 |
MyUmlElement | getType | 3 | 1 | 0 |
MyUmlInteraction | MyUmlInteraction | 60 | 11 | 1 |
MyUmlInteraction | buildUmlMap | 52 | 16 | 0 |
MyUmlInteraction | getClassCount | 3 | 1 | 0 |
MyUmlInteraction | findClass | 19 | 5 | 1 |
MyUmlInteraction | getClassOperationCount | 8 | 2 | 2 |
MyUmlInteraction | getClassAttributeCount | 4 | 1 | 2 |
MyUmlInteraction | getClassAssociationCount | 4 | 1 | 1 |
MyUmlInteraction | getClassAssociatedClassList | 9 | 2 | 1 |
MyUmlInteraction | getClassOperationVisibility | 4 | 1 | 2 |
MyUmlInteraction | getClassAttributeVisibility | 11 | 3 | 2 |
MyUmlInteraction | getTopParentClass | 4 | 1 | 1 |
MyUmlInteraction | getImplementInterfaceList | 12 | 3 | 1 |
MyUmlInteraction | getInformationNotHidden | 4 | 1 | 1 |
MyUmlInterface | MyUmlInterface | 5 | 1 | 1 |
MyUmlInterface | getAssociationNum | 7 | 2 | 0 |
MyUmlInterface | isSearched | 3 | 1 | 0 |
MyUmlInterface | setSearched | 3 | 1 | 1 |
MyUmlInterface | getAttributeNum | 10 | 3 | 1 |
MyUmlInterface | getAssociatedClass | 7 | 2 | 0 |
MyUmlInterface | getAttributeByName | 12 | 4 | 1 |
MyUmlInterface | getInterface | 12 | 3 | 0 |
MyUmlInterface | getNotHiddenInformation | 7 | 2 | 0 |
MyUmlOperation | MyUmlOperation | 5 | 1 | 1 |
MyUmlOperation | addParameter | 10 | 2 | 1 |
MyUmlOperation | getRetNum | 3 | 1 | 0 |
MyUmlOperation | getInParasNum | 3 | 1 | 0 |
MyUmlOperation | getVisibility | 3 | 1 | 0 |
第二次作业
第二次作业基本沿用了上次作业的架构。
(由于建立的类比较多看起来比较臃肿,但实际上逻辑关系还是比较清晰的)
Type Name | Method Name | Implementation Smell | Cause of the Smell |
---|---|---|---|
MyUmlClass | getOperationNum | Complex Method | Cyclomatic complexity of the method is 11 |
MyUmlClassInteraction | MyUmlClassInteraction | Complex Method | Cyclomatic complexity of the method is 11 |
MyUmlClassInteraction | buildUmlClassDiagram | Complex Method | Cyclomatic complexity of the method is 16 |
MyUmlGeneralInteraction | MyUmlGeneralInteraction | Complex Method | Cyclomatic complexity of the method is 16 |
MyUmlGeneralInteraction | buildStateDiagram | Complex Method | Cyclomatic complexity of the method is 13 |
MyUmlGeneralInteraction | buildSequenceDiagram | Complex Method | Cyclomatic complexity of the method is 8 |
与上一次作业相似,依然出现了建图时圈复杂度过大的问题。
Type Name | NOF | NOPF | NOM | NOPM | LOC | WMC | NC | DIT | LCOM | FANIN | FANOUT |
---|---|---|---|---|---|---|---|---|---|---|---|
MainClass | 0 | 0 | 1 | 1 | 6 | 1 | 0 | 0 | -1 | 0 | 1 |
MyBroadClass | 7 | 0 | 18 | 18 | 54 | 19 | 0 | 0 | 0.777778 | 0 | 0 |
MyUmlAssociation | 5 | 0 | 7 | 7 | 31 | 7 | 0 | 0 | 0.428571 | 0 | 0 |
MyUmlClass | 3 | 0 | 12 | 12 | 138 | 37 | 0 | 0 | 0.333333 | 0 | 0 |
MyUmlClassInteraction | 10 | 0 | 13 | 13 | 206 | 48 | 0 | 0 | 0.692308 | 0 | 0 |
MyUmlElement | 7 | 0 | 10 | 10 | 43 | 10 | 0 | 0 | 0.3 | 0 | 0 |
MyUmlGeneralInteraction | 12 | 0 | 11 | 11 | 230 | 56 | 0 | 0 | 0.545455 | 1 | 0 |
MyUmlInteraction | 5 | 0 | 7 | 7 | 33 | 8 | 0 | 0 | 0.571429 | 0 | 0 |
MyUmlInterface | 2 | 0 | 9 | 9 | 70 | 19 | 0 | 0 | 0.888889 | 0 | 0 |
MyUmlLifeline | 3 | 0 | 4 | 4 | 18 | 4 | 0 | 0 | 0.75 | 0 | 0 |
MyUmlOperation | 5 | 0 | 5 | 5 | 31 | 6 | 0 | 0 | 0.4 | 0 | 0 |
MyUmlRegion | 5 | 0 | 7 | 7 | 33 | 8 | 0 | 0 | 0.571429 | 0 | 0 |
MyUmlState | 8 | 0 | 8 | 8 | 65 | 16 | 0 | 0 | 0.25 | 0 | 0 |
MyUmlStateMachine | 2 | 0 | 3 | 3 | 14 | 3 | 0 | 0 | 0.666667 | 0 | 0 |
MyUmlTransition | 5 | 0 | 9 | 9 | 35 | 9 | 0 | 0 | 0.555556 | 0 | 0 |
Type Name | Method Name | LOC | CC | PC |
---|---|---|---|---|
MainClass | main | 4 | 1 | 1 |
MyBroadClass | MyBroadClass | 3 | 1 | 1 |
MyBroadClass | addOperation | 3 | 1 | 1 |
MyBroadClass | addAttribute | 6 | 2 | 1 |
MyBroadClass | addAssociation | 3 | 1 | 2 |
MyBroadClass | getAssociationNum | 0 | 1 | 0 |
MyBroadClass | addInterface | 3 | 1 | 1 |
MyBroadClass | getAttributeNum | 0 | 1 | 1 |
MyBroadClass | getAssociatedClass | 0 | 1 | 0 |
MyBroadClass | getAttributeByName | 0 | 1 | 1 |
MyBroadClass | getInterface | 0 | 1 | 0 |
MyBroadClass | getNotHiddenInformation | 0 | 1 | 0 |
MyBroadClass | setVisibility | 3 | 1 | 1 |
MyBroadClass | getInterfaces | 3 | 1 | 0 |
MyBroadClass | getOperations | 3 | 1 | 0 |
MyBroadClass | getAssociations | 3 | 1 | 0 |
MyBroadClass | getNotHiddenAttribute | 3 | 1 | 0 |
MyBroadClass | getAttributes | 3 | 1 | 0 |
MyBroadClass | getAssociatedClassGetter | 3 | 1 | 0 |
MyUmlAssociation | MyUmlAssociation | 4 | 1 | 1 |
MyUmlAssociation | setEnd1 | 4 | 1 | 2 |
MyUmlAssociation | setEnd2 | 4 | 1 | 2 |
MyUmlAssociation | getEnd1Class | 3 | 1 | 0 |
MyUmlAssociation | getEnd2Class | 3 | 1 | 0 |
MyUmlAssociation | getEnd1 | 3 | 1 | 0 |
MyUmlAssociation | getEnd2 | 3 | 1 | 0 |
MyUmlClass | MyUmlClass | 5 | 1 | 1 |
MyUmlClass | getOperationNum | 29 | 11 | 1 |
MyUmlClass | findTopFather | 9 | 2 | 0 |
MyUmlClass | setDirectFatherClass | 3 | 1 | 1 |
MyUmlClass | getAttributeNum | 13 | 3 | 1 |
MyUmlClass | addAssociation | 6 | 2 | 2 |
MyUmlClass | getAssociationNum | 8 | 2 | 0 |
MyUmlClass | getAssociatedClass | 10 | 2 | 0 |
MyUmlClass | getOperationVisibility | 14 | 3 | 1 |
MyUmlClass | getAttributeByName | 13 | 4 | 1 |
MyUmlClass | getInterface | 15 | 4 | 0 |
MyUmlClass | getNotHiddenInformation | 8 | 2 | 0 |
MyUmlClassInteraction | MyUmlClassInteraction | 60 | 11 | 1 |
MyUmlClassInteraction | buildUmlClassDiagram | 52 | 16 | 0 |
MyUmlClassInteraction | getClassCount | 3 | 1 | 0 |
MyUmlClassInteraction | findClass | 19 | 5 | 1 |
MyUmlClassInteraction | getClassOperationCount | 8 | 2 | 2 |
MyUmlClassInteraction | getClassAttributeCount | 4 | 1 | 2 |
MyUmlClassInteraction | getClassAssociationCount | 4 | 1 | 1 |
MyUmlClassInteraction | getClassAssociatedClassList | 9 | 2 | 1 |
MyUmlClassInteraction | getClassOperationVisibility | 4 | 1 | 2 |
MyUmlClassInteraction | getClassAttributeVisibility | 11 | 3 | 2 |
MyUmlClassInteraction | getTopParentClass | 4 | 1 | 1 |
MyUmlClassInteraction | getImplementInterfaceList | 12 | 3 | 1 |
MyUmlClassInteraction | getInformationNotHidden | 4 | 1 | 1 |
MyUmlElement | MyUmlElement | 7 | 1 | 1 |
MyUmlElement | getId | 3 | 1 | 0 |
MyUmlElement | getName | 3 | 1 | 0 |
MyUmlElement | getParentId | 3 | 1 | 0 |
MyUmlElement | getParent | 3 | 1 | 0 |
MyUmlElement | getUmlElement | 3 | 1 | 0 |
MyUmlElement | getSons | 3 | 1 | 0 |
MyUmlElement | setParent | 3 | 1 | 1 |
MyUmlElement | addSon | 3 | 1 | 1 |
MyUmlElement | getType | 3 | 1 | 0 |
MyUmlGeneralInteraction | MyUmlGeneralInteraction | 75 | 16 | 1 |
MyUmlGeneralInteraction | buildStateDiagram | 43 | 13 | 0 |
MyUmlGeneralInteraction | buildSequenceDiagram | 23 | 8 | 0 |
MyUmlGeneralInteraction | findInteraction | 10 | 3 | 1 |
MyUmlGeneralInteraction | getParticipantCount | 4 | 1 | 1 |
MyUmlGeneralInteraction | getMessageCount | 4 | 1 | 1 |
MyUmlGeneralInteraction | getIncomingMessageCount | 11 | 3 | 2 |
MyUmlGeneralInteraction | findMachine | 10 | 3 | 1 |
MyUmlGeneralInteraction | getStateCount | 4 | 1 | 1 |
MyUmlGeneralInteraction | getTransitionCount | 4 | 1 | 1 |
MyUmlGeneralInteraction | getSubsequentStateCount | 28 | 6 | 2 |
MyUmlInteraction | MyUmlInteraction | 4 | 1 | 1 |
MyUmlInteraction | addLifeline | 7 | 2 | 1 |
MyUmlInteraction | addMessage | 3 | 1 | 1 |
MyUmlInteraction | addEndpoint | 3 | 1 | 1 |
MyUmlInteraction | getLifelines | 3 | 1 | 0 |
MyUmlInteraction | getMessages | 3 | 1 | 0 |
MyUmlInteraction | getLifelineByName | 3 | 1 | 1 |
MyUmlInterface | MyUmlInterface | 5 | 1 | 1 |
MyUmlInterface | getAssociationNum | 7 | 2 | 0 |
MyUmlInterface | isSearched | 3 | 1 | 0 |
MyUmlInterface | setSearched | 3 | 1 | 1 |
MyUmlInterface | getAttributeNum | 10 | 3 | 1 |
MyUmlInterface | getAssociatedClass | 7 | 2 | 0 |
MyUmlInterface | getAttributeByName | 12 | 4 | 1 |
MyUmlInterface | getInterface | 12 | 3 | 0 |
MyUmlInterface | getNotHiddenInformation | 7 | 2 | 0 |
MyUmlLifeline | MyUmlLifeline | 4 | 1 | 1 |
MyUmlLifeline | addIncoming | 3 | 1 | 1 |
MyUmlLifeline | addOut | 3 | 1 | 1 |
MyUmlLifeline | getIncomingMessages | 3 | 1 | 0 |
MyUmlOperation | MyUmlOperation | 5 | 1 | 1 |
MyUmlOperation | addParameter | 10 | 2 | 1 |
MyUmlOperation | getRetNum | 3 | 1 | 0 |
MyUmlOperation | getInParasNum | 3 | 1 | 0 |
MyUmlOperation | getVisibility | 3 | 1 | 0 |
MyUmlRegion | MyUmlRegion | 4 | 1 | 1 |
MyUmlRegion | setMachine | 3 | 1 | 1 |
MyUmlRegion | addState | 7 | 2 | 1 |
MyUmlRegion | addTransition | 3 | 1 | 1 |
MyUmlRegion | getStates | 3 | 1 | 0 |
MyUmlRegion | getTransitions | 3 | 1 | 0 |
MyUmlRegion | getStateByName | 3 | 1 | 1 |
MyUmlState | MyUmlState | 12 | 3 | 1 |
MyUmlState | addNextState | 6 | 2 | 2 |
MyUmlState | addPreviousState | 6 | 2 | 2 |
MyUmlState | getSubSequentStats | 19 | 5 | 0 |
MyUmlState | setSearched | 3 | 1 | 1 |
MyUmlState | isSearched | 3 | 1 | 0 |
MyUmlState | clearAllSeq | 3 | 1 | 0 |
MyUmlState | getNextStates | 3 | 1 | 0 |
MyUmlStateMachine | MyUmlStateMachine | 4 | 1 | 1 |
MyUmlStateMachine | addRegion | 3 | 1 | 1 |
MyUmlStateMachine | getRegion | 3 | 1 | 0 |
MyUmlTransition | MyUmlTransition | 4 | 1 | 1 |
MyUmlTransition | getSource | 3 | 1 | 0 |
MyUmlTransition | getTarget | 3 | 1 | 0 |
MyUmlTransition | setEvent | 3 | 1 | 1 |
MyUmlTransition | setOpaqueBehavior | 3 | 1 | 1 |
MyUmlTransition | setFrom | 3 | 1 | 1 |
MyUmlTransition | setTo | 3 | 1 | 1 |
MyUmlTransition | getFrom | 3 | 1 | 0 |
MyUmlTransition | getTo | 3 | 1 | 0 |
第三次作业
四个单元中架构设计及OO方法理解的演进
四个单元下来,我的架构设计是螺旋上升的感觉。第一个单元的设计较差,在第二次作业后不得不选择了重构,但即便是重构后,第三次作业的结果也仍然不理想。第二个单元的设计相比之下就改善了很多,三次作业下来没有重构,基本都是在上一次作业的基础上进行扩展。当然,这一单元我考虑得更多的可能是功能上的实现,缺少一些性能上的考虑,这是第二单元不足的地方。第三单元的架构设计有所退步,基本只是沿用了给出来的接口的设计。第四单元我有认真考虑架构的设计,最终选择了装饰者模式来赋予每个UML对象新的功能,这个单元我特别能感觉到“对增加功能开放”的感觉,每次作业基本都不需要改变过去的代码,这对于准确性也有好处。
在我看来,对于一个OO新手来说,想要让自己架构进步的一个好方法就是学习各种设计模式。毕竟这些是前人在实践中总结出来的方法,站在巨人的肩膀上,我们自己的设计质量也会提高。比如第二单元我们常用的生产者-消费者模式,第四单元我使用的装饰者模式,都是学习了设计模式后的结果。
至于OO方法,我最大的体会就是,各人自扫门前雪,莫管他人瓦上霜。一个类要有自己明确的功能,有了别的功能就让另一个类来干,这样对于SOLID原则也能比较好的满足。其实我们现实世界又何尝不是如此,每个人都分工明确,才能让社会以比较高的效率运作下去。
四个单元中测试理解与实践的演进
这四个单元我基本采取了自动数据生成评测+手动构造数据评测的方法。
前两个单元,在讨论区文章的启发下,我都用python写出了自己的评测机和数据生成器,在大部分情况下,他们在我自测和互测时都大有帮助。
第三单元采用了评测机与单元测试相结合的方式。虽然前两个单元一直也有同学/老师在强调单元测试的概念,但是可能是程序本身需求所限,也有自己写的程序模块间独立性不强的原因,并没有尝试过单元测试。第三单元,由于各个查询指令的要求都很明确,因此我开始尝试了单元测试。
四个单元下来,对于测试最大的感触就是,一个优秀的程序必然要经过大量的测试,程序也是在测试中发现问题解决问题实现进步的(甚至有点对立统一的感觉)。程序员需要对自己的程序经过大量测试后才能心安,到了第四单元,因为自己不太能想到构建数据的方式,也因为临近烤漆,所以没有在自动评测的部分太下功夫,只是自己构造了几个uml图测试,每次交上去都觉得心慌。这大概也是我OO一学期下来的最大的改变,曾经写完了就觉得自己写的没问题,现在写完了一个程序,如果没有跑一晚上自动测试+手动极端数据测试,就总觉得程序有自己没发现的问题。
另一个体会就是,程序测试的难度与程序规模的关系事实上是以类似指数爆炸的形式上升的,即便几个模块都没问题,也无法保证组合在一起的程序没问题。这似乎也是全部工程领域都面临的问题,规模的扩大必然带来复杂度的急剧上升。由此,我们在测试时的思路应当是单元测试与全局测试相结合,单元测试用于测试各个模块自己的问题,全局测试用于测试整个程序的问题,这样有层次感的测试,或许可以帮助我们更容易找bug/确认程序的稳定性。
最后,在我看来,测试最难的部分就是数据生成了。怎么生成数据?什么样的数据才能有最大的覆盖度?随机生成的数据在测试时有多可靠?这些问题是每次我进行测试时思考最多的,而后两个问题现在我也不太有一个明确的答案,未来我会在这方面继续思考。
课程收获
这门课最大的收获大概就是走进了OO的领域,开启了多线程编程的大门,学到了建模方法,在测试的部分也相较以前大有改善,这些在前两个部分已经说的比较明确了。而对我最大的意义,还是让我对面向对象编程有了开始的了解。入门这件事或许是最难的,尤其是面对着OO世界浩如烟海的学习资料,从哪里开始总会让人感到迷茫。但是当你真正走进了大门,后面想学什么似乎都有了基础。师傅领进门,修行靠个人,但是没了师傅,可能门都进不了。
另一方面,OO也让我对比较大的程序有了掌控的感觉。过去写个200-300行的代码就感觉很难控制它的准确性了,而在面向对象方法和测试的帮助下,写一个上千行甚至更大规模的稳定的程序现在对我来说也是一个可以完成的目标了。
三个具体建议
- 希望以后的实验课可以有后续的视频讲解。前几次实验课难度较低,这一需求不太明显,但是在第三、第四单元的实验课时,由于难度增大,在做实验时难免会有不清楚、不确定的地方。而现在的实验课是做了就结束了,不知道自己的得分,也不知道正确的做法应该是什么样的。希望以后可以有老师或助教录制实验课的讲解视频,在每次实验课后放出来,可以加深同学们对于实验内容的理解。
- 建议以后类似第二单元第一次作业,给出检测互测数据是否合法的工具。尽管互测数据是否合法是一个需要同学们自己控制的事,但是在第二、三单元的互测时,很多同学交互测数据时都发现自己的数据非法,却难以发现到底是哪里出了问题。在第二单元的第一次作业时,课程组下发了互测数据检测软件,帮助大家规范了互测数据。希望以后的课程也可以有类似的软件,告诉同学们到底是上交的互测数据哪里不符合约束。当然,类似第一单元需要同学们自己判断WRONG FORMAT的作业,可以考虑不给检测工具。
- 希望可以有助教分享测试数据生成的技巧。这学期虽然课上、分享课都有老师和同学介绍测试/搭建评测机的方法,但对于如何生成测试数据却很少有介绍。到了第三单元,许多同学基本都可以用python或其他语言写出一个自己的评测程序,用Junit测试也并不是一件难事。但从我个人的体验来说,对拍和检测正确性,生成测试结果日志的部分其实并不难,最难的往往是数据生成的部分。三个单元我基本都是在随机生成数据,但这样有时并不能测出程序存在的bug。因此希望负责评测数据的助教可以分享给大家一些生成测试数据的方法,这样也便于同学们课下自己测试。
线上学习OO的体会
其实感觉OO这门课是最适应线上教学的,因为无论是上课/实验/作业/分享,都可以线上进行,完成作业与实验的核心部分也一向是放在线上,所以在课程的完整程度上我认为线上与线下差距并不大。但是我感觉线上上课和线下上课还是存在差距,一方面,老师的录播课相较于线下,确实少了一些老师“灵光突现”的时刻,听起来没有线下生动。另一方面,老师和同学们的互动似乎也减少了一些,尽管每节课都有思考题,但是线上授课的情况下,文字交流的效率实在太低了,可能线下五分钟聊完的问题,线上发文字甚至能拖到一小时,似乎这也是每节OO的讨论都能持续到课后约一小时的原因。当没人愿意主动加入讨论时,如果是线下,老师可以叫某个同学起来,可是在线上,即使@了某位同学,那位同学有时候也迟迟不现身,讨论经常陷入沉默。而就我个人而言,有的时候也比较难理解题目的意思,就不太敢加入讨论。
最后,我感觉OO已经是一门几乎完美的课程了。甚至可以说,我在这学期最喜欢的课就是OO。每周二晚上放出作业前和每周六互测开始前甚至都会让我感到兴奋。大一的时候看到知乎上对于这门课的吐槽,大二听学长说这门课的挂科率不低,都让我在学期之初对这门课有一些畏惧。然而一个学期过去,我感觉OO的难度曲线比较平缓,自己也逐渐走入了面向对象程序设计的大门。无论是看到强测高分,还是在互测中发现roommate的bug,都让我充满了成就感。老师的课上讲解和同学们的分享也让我这学期收获良多。感谢老师和助教一学期的辛苦付出!!!