【调查报告】关于面向对象(OO)课程目前存在的一些问题和个人思考

据了解,这门课程从2012年才刚开始开设,从最初的原始机制到现在已经有很很大的改善,这一点也是十分值得肯定的,老师和前辈们的努力功不可没

不仅如此,OO作为北航的一门特色课程,从价值来讲,当然是很有价值的:

  • 可以让学生去通过大量写代码以及踩坑来提高姿势水平
  • 可以让本科生真正意义上去接触OOP式的工程,领略工程思维

这门课程除此以外的好处与价值,还有很多,本文不再赘述。

然而,另一个不可否认的事实是,这门课程目前仍然存在不少的问题

接下来,笔者将谈一谈这些问题,笔者将

  • 结合笔者所了解的情况,描述问题的现象
  • 结合事实,分析问题的成因以及本质
  • 给出一些个人的思考
  • (可以的话)给出一些个人觉得更优的改进方式

不过,关于具体化体系化的建议,在本文中将不作过多讨论,笔者将另起文章详细概述。

好的,接下来进入正题。

矛盾与思考

在这一部分,笔者将就目前存在的比较明显的具体问题进行详细的阐述、分析,并提出一些自己的修改意见。

工程需求?公测?

在这学期OO2018的初期,这应该算是遇到的第一个问题了。

现状与分析

根据笔者的了解,课程组在2015届开始(即OO2017)开始引入了公测机制。并且在2016届(即OO2018,我们这届)开始使用错误树。

不得不说,这些都是很有进步意义的改进。

