OO第四单元&课程总结博客
本单元作业最大敌人:
CheckStyle
。
Checkstyle found no problems in the file(s)
(1) 总结本单元作业的架构设计
第一次作业
-
第一次作业要求实现UML类图的解析。
-
最大的麻烦在于,UML类图中诸多元素的输入顺序是没有限制的。比如,一个类
class1
的属性attr1
有可能在类输入之前就输入了,这种时候没法将attr1
及时“关联”并保存到class1
之中。(此处的“关联”不是UML中的专业术语,下同) -
对于此,有两种处理思路:
-
先保存所有元素,再针对每类元素分别与其上层元素进行关联。
-
采用多次扫描,自上而下分别保存并关联处于不同“层次”的元素,确保每类元素保存并关联时,其上层元素已经被保存并可被直接调出。注意,这里说的“层次”并非一般理解中由包含、所有关系确定的层次,而是根据元素的
parent
、source
、target
等属性的引用关系而确定的层次。举个例子:-
比如
Association
的属性end1
、end2
,分别指向了两个AssociationEnd
。要想建立起对应的两个类(接口)之间关联关系,需要先保存两个AssociationEnd
,才能在保存Association
时根据end1
、end2
直接调出两个类(接口),随后再建立起关联关系。 -
在某种意义上,可以称
AssociationEnd
为Association
的前序元素。
-
-
-
我的实现采用了第2种方法,总共三次扫描,每层扫描中处理的元素类型如下:
第一层 | 第二层 | 第三层 |
---|---|---|
Class, Interface, AssociationEnd | Attribute, Operation, Generalization, InterfaceRealization, Association | Parameter |
-
本次作业的UML类图:
第二次作业
-
第二次作业要求实现UML时序图和UML状态图的解析。
-
整体的思路与第一次相同,但在分析了UML状态图的元素层次之后,发现原先的三次扫描不够用了。。。不过:
计算机上,没有什么问题是增加一个中间层解决不了。除非问题是层数过多。
- 于是,在保证架构
从外面看起来没变的情况下,从三次扫描升级为3
次扫描。具体每层的扫描内容如下表所示:
第1层 | 第2-1层 | 第2-2层 | 第2-3层 | 第3层 |
---|---|---|---|---|
Class, Interface, AssociationEnd, Interaction, StateMachine | Attribute, Operation, Generalization, InterfaceRealization, Association, Lifeline, Region | State, Pseudostate, FinalState | Transition | Parameter, Message, Event |
-
此处表格展示的和实际实现的略有不同。实际实现中有
CheckStyle
梦魇伴随左右,为了保证每个方法(每次扫描)在60行以内,只能在不违反逻辑关系的前提下,将第2-1层中的部分元素放到第2-2、2-3层的扫描中。 -
本次作业的UML类图:
第三次作业
-
第三次作业涉及模型的有效性检查。
-
核心内容是图的
dfs
算法,架构设计与第二次作业相同,此处不再赘述了。 -
本次作业的UML类图:
-
最后,经历了与
CheckStyle
之间漫长的相互折磨后……-
500行以内?绰绰有余嘛。
(2) 总结自己在四个单元中架构设计及OO方法理解的演进
-
回顾理论课,面向对象的设计思想是重中之重。
-
在这四个单元的作业中,架构设计是落实面向对象思维的直接体现。
-
具体的架构设计在以往的博客作业中已经详细阐述了,这里不再搬运。我认为最核心的是,在四个单元设计与实现的过程之中,我深入理解了、应用了面向对象这种思维模式,并掌握了多种设计模式。
-
关于四个单元的联系与区别,我认为自己的理解不够深刻。我想转载部分周远航学姐的博客内容:
- 我认为第一单元对于面向对象思想的体现是最明显的,我的设计重点主要在如何实现某个对象。将表达式从上到下进行解析,提取出表达式类、因子类、各种项类。通过成员变量等方法建立其中的包含关系和函数调用关系,每个类只需要完成自己的任务。综合来看,第一单元是我心中最OO的一个单元,也是阐释OO思想的很典型的一个样例。
- 第二单元延续OO的设计思想,但增加了重要的功能性,也就是这一单元的特点——多线程,这使得我的设计重点由如何实现某个对象,变为对象之间的如何交互。线程安全等问题非常结合实际又难度,并且调度算法的开放性也激发了我对于不同调度策略的尝试和比较。通过本单元的学习,我明白了对于OO而言,设计好一个对象的行为是远远不够的,如何让他们系统地、高效地、安全地交互才是将架构真正付诸实践的关键。
- 第三单元涉及JML,让我体会到了在实际工程实现中根据规格要求实现具体方法的过程,我的设计重点放在了如何高效实现方法要求上。针对特定的JML规格,方法的具体实现方法有许多种,但总有效果更好的一种。我认为在阅读JML时,最重要的是要深层次理解其设计目标的内涵(如最短路、连通分量数量等),而不应该仅停留在JML字面意思,否则将难以将需求抽象出来,可能造成方法复杂度过高等后果。
- 第四单元学习了UML的相关知识,UML模型模型化设计将对象、对象之间的关系全部抽象出来,组建成模型。我认为设计的重点在于层次化抽象成模型。对于层次化,需要将UML图中的各种元素进行层次划分,形成从抽象到具体的逻辑关系。对于抽象,需要深入理解UML图的本质,并采用某种数据结构将元素进行统筹整理。
(3) 总结自己在四个单元中测试理解与实践的演进
-
第一、二单元,主要采用了黑盒测试。能力一般,水平有限,笔者不会搭建自动测评机,于是只能根据对于所要实现的需求的理解,预判存在
WA
或TLE
隐患的边界情形,并有针对性地手动构造数据并加以测试。 -
第三、四单元,主要采用了单元测试与对拍大法。同样使用的是手动构造的数据,和同学进行对拍。
-
此外,我还做了充分的样例测试,以及基于历史强测数据点的二次测试。
(4) 总结自己的课程收获
面向对象悖论:面向对象让人无暇面向对象。
我认为这门课最重要的是面向对象的思想,远比编程本身有价值。
醒醒!说的好像没有面向对象就能面向对象似的。
(5) 立足于自己的体会给课程提三个具体改进建议
关于寒假pre
-
这门课需要熟练运用JAVA语言,在没有先修课程的情况下,课程组希望同学们在寒假自学,并完成pre的两个单元作业。
-
但是今年寒假期间,同学们普遍在学院的督促下推进冯如杯项目,学院也组织了两次冯如杯线上答辩。原本用于休息、个性化发展的时间已经被大量占据的情况下,OO的JAVA和git自学任务和pre作业又给同学们增加了新的负担与压力。我认为,作为春季学期的课程,挤占同学们的寒假时间并不妥当。
关于作业设置
-
据了解,第一单元绝大多数同学都花了大量时间用于学习、理解和实现递归下降分析算法。事实上,这个算法是在大三上学期的编译原理中正式讲到的,不应在OO这门大二下学期的课程中作为一个持续四周的单元中作业的核心而出现。
-
由于绝大多数同学没有JAVA基础,直接上手编写复杂的程序本来就很困难了。此时,在应对JAVA语法规则、
CheckStyle
限制、正则表达式相关知识之外,还要学习复杂的、与面向对象无直接关联的新算法,这样的安排可能不太妥当。第一单元作业需求的设置不够合理。 -
对新手来说,第一单元感到格外煎熬的另一大原因是坡度过大,即难度没有循序渐进地上升,不是由浅入深,而是直接“冲顶”。这在一定程度上违反了认知规律。
-
我认为,可以用pre部分的两个单元(图书馆管理系统、小型邮件信息系统)的共计11道编程题,作为开学后前四周的第一单元作业内容,给同学们一个充分地学习并熟练JAVA语言的过程,并结合
CheckStyle
培养良好的书写习惯。一方面,不给假期施加额外的压力;另一方面,也可以确保课程难度循序渐进。 -
如感觉有必要,可将原有第一单元表达式求导的第一次作业作为新第一单元的作业之一。因为此次作业不涉及到嵌套、不需要语法检查,被处理的字符串呈一维线性而非二维树状,故可以用
.replaceAll()
、.split()
等具有JAVA特色的方法硬莽,避免使用到递归下降分析算法。
关于查重宣传
-
开学以来,课程组在不同场合多次强调代码查重的强度,从课上老师的反复强调到大班水群里不同助教的发言强调。
-
课程组本意是非常好的:希望同学们不要抄袭,独立完成代码作业,这不只是为了确保评分的公平,也是为了让同学们能切实提升编程能力。
-
要求需要明确不假,只是过分的强调容易适得其反。与预期不一致的结果(之一)是:对代码查重强度的过分强调,影响了同学之间正常的关于架构设计的讨论。正常的交流讨论对同学们打开思路、拓宽想法、提升思维有着极其重要的作用。然而实际情况是,有的同学不要说看代码,连思路也不敢讨论,甚至有意说一个与自己的实现不一样的(被舍弃的)思路,颇有“风声鹤唳”、“草木皆兵”之态。这样的现象不利于同学们的学习与实践。
-
我认为,如果想让同学们不会一刀切地对待交流讨论,那么可能有必要划定更为明确的行为边界。在强调了“复制粘贴”的红线后,还要明确说明交流思路、架构(包括类的划分方式、部分属性的设置等)不会影响到代码查重结果,不会影响到对抄袭的认定。诸如“只要编写代码过程是独立完成的,不是边看别人代码边写的,就基本不可能查重中招”等说法的明确,可以有效地促进同学们放开手脚地交流讨论、相互学习,“必能裨补阙漏,有所广益也”。
其他
关于指导书
-
不妨在指导书中给出几个可用或推荐的实现方法的举例,或者提示一些简单的思路帮助同学们更好上手。比如:
- 第一单元:递归下降分析算法;
- 第二单元:SSTF算法、LOOK算法、集中式调度、分布式调度;
- 第三单元:并查集、变量维护;
- 第四单元:缓存机制。
这一点我之前与老师交流过,老师说不希望大家的关注点被带跑到具体的算法上。我非常能理解老师的意思,但是以第三、四单元为例,指导书中给出的时间要求对同学们来说不够直观、难以把握,不好估计自己实现的复杂度是否满足要求。这种时候同学们为避免重构,往往会去往年博客里找哪些实现方法能满足要求。与其这样,不如课程组更直观地给出一些推荐算法,或者指出对实现方法的复杂度的限制,让同学们在比较中更好地对自己设计的实现方法进行预先的评估。
-
希望第四单元的指导书中能将边界情形描述得更加清晰,避免同学们去讨论区提问其中模糊之处,比如“不同接口的名字是否会出现重名”、“循环继承/重复继承的图中哪些结点需要被输出”等。
关于课程网站
- 建议OO课程网站上的讨论区,看完的帖子可以显示为灰色。
最后
- (未完待续)