然而,这样也带来了不小的问题(尤其是在前几次作业,使用OJ统一公测的时候

  • OO的课程,希望锻炼的是工程技能和工程思维。而根据笔者实际的了解,在真正的工程应用场景,需求常常是模糊的甚至甲方只能说出大致需求,需要乙方自己体会的情况也很多;以及在创业圈子,CTO们常常也需要自己拿捏产品和工程的整体协同设计)。
  • 也正是基于如上的原因,所以指导书也被设计的较为模糊,很多细节并没有详细讲述。
  • 然而,现在又引入了传统的自动化测评,来实现自动化公测,而且采取的是传统OJ式的输入输出文件比对模式(只是过滤了#开头的行,连Special Judge甚至都算不上)。这就意味着,只要和标准输出结果不符,就是错的

于是一个不可调和的矛盾就此产生了:

  • 一方面,工程需求不可能那么清楚,细节需要自己拿捏。
  • 另一方面,公测的需求却又无比清楚,顺我者昌逆我者挂。

于是,本来应该自己把握的细节,大家只能都开始依赖于不停地问助教各种琐碎的细节,通过客服群和issue区。而原因,正是因为实际上答案还是只有一个,而且还不告诉你到底是啥。

于是,后果就是:

  • 该锻炼的产品思维没锻炼成
  • 该锻炼的自主思考能力没有锻炼成
  • 时间全都花在了抠一个个的细节上
  • 指导书无论如何改进,只要没有绝对细致到每一个细节,都一定会被吐槽
  • 同学们心力憔悴,助教们不胜其扰,效率极其低下

思考与建议

关于以上的状况,个人也是有一些自己的思考的。

首先,我们来看看现在的OJ制度内部的逻辑是什么

  • 设立一个标准输入。
  • 设立一个标准输出。
  • 输入标准输入,然后拿来和标准输出比对。
  • 完全一致就是正确,否则就是错误。非黑即白

也正是这一非黑即白的特性,成为了与工程&产品思维背道而驰的地方。

然而,公测其实是一种很高效,也很能客观对同学们程序质量进行横向比较的一种手段(比起互测,下文将详细讲述),为了这样的原因直接废除公测,无异于因噎废食。

所以,笔者觉得,能否从这个非黑即白的特性入手,将这个矛盾的焦点化解掉呢?

对此,笔者的解决思路如下—— 改进OJ上的测评策略,使之不再非对即错

  • 对于第一次作业(多项式计算,实际上傻瓜电梯也适用)这样对错很明确的程序,可以使用Special Judge,将评测正确放的更加宽泛,而不再是简单粗暴的比对模式。
  • 对于后面几次作业(两次单线程电梯,实际上多线程电梯和出租车一样适用),有比较多的实际上不影响产品全局的微观细节。可以通过Special Judge来先检查调度结果是否正确(即不可以出现非正常的调度,例如同一电梯同时执行不止一个请求、电梯瞬移等),在调度正确的基础上,可以拿到基础分(建议基础分放低,刺激大家尽量优化),之后再根据结果的优劣性(例如在较多调用的时候,调度的总时间)来进行一个阶梯化或者连续性的一个打分(建议极差可以放大,以提高对同学们来说精益求精的性价比)。
  • 对于后面几次作业这样微观细节的情况,只需要写清楚不允许出现XXX的情况即可,剩下的同学们自己拿捏,法不禁止即合理。此外,对于部分应该自主思考的问题,助教有权回复NO RESPONSE,即表示提问者应该自行思考自行拿捏。

加上这样较为平滑的过渡措施之后,之前的这个矛盾将会得到很大程度上的解决,同学们也将能真正形成自主思考意识与基本的工程产品思维。(实际工程上,在不违背基本原则的情况下,一般也只有优劣之分)

个人信息?无效作业?

这个问题呢,虽然也许很多同学一整个学期都不见得遇得上,但是一旦遇上,便是一道送命题。

现状与分析

根据笔者调查了解,以前的OO课程由于采用互测且机制尚不成熟,故存在大面积的同学之间互相readme求饶的现象。

为了强力扼制这种现象,于是现在就在程序和readme文档内严打个人信息(听说甚至连git commit的信息也在严打范围之内)。

笔者在这个学期也遇上了一次这种事,而且可以说,遇上这种人品糟糕且工程素养恶劣的测试者,是一件非常糟心和令人恼火的事情(前方高能,详情在此

不仅如此,自从第二第三次作业以来(即程序开始变得稍微复杂,工作量稍微大那么一点之后),就经常可以听到这样的言论:

  • 啊,真羡慕我的室友啊,他这次这人文档个人信息没去掉,直接无效了
  • 啊,真希望我也能抽到一份无效作业啊,程序写的累死了,还是无效作业处理着爽

这样类似的话,笔者平均下来每周能听到五次以上。

根据笔者的了解,课程组对待无效作业的政策是这样的:

  • 对待被无效者,本次作业取无基础分的最低分
  • 对待测试者,本次作业这部分分数取全年级最高分

所以,大致动机可以判定为——想通过不劳而获拿到全年级最高分

那么我们还是老规矩,分析一下这件事背后的逻辑是什么(假设测试者是一个以不劳而获为第一目的人):

对于这位测试者,面临的选择有以下几种:

  • 认真测评,但是挺累的
  • 不认真测评,挺水的,但是貌似有制度约束,有被扣分的风险
  • 举报对方无效,也挺水的,不过名正言顺,好处还大大的

换位思考一下,这种事情又没啥成本(或者说成本即便再高也远远低于认真评测一份程序),风险还几乎为零,利益诱惑巨大,很多这样的人怕是都会想去试上一把的。

综合来看,举报对方无效就成了低成本低风险高收益的最优解。。

建议与思考

我们从一般人的心态考虑,在这样的博弈中,一般人都不会单纯的希望对方受到伤害,伤害对方行为的背后根源都是利益驱动

不仅如此,基于如上思路,我们知道举报对方无效这种决策的三个特性:

  • 低成本
  • 低风险
  • 高收益

然而俗话说得好,掉脑袋的活有人干,没好处的活没人干。说到底,这三点里面最关键性的是高收益

所以,笔者的思路也很明确——只要让这样做的实际收益降低,就可以有效遏制以不负责任为目的无效作业申报

根据笔者的调查(包括从一些助教前辈那里了解到的情况),无效作业大致分为以下几种类型:

  • 作业不具备最基本的功能
  • 作业里面暴露了各类个人信息

其中,暴露个人信息的,实际上也分两种:

  • 一种是明摆着求饶,明摆着想搞交易的
  • 另一种只是一不小心暴露了一些个人信息

然而目前的措施是,只要一旦认定为无效,全都一视同仁,或者更准确的说,全都一棍子打死。显然这样的做法是欠妥的:

  • 对于不具备基本功能的作业,没有测试的价值,直接申报无效的确没有什么问题
  • 对于明摆着求饶搞交易的,这种一定程度上已经与作弊与抄袭无异,申报无效(甚至如果可以实锤的话直接不及格)也没有什么不对的
  • 然而,对于第三种这样的过失错误一样被同等对待,然后测试者就可以带着最高分溜之大吉,显然很不合理

首先,笔者在之前挂人的博客里面也已经提到

  • 作为一个认真学习但有过失的学生,有权知道自己劳动成果如何,更有权从中获取应有的养分
  • 作为一个还算有点基本工程素质和责任心的测试人员,应该尽到最起码的工程测试义务,对工程质量负责

所以,综上,笔者的建议是:

  • 以后将无效作业分类,每种类型对应不同的惩罚措施
  • 对待被测试者,出现前两种情况,可以老规矩处理;对待第三种情况,可以采取较为折中的惩罚措施(例如本次作业分数打折,一定数量的扣分等)
  • 对待测试者,申报对方无效作业之后,如果对方被成功认定为前两类无效,则可以不用测试。否则必须按规则完成测试(否则按规则进行惩罚,可以取消给年级最高分的奖励)。然而助教要是没有第一时间审批呢?没关系,如果助教最终审核结果没认定为前两种,而你没有完成测试的话,测试者一样被惩罚(哪怕助教认定的时间已经过了公测ddl)。这就保证了,除非申报者足够确信对方会被认定为前两类无效,否则不测试对方的程序都无异于铤而走险。同时,对待第三种情况,将不给测试者全年级最高分的奖励,而是给一个稍微折中的奖励(例如加几个crash的分数)

可能读者还是有疑问,如何区分第二种和第三种呢(这貌似也是以前助教团队没解决的一个问题)?

笔者的建议是,对于第二种的认定,一定需要较为明显的实锤(例如有个人信息且有求饶的话,例如个人信息摆在特别显眼的地方)。否则认定为第三种。

其实这样做也是合理的。一个想求饶的人,即便侥幸被认定为了第三种,在分数打折这样伤害不低的惩罚下,他们如果不想挂科的话,也不会再敢继续了。然而对于无意犯错的人,这样的惩罚也好于直接无效。

基于这样的制度限制

  • 被测试者依然不敢做出过格的行为
  • 测试者直接申报对方无效的收益大大受限,且风险急剧增大(主要是针对纯粹想不劳而获的这类人,对于真正的无效作业不受影响),故也会选择以更正常的方式处理无效的问题

PS:顺带吐槽一下,个人觉得,给不劳而获的举报者直接最高分实际为一种很不公平的政策。对整个年级所有认真写程序认真测试的同学,是一种很不公平的存在。这一点希望课程组认真考虑

互测?工程评价?

之前说到,互测是一种很好的双向锻炼的机制。然而,互测要是用在工程评价上,还合适吗?

现状与分析

众所周知,现在除了bug以外,还有一些东西在使用着互测机制,例如:

  • 12条原则
  • 文档评价
  • jsf规格评价

另一个众所周知的事实是,很多同学都似乎很反对互测机制。笔者暂不评论这样的主流思维,不过笔者观察发现,当上述的这些东西开始互测之后(尤其是jsf互测),大家对OO这门课程的意见变得异常大

笔者详细去了解了一下情况,身边很多的同学都有过被对方大面积扣jsf的情况,且动辄就是好几十分,自己辛辛苦苦找的bug根本不够塞牙缝的。于是呢,很多同学就是从规格作业(第9次作业)开始选择“佛系”——什么好好写程序,什么好好找bug,都是扯淡!还是jsf使劲挑对方刺来的靠谱。

分析

按照惯例,还是来分析下。我们来看看,以上的这些工程类评价有什么样的特点:

  • 并没有很严格很固定的标准。这个了解过一些工业界的人应该都清楚的,这些东西本质是在为程序为工作效率服务的,效果好的就是正确的,并无明确的对错之分。

在工业界很棒的一些东西,搬到了课程里,就出了问题:

  • 正是因为没有很严格很固定的标准,所以每个人各有各的道理,各有各的对错,很难有个统一的标准衡量正确与否,甚至优劣之分也难以统一衡量。

于是,从对工程对工业界不是很了解的同学们的视角来看,这意味着:

  • 从编程者角度来看,自己哪怕再认真写,只要对方想挑刺,自己都不是安全的
  • 从测试者角度来看,只要想挑刺,分数要多少有多少

基于这样的情况,很多同学便不再愿意精益求精(反正再好也会被挑刺),而是为了保证自己的安全,疯狂挑对方的刺。

也许还有一个申诉仲裁制度似乎在保证着公平性,但是,老实说这样子效率很低。以及,实际上,只要同学们看到成片的bug,无论最终到底申诉成功多少,其体验都可以说是非常糟糕的

于是,很多同学陷入了这样的囚徒博弈

  • 遵守道德,不乱扣对方——如果测试自己的人挑自己的刺的话,自己就完蛋了
  • 不遵守道德,乱扣对方——自己无论如何都是安全的。就算发现自己的测试者没有对自己下狠手,大不了到时候撤掉自己扣对方的就好了

于是,连锁反应发生了。这样想的人越多,就会有越多的人做出后者的选择。这样选择的人越多,这样想的人也必然越多。

建议与思考

其实,造成这种尴尬局面的根源,非常简单。

用一句话简单概括,就是——让不懂工程的人强行评价工程的好坏

工业界人士的话,就算规格、原则啥的再没有绝对的标准,他们心里也都是有一把尺子的——即什么能满足工业工程需要,什么不能。

然而对于初次接触OOP工程代码的同学们来说,他们并没有这样的分寸,更不知道到底什么东西合适什么东西不合适,界限在哪里。毕竟规格原则之类的东西和程序bug有本质的区别。

然而,再回想起来每次这种互测,测试的人又是谁?就是这些根本不了解工程的学生

让不懂工程的人强行评价工程的好坏,而且还纳入考核,还用来数据分析,这显然是荒谬的。毫无疑问只会导致因为利益冲突引发的乱象,即无法保证公平性,学生们也不会学会应该学会的技能,最终一无是处。

基于以上的事实与分析,笔者觉得,有以下几种破局的思路:

  • 让学生一开始就尽可能多的了解一些工业界的情况。比如从一开始就严格要求代码规范、javadoc、单元测试等。有了这些基本认识,大家的分寸感会更强。不过这样的思路也存在弱点——工程思维不是一个能在短时间内速成的素养,即便尽力培养,学生对工程的认知和专业人士依然会有不小的差距,分寸感还是非常有限的。
  • 将学生的这种工程评议权力收回。这是一个很关键的操作,这类评价还是应该交给专业人士进行,也好给学生们以一个更加正确的引导(现在jsf的互测这一点做的就很糟糕),也给大家一个更加公平的环境。
  • 还有一种思路,那就是建设完善的JSF规格评测体系。首先,JSF应该彻底解决自动化问题,其次,作为一个目前面向教学的工具,也需要一整套完善合理的评价体系(后文将详细讲述)。不过不得不说,就目前的JSF而言,想做到这样并非一件简单的事情。(关于JSF的相关讨论传送门

以上是一些零散的思路。这一块如果想要较为根本的解决问题的话,可能需要对课程进行大改动,这一块将在后文论述。

维护?扩展?

说到面向对象,自然是为了工程化服务的。说到工程,可维护性可扩展性自然是一个很重要的评价指标。然而,现在的课程这一点究竟做得如何呢。

现状与分析

我们,先来看看我们每一周都在干些什么:

  • 第一周:多项式计算
  • 第二周:傻瓜电梯
  • 第三周:ALS捎带电梯
  • 第四周:博客作业
  • 第五周:多线程电梯
  • 第六周:IFFFT
  • 第七周:出租车系统
  • 第八周:博客作业
  • 第九周:可更改路径状态出租车系统+规格
  • 第十周:带红绿灯可更改路径状态出租车系统+规格
  • 第十一周: 多种出租车系统+规格
  • 第十二周:博客作业(规格相关)
  • 第十三周:基于第三次作业的单元覆盖性测试
  • 第十四周:基于第三次作业的代码正确性论证

排除博客作业,我们来对代码作业进行一下分类:

  • 多项式计算
  • 电梯类作业
    • 傻瓜电梯
    • ALS捎带电梯
    • 多线程电梯
  • IFFFT
  • 出租车作业
    • 出租车系统
    • 可更改路径状态出租车系统+规格
    • 带红绿灯可更改路径状态出租车系统+规格
    • 多种出租车系统+规格

然而,实际上,真正算得上连续的作业只有这些:

  • 单线程电梯作业(2次)(实际上多线程电梯和单线程电梯的差距实在有点大,所以虽然都叫电梯,但是不属于同一类)
  • 出租车作业(4次)

我们再来根据以上分析结果看一下,我们整个学期每次作业的操作是什么样的:

  • 第一次作业:从头开始写
  • 第二次作业:从头开始写
  • 第三次作业:改需求或从头开始写
  • 第五次作业:从头开始写(也许还有那么点可重用部分,但是核心部分几乎不可重用)
  • 第六次作业:从头开始写
  • 第七次作业:从头开始写
  • 第九次作业:扩展
  • 第十次作业:改需求或从头开始写(之前有人不少人用的单线程)
  • 第十一次作业:改需求

我们可以统计下,对于工程能力较好的同学,一共是这样的操作

  • 从头开始写:5次
  • 改需求维护:3次
  • 扩展维护:1次

没错,整个学期九次代码作业,一多半都在从头开始写,改了三次需求,扩展了一次。大部分时间都花在了从头开始写上,或者换个角度来说,就是一多半的作业都是用完就扔的

而对于能力稍差(或者未得要领)的同学,这种情况更为严重(甚至不乏次次都写一次性代码的同学)。

很明显,目前的作业配置上,对于维护的体现程度可以说远远不够。(实际上这也是很多同学至今完全不重视代码可维护性的主要原因)

建议与思考

基于以上的分析,那么改进思路也是非常明显的——增大维护、扩展的实际需要量

例如,整个学期的程序作业,可以出了几次入门作业之外,只分成2-3个长的系列作业,而且做到每次工作量尽可能接近(即不出现第一次写累死后面维护没啥事干的情况,也不出现第一次写太简单后面每次维护都像扒层皮的情况)。

面向对象,作为一个和工程紧密相关的学科,不应该沦为单纯的代码堆砌,而应该以真正让学生理解其中的思想精髓为第一要务。

排位?BUG数?

众所周知,在我们课程中有个天梯系统,用于每次分配水平相近的同学进行互测。但是,目前这个排位真的客观科学么?

现状与分析

根据笔者的了解,现在,实际上主要影响排位的因素,还是互测

虽然现在似乎有了公测进行一些缓冲,但是根据笔者从助教那边了解到的情况,实际上绝大部分同学都是处于公测全对或者接近全对的状态(因为公测的数据全都是面向bug树的弱数据,且为了保证数据到节点的一一映射关系,数据不便加强),公测部分实际上拉不开差距,所以最终最关键的还是互测。

然而,我们来看看互测的逻辑是什么:

  • 扣对方的bug,有收益
  • 被对方扣bug,有损失
  • 双方的收益和损失实际上对等,即零和

基于这样的逻辑,我们来假象一种情况。

有四个同学,A、B、C、D,其中A、B水平接近,C、D水平接近,A、B水平明显强于C、D。

大佬们的特点是,抓bug能力强,而且自己程序的严密性也高。非大佬们的特点是,抓bug能力弱,而且自己程序也不够严密。(虽然简化了模型,但是依然是很符合现状的——一个人的写代码能力和找bug能力基本成正相关)

那么,我们来考虑一下局面:

  • A vs B,双方都是大佬,虽然双方都有较强的找bug能力,但是对方的程序又都滴水不漏。最终很可能双方都是0收获
  • C vs D,双方都不是大佬,虽然双方的程序bug都很多,但是双方找bug能力都不强。最终也很大可能是双方都0收获
  • A vs C,一个是大佬一个不是大佬,A能找到C很多的bug(A能力强+C程序弱),C找不到或只能找到A很少的bug(C能力弱+A程序强)。最终结果是A凯旋而归,C损失惨重

于是呢,我们可以发现一个很有趣的现象——每次互测,得分的实际情况并不取决于个人的能力,而是取决于个人能力和对方能力的差

这意味着,得分高,其实最主要原因是碰巧抽到了比自己弱的对手。对手比自己弱的越多,分数越棒。而这一切的决定者,则是我们系统平台的随机数生成器。(实际上,OO课程“面向运气编程”的恶名就是这么来的)

建议与思考

实际上,互测虽然的确存在这样的问题,但是互测依然有其重要的意义。

只是,拿这种一对一式的互测当做考核的核心指标(或本意不是如此,但因为其他制度的不健全导致情况实际变成了如此),是明显不合理的

为保证考核的最基本公平性,考核的核心指标,必须是面向个人实际实力的,而不应该引入其他无关的影响因素(即便不能绝对做到,也应保证绝大部分情况下做到)。

综上,笔者有几种大致的改进思路:

  • 增强并改进公测制度,且进一步削弱互测考核占比。实际上,现在应该在很大程度上参考公测的成绩,但是效果不理想,最主要的原因是拉不开差距。目前的公测是面向bug分支树的,且公测常常和树上节点呈单射映射关系(即一个测试点仅对应一个bug),这就意味着,公测数据只能出的很弱(因为一旦数据变强,那么就会不可避免的牵扯到不止一个的bug,评分将难以进行)。然而,很弱的单bug公测数据常常只能进行最最基本的功能性测试,根本无法真实反映程序的质量(实际上,在中等及以上水平段,基本上是清一色的公测全对)。而解决方案,则可以采用笔者在之前章节中所讲述的新测试方式,让程序的实际质量可以连续性地进行衡量。这样即便正确的程序也可以高下立判,而且也可以进行有效的强测试并进行有效的评分,不再全盘受到bug树的制约。在这样的基础上,公测变得更加靠谱,则可以进一步扩大公测考核的占比。
  • 互测转型升级。目前互测的基本规则是一对一测试,那么必然无法避免偶然性问题。然而,如果转型成了多对多的话(类似codeforces的hack制度),情况就会有很大的好转。因为所有参与互测的人,程序都将同等的被所有人测试(理论上),测试者水准是公平的;而对于测试者,可以尝试测试所有的程序,也是很公平的。简而言之,代码编写者的水平,直接决定其能找到别人bug的数量(正相关),也直接决定其被别人找到bug的数量(负相关),这样一来公平性问题就得到了很大程度上的解决。

其他一些问题

本节为上一节的一些补充,笔者将指出其他的一些问题。

系统设计依然不完善

这一点其实很显然,可以列出很多点。

目录树机制的新增节点限制

这个是目前被吐槽的很厉害的一个问题,曾经以为是bug,后来发现是个feature。

对于这个,笔者其实不是很懂这样的限制初衷是什么。

  • 防止恶意攻击?然而对于真正不怀好意的人,一样可以在原有节点上挂满bug(且都不是正常的申报bug),甚至成本还更低。真正的攻击者根本不会绕这个远路,还增大被发现的风险。这种防御毫无意义。
  • 减少系统压力?一般情况下,只要是正常人在操作(即不考虑脚本),这样的一点数据交互密度其实非常低,根本构不成大流量。而如果发生脚本攻击,可攻击的点又远远不止这么一个,这样的措施依然毫无意义。
  • 还有一种可能,那就是用这种方式引导同学们尽量把发现的bug归类到错误树上,从而实现收据数据并二次利用等效果。然而,实际情况下,bug的分布可以非常复杂,远不是一个小小的错误树可以有效概括的(笔者实测,一般情况下挂2-3个节点就不让再挂了)。即便从数据采集与分析角度来看,这样的措施虽然的确可以使数据项更为集中到预设的聚类中,但是也有很大可能导致更多的噪点进入到预设的聚类中。这样收集数据效果不一定更好。

所以,笔者的意见是:

  • 可以放宽这样硬性的限制,保证真正有需要的情况下也能正常反馈错误树以外的bug
  • 然而,对于一些外挂节点较多的同学,可以采用人工复查(复查后出现较多大面积归类错误可以扣分,但是效率偏低),或者外挂节点达到一定数量时得分阶梯打折(个人推荐这种方式)等措施来进行限制。

评测等相关功能有待进一步扩展与完善

正如上文所说,评测等功能应当进行进一步的扩展和完善。

鉴于已经进行了较为详细的说明,此处不再赘述。

同学们没有受到正确的引导

OO这门课程已经接近尾声,那么同学们学习的效果如何呢?

下面放几张图,取材于笔者在互测中抽到的各个程序,工业界人士们可以感受一下:

  • 这张还算稍微好点的,不过C味还是浓的很

  • 静态数组满街跑

  • 长度感人肺腑的逻辑表达式

  • 通篇使用int数字来表示节点,通篇把80这样的常数直接裸露,理由是——我觉得这样方便

  • 惊天地泣鬼神的单个方法长度(注意看左侧行号,在notepad++中折叠了run方法,而且折叠部分里面基本没有注释;据说甚至还有人的代码一个run方法直接1500行的)

  • 除了以上的,还有非常多,多到可以专门写一个长文进行探讨。。。

不得不说,很多同学(甚至包括一些水平不弱的同学),直到快要结课的时候,不仅面向对象思想丝毫没有理解,而且可以说连JAVA语言都没有入门

  • 刺鼻的C语言味(一整个学期丝毫没有改变),不堪入目的语法格式。
  • 巨大的数据耦合和功能逻辑密度。
  • 甚至笔者和他们说了一些概念并推荐其使用时(例如接口抽象,逻辑封装,甚至HashMapArrayList等数据结构),他们一脸愕然地问笔者那是啥玩意,C语言有吗。。。
  • 更不用提工程、产品思维的形成了。当笔者向他们说了要工程化和工程化的好处时,他们就那几句话——我觉得这样写方便、我觉得这样写别人看不懂(就找不了我的bug)、我觉得代码越短bug越少。。。

除此之外,还有很多,多得说不完。

笔者认为,如果一门名为面向对象的课程,学了一学期,大部分同学就这个水准的话,真的是白学了。(实际上,笔者能抽到的这些同学,水平都还是不弱的,最差也有中上游,那么中游甚至中下游水准的同学又会是什么样的呢?)

那么原因何在呢?我们来研究下课程目前的安排,看看我们各方一直都在做些什么:

  • 老师:
    • 讲理论课课
    • 课程纲领性指导
    • 安排实验课
  • 助教:
    • 各种答疑
    • 编写数据和测试
    • 维护申诉区和平与稳定
    • 系统维护
  • 学生:
    • 写作业1
    • 写作业2
    • 写作业3
    • ......
    • 写作业16
    • 实验课1
    • 实验课2
    • ......
    • 实验课8

没错,我们的同学一直在做的事情,只有写写写。而老师主要做的事情呢?也只有讲讲讲,而且局限于理论。

整个课程中,同学们一遍一遍用着以前就会的C语言风格来一遍遍做着重复劳动(在大部分同学们的视角中就是这样,这也是很多人觉得身心俱疲的重要原因)。

老师们讲理论课也讲的神乎其神不亦乐乎,唯独,没结合实例讲过程序到底应该怎么写

实际上,我们也安排有博客作业,其目的在于让同学们反思一下这三次的得与失。然而很多同学们依然不知道如何将理论与实践相结合(实际上,理论课的很多概念可以说相当的抽象),于是博客里面真正能反思提高的非常非常有限。然后以后继续用老一套写,继续巩固完全错误的知识技能。正所谓,“学而不思则罔,思而不学则殆”,直到结课,除了加深了错误的印象之外,一无所获。

虽然,对于IT从业者来说,自学能力相当重要。但是在这样的初学阶段,正确的引导对于同学们而言也是必不可少的

综上,笔者认为,我们需要开设作业题目讲解,对于每次作业进行稍微具体化一些的讲解。可以请大佬们、老师们或者校外请到的攻城狮嘉宾给大家讲解正确的写法用法。好让大家真正学到正确的知识技能,也能有所收获。此外,也可以考虑将代码风格纳入考核的一项指标,以保证大家充分的重视

仲裁处理供不应求

如字面意思,根据笔者的了解,在大概第十次作业的时候(大约五月中旬),仍有同学在客服群里问助教,第五次作业的申诉仲裁什么时候解决。

而笔者自己这边也有类似的情况,截至2018年6月8日23时59分59秒,即第十三次作业那周的周六晚,笔者这边第六次作业的仲裁(被申诉)依然没有处理(已经过去了一个月有余)。

UPDATE 2018-06-15 : 最新消息,在2018-06-15 00:13:33,助教们终于处理掉了笔者第六次作业的仲裁。

笔者也从助教那边了解了一些情况。实际上助教也很忙,而且仲裁区里面有很多的疑难杂症,为保证公平合理性,处理起来实际上相当费时费力

目前这样的状况,将会造成以下的影响(不针对助教,不针对同学,只是单纯的分析):

  • 同学们不再相信助教团能带给他们公平正义。不管助教团那边是什么样的情况,在同学们的视角来看,事情就是这样的——我在XXX时候有一个bug没和对方达成共识,于是我点了仲裁,然而助教并不鸟我们。如此一来,如果更多同学对我们的公正维护体制丧失信心的话,对课程整体风气和制度维护将是灾难性的
  • 任务越积越多,“债多不愁”。相信不仅助教,很多人都应该有过类似这样的心态。当任务庞大到自身无法承受的一个地步时,干脆就想着弃疗了。虽然助教们不一定会弃疗,但是,任务如此的滚雪球,难免造成这样的消极心理,甚至可能造成恶性循环。

所以,个人的一些建议&思路是:

  • 首先,不知道仲裁里面有多少是真的有效的内容(即真的存在争议,而非各种胡闹的)。如果有很多无效内容的话,建议在这方面入手,对于很明显的此类仲裁者进行扣分处理,以减少此类情况注:根据笔者了解,每次左右都有人给对方乱申报bug,而且都是很明显没认真考证不讲道理的,就是为了撞撞大运,遇上个软柿子就赚了,遇上不退让的大不了撤回,反正没有任何成本。对于这样的不正之风笔者认为必须严打)。
  • 其次,助教团内部最好可以更加完善这样的仲裁制度。成员限制明确的任务ddl,提高效率,尽量做到今日事今日毕,最起码保证在申诉期结束之前或者结束不久之后能还同学们公平正义。给同学们一个盼头,让大家相信公平正义的存在
  • 不过,实际上,无论怎么改进,助教的工作能力终究是十分有限的。所以,实际上最终极的解决思路是,想办法改进其他制度以减少仲裁的情况与数量,让绝大部分问题在上游就得到解决(或者干脆从一开始就不发生)。

同学存在消极比赛心理

如标题,笔者在16级微信群等地方不止一次的看到类似这样的言论。

看上去,加分似乎挺能刺激大家努力竞争。可事实上却不尽然。

大家眼中,扣bug的分数,和最终成绩是严格线性相关的。即,不求有功但求无过,零和心态是也

然而实际上,根据笔者对于课程制度的细节了解,却不尽然。以及bug积分到底能不能真实客观的评价代码质量,也是一件很值得怀疑的事情。

综上,笔者认为:

  • 需要让同学们更加详细具体的了解课程制度(最好包括制度细节)
  • 需要保证信息充分透明公开(例如积分,例如排位)
  • 需要引入更加合理的制度(例如不同排位上的同学基础分是不同的,保证高分段有充分的好处,而不是仅仅增加被扣分的危险性,维持一个稳定平衡体系)
  • 需要更加客观合理的代码评审制度(在前文有讲述)

相关学习过程过于突兀

说到这个,笔者不得不提一下最后的几次作业:

  • 单元测试——给所有的类配上单元测试
  • 正确性证明——给所有的类所有的方法进行正确性证明

除此之外,实际上第一次让同学们全面加上jsf(没记错的话是第九次作业),也差不多是这样的感觉。

什么样的感觉呢?其实很简单。

从学生的视角来看,事情就是这样的:

  • 老师课上讲了一个新东西,我们第一次听说的新东西
  • 哇,这次居然要在全部代码里面加上这个东西
  • 哇,我的代码居然这么多
  • 哇,这玩意考核扣分居然还这么狠

这意味着什么呢?我们继续从学生的视角来看,大概是以下几种可能:

  • 哇,我的代码居然这么多,我以前还没写过这个新东西,毫无把握啊
  • 哇,我的代码居然这么多,一旦理解错了一个东西,岂不是被扣分扣得飞起来

说的更直接点,学生们在写这些东西的时候的真实体验,就是在摸着石头过河,赌这一锤子买卖。(不仅大家如此,连笔者这样熟悉一般工程套路的同学在一次性写如此规模的证明的时候都感到非常迷茫和吃力)

虽然,ppt上也许都有相关内容,老师们也都觉得自己讲了。但是,学生们的理解总归是很可能存在偏差或者信息丢失的,而且还没有一个相对缓和的纠正机会

在这样的情况下,学生一口吃了个胖子,就算老师后续愿意亲自纠正批改,但是错误的东西很可能已经先行巩固了几十遍甚至上百遍

综上,笔者认为,对于这样新东西的引入,应该有一些相对的缓冲过程:

  • 可以在之前的理论课上布置一些理论作业
  • 作业不需要多,但是老师一定得认真批改纠正
  • 理论作业可以循序渐进,一点一点扩大(比如证明正确性,先从证明一个方法开始,再到一个类,最终再到一个工程)

这样一来,同学们有了循序渐进学习的一个过程,学习效果与体验都会相应的好上很多。

其他

推荐大家使用idea作为ide

如标题所述,希望能在以后推荐大家使用idea作为ide,理由如下:

  • 很快看到自己程序里面的不足,例如右边滚动条成片的黄色warning(每次互测看到这种辣眼睛的程序都感觉好绝望),有利于让大家养成良好的编程习惯
  • 提供各种便捷的工具,可以让大家获得更好的编程体验

更多关于idea的好处,我的这篇文章里头有讲述:【备忘】Idea的那些事

之前向学长了解过之前推广上的障碍,似乎是因为版权相关的问题。

不过实际上,对于本科生并不存在这样的问题,因为idea对本科生有学生免费优惠,只需要用buaa.edu.cn邮箱即可注册登记并合法地使用。(详情:For Students: Free Professional Developer Tools by JetBrains,注册流程网上教程有很多)

以及,这里还有java的educational版本,自带教程的ide(详情:Java Edu

课程体系改革

关于课程体系的具体改革建议,笔者将在这篇文章中进行详细概述(【策划】关于新OO课程改革的一些设想与计划尚未完成,敬请期待

一点点总结

关于制度制定上的一些思维方式

其实,以上很多的问题,看似不相关,实则背后是形式类似的制度思维方式偏差

笔者将在文章【思考】基于目前OO课程的一些制度问题引发的思考尚未完成,敬请期待就这一点,进行一些个人观点的阐述。

其他一些笔者想说的话

笔者在这个学期之前,便听说过北航OO课程。同时,笔者早在大学入学前,就已经熟练运用一般的面向对象设计思想,大致了解一些OO。

最初是在知乎上看,感觉众说纷纭,有助教们的辛勤付出,也有各路高人的一些批判,当然了也不乏有些居心叵测的人恶意诋毁(甚至包括一些既得利益者)。之后也听一些学长抱怨过种种不顺(甚至某某导员曾在年级大会上建议大家都来和谐都来划水)。

总之,在上这门课程之前,我感觉到,这门课程在以前的风评似乎不是那么的好

在这门课程开始后,笔者真正接触了这样的一门课程,也观察了一整个学期,也向以前的学长(包括一些助教)和老师们了解过曾经的情况以及这门课程的发展史。于是再结合个人对于工程对于课程教育对于制度的理解,写下了这篇文章。多有一些个人意见,不见得绝对客观,也有可能有我遗漏的信息。欢迎读者指正,更欢迎善意的批评与交流

以及,不得不说,直面无数人的风言风语和诋毁,并把这一门曾经风评不那么好的课程着手改善,是需要勇气的。笔者,已经做好了这些觉悟。如果能有幸成为OO的助教的话,希望可以一改原本的弊病,给大家一个全新的印象,让同学们觉得,原来OO也是这么有趣有用的东西

最后,还是老话拿出来再说一遍:

  • 对于支持我们工作的人,我们报以感激之心
  • 对于为了改善课程不懈努力的人,我们表达崇高的敬意
  • 对于提出建设性批评意见的人,我们将认真听取并表示感谢
  • 对于风言风语甚至恶意诋毁我们和前辈们努力与成果的人(无论你是已经实习的大佬,还是某些ACM大佬),将被视为我们的敌人,我们将按规则办事,勿谓言之不预也(感兴趣的话欢迎去问问去年STAR助教团发生了什么事_
posted @   HansBug  阅读(621)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示