各位同志们大家好,我又回来磨叽了,前阵子忙于肝代码而鸽了一阵,实在不大好意思。由于接下来会参与北航本科敏捷软工的课程改革,并且在技术开发这一层面而言,重点将会是结对作业部分。上过2019年及以后的OO课程的老哥老姐们应该都知道,新OO课程中,第二到第四单元部分的基本路子,简而言之,不再是单纯的平地起高楼,而是基于官方包进行开发,学生主要开发的内容是作业的部分核心逻辑,将其封装进标准官方接口,然后在官方包内的外围逻辑支撑下,形成一个完整的程序。大概就是这样的一个模式,其最大的优势在于让学生真实体验分层开发,并且让学生开发注意力聚焦在作业的核心逻辑部分中。在马上的软工课程中也将考虑采用这一模式。
本文也将基于上述的基本前提,以及结对项目课程基建的一些基本需求,对过去两年的结对项目学生作业情况等数据进行分析,以达到更进一步明确课程现状和课程基建开发需求的效果。
结对项目分析与课程基建需求
根据笔者自己的整体研判,需求应该主要分为两部分:
- 课程平台基建,指与课程本身相关,为学生持续提供服务的平台基建,例如gitlab、评测平台等
- 作业工具链,指与具体的作业相关,为学生的作业完成引导方向,并为课程平台基建的评测提供方便,例如之前OO课程的官方包
大致需求就是这两部分。考虑到软工这边的实际情况和OO有所不同,故这一需求应当进行如下细化:
- Gitlab CI专用Runner,现在的Runner基本还都是泛用runner,需要针对课程需求专门构建runner。
- 后台简易评测用服务端,用于让CI内的CLI工具对其进行连接。
- CI用的评测用CLI工具,需要结合CI评测的特点,方便易用且能充分顾及到教学评测需求。
- 精细化分层设计的作业与Java官方包,这个OO课早就有类似东西了,得针对具体作业内容来设计。
考虑到时间及人力资源有限,所以在下个学期中,较为可能会采用Java语言进行结对作业。笔者首先对Java技术栈相对熟悉一些,并且有在Java语言上构建官方包等工具链的经验,故作此考虑,以节省时间与成本。不仅如此,考虑到实际上很多同学对C++/C#根本就不熟悉。关于这件事,虽然北航六系的人大一学过程设和数据结构课程,但是用的那是C语言,真正了解C++/C#的都该知道,别看这哥仨都带个C字,也别看C++似乎像是C的超集,但是这仨根本就不是一个概念,甚至也不是一类概念,倒是更类似于雷锋和雷峰塔,老婆和老婆饼的感觉。所以实际上同学们在使用C++/C#进行编程的时候,首先语言就是障碍,而使用他们早已在OO课中十分熟悉的Java语言,几乎没有学习门槛,则不存在分散注意点这一问题。
目前来看的话,需求就是这么些,因此从定量的角度分析,我们接下来的分析还需要搞清楚一件事——我们的系统需要可以支持什么样、多少量的评测需求?
就酱,接下来正戏开幕。
结对数据分析需求
在接下来的数据分析中,我们对所需要分析的数据项作如下定义和划分,其中重要数据项会进行标记:
- 宏观数据
- 总仓库数,即仍可以爬取到的仓库数
- 总组数,即结对项目进行时总共存在的结对组数
- 有效组数,即提交了有效仓库及内容的组数
- 仓库总有效提交数,即全部仓库在有效时间段内的总提交数量
- 提交者数据
- 总不同提交者数,即全部仓库存在的不同提交者数量,按照提交者名称进行区分
- 总不同提交邮箱数,即全部仓库存在的不同提交邮箱数量,按照提交者邮箱进行区分
- 不同提交者数分布状况,即各个组的提交中出现的不同提交者数量分布
- 不同提交邮箱数分布状况,即各个组的提交中出现的不同提交邮箱数量分布
- 提交合并数据
- 总合并提交数,即全部组进行合并提交的总次数
- 合并提交数分布状况,即各个组进行合并提交的次数分布
- 提交变化数据
- 总提交变化数据,包含全部的提交新增行数,删除行数以及文件变化数量
- 总提交净变化数据及占比,结构类似一般变化数据,净变化数据中只包含涉及到关键代码(根据前两年实际情况,即C/C++/C#代码文件,爬取时根据扩展名进行识别)的部分数据
- 提交变化数据,提交净变化数据及占比分布状况,即各组变化数据、净变化数据及占比分布
- 代码规模数据
- 各组代码最终规模分布状况,即总代码规模在各组内的分布情况(最终净代码规模数据由commit的有效新增和有效删除数据进行整合后计算得出)
- 代码提交时间数据
- 总代码提交时间分布状况,即全部组代码提交时间的分布情况
- 各组代码提交时间分布状况,各组代码各时间阶段提交量分布状况
- 代码完成度数据
- 各组代码提交时间及进度状况分布状况,各组项目代码各时间阶段完成度(以当前净变化量相较于总净变化量的比例为标准)分布状况
2019年敏捷软工
背景分析
首先交代一下,关于2019年敏捷软工课程,我所了解到的一些情况。
根据笔者的走访,2017年的实践软工似乎还是个选修课,由于比较肝所以没太多人爱选,这一点大概所有学校都差不多少。不仅如此,2018年的软工都还是统一的,还没有进行分班。而在2019年,软工分为了AI、嵌入式和敏捷三个课程,其中敏捷课程和原本的旧软工内容整体类似,并且软工改为了必修+三选一的模式。
2019年,软工课的结构为,结对编程+团队编程。为期两周的结对编程,内容为实现一个类似分词的功能。
2017年,软工课的结构为,个人编程+结对编程+团队编程。个人项目是个数独,然后结对编程为个人项目的进一步扩展。
2016年,软工课的结构为,个人编程+结对编程+团队编程。个人项目是地铁出行系统,然后结对编程为个人项目的进一步扩展。
更早的软工,则基本上为理论软工,基于瀑布模型等一系列概念,然后作业和考试驱动。而且根据了解,2016、2017年的实践软工课程也属于试点,还没有做到真正的普及。
顺带特殊说明下,根据笔者走访,2018年没有软工课程。因为,那个学年的软工安排在2017年秋季学期,也就是大三上;而之后一届则因为课改而开始安排在了大三下,即2019年春季学期,也就是笔者作为学生的这个学期。因此2018年没有软工课程,2017年即为笔者之前最近的往年。
数据分析
笔者对现在依然还能在github找得到的结对作业仓库进行了数据爬取,得出的数据进行整理后在本节放出。
在下述的数据中,对于来源非爬虫数据整理的数据项,会标注数据来源。
对于一些涉及分组分析的数据,组别信息等可能涉及隐私的数据均已经进行过脱敏处理。
宏观数据
- 可访问仓库30个
- 总计结对小组35组(来源:2019年课程组)
- 其中34组有效(来源:2019年课程组;此外经过与相关助教的确认,唯一无效的组当时未提交作业且始终无法取得联系)
- 全体可访问组共计创建了818条git提交,平均每组27.26条
后续的所有数据将以30个可访问的仓库为基础,并统一称之为全体组。
此外,小小吐槽一下,这个数据其实应该趁热乎就爬下来的,这样数据会更完整,也比炒冷饭更具说服力。
提交者数据
- 全体组共计出现过73位不同的提交者,出现过共计76个不同的提交邮箱
- 各组仓库全程出现的不同提交者和不同提交邮箱数量如下所示
- 各组出现的不同提交者数分布情况如下
- 各组出现的不同提交邮箱数分布情况如下
基本可以看到,大部分组的不同提交邮箱数和提交者数量控制在2-3左右,有个别组数量较大,也有个别组异常过低。
提交合并数据
- 全体组总计进行过80次合并提交
- 各组仓库出现过的合并提交次数如下如所示
- 各组合并提交次数分布如下图所示
这边可以看到,有相当多的组全程没有进行过合并操作,而且很多组全程只进行了一次合并操作,只有少部分的组真的有多次的合并,比较像是在“结对”编程。
提交变化数据
- 全体组共计提交了801066行新增代码,314858行删减代码,9693次文件变更(单位:文件*次)
- 全体组共计提交了307347行有效新增代码,82271行有效删减代码,2998次有效文件变更(有效指的是包含在净变化中的部分,关于净变化的定义可以参见上文数据项定义),新增、删减和文件变更总体有效率分别为38.38%、26.23%和30.93%。
- 各组提交有效率数据分布如下图所示(由于存在有较多的组由于各种原因,新增、删除和文件变更数据比较极端不便展示且实际意义有限,故仅展示有效率分组数据)
不难发现,有效率数据各组比较两极分化,肉眼可见有较多的组有效率较高,但是也有不少很低的组,而且全组有效率值也很低。
代码规模数据
- 各组的最终净代码规模值如下所示(最终净代码规模定义见上文;下图已经去除了五组因为git使用问题而导致数据明显异常的样本)
- 被去除的五组数据中,有三组经核查,系直接在源代码中大面积拷贝GUI开源代码所致(大约几万行到几十万行不等);另外两组作业本身存在较大问题,无参考价值。
通过这个,可以大致判断出2019年结对项目的规模和工作量。
代码提交时间数据
- 全体组的总代码提交次数在整个任务周期内的分布如下图所示
- 各组的代码提交次数在任务周期内的分布如下图所示
可以明显的看到,在任务的中后期,总提交次数有非常明显的提升(果然老拖延症了);而各组图上的数据则看起来相对平滑,只是后期更加密集。
代码完成度数据
- 各组的项目完成度数据分布如下图所示(项目完成度数据计算方式和定义如上文所示)
可以看到,不少组依然还是后场发力型的,后期折线明显陡峭了不少(果然老拖延症了x2),能在中前期达到同比例进度的微乎其微,在七天时能达到一半进度的也只有不超过5组。
综合分析
基于上述数据,我们可以对2019年的结对项目得出以下的基本结论:
- 根据宏观数据、提交者数据部分来看,应该大部分组应该是有两个人在参与编程。不过比较有意思的一点是,不少组有3个不同commit身份,而且看了下这第三个身份大多是github noreply邮箱,似乎大家比较喜欢在页面上开commit?
- 根据对合并数据的分析,可以基本判定,有相当多的组根本就没有在结对编程。这样的组最少一半,甚至很可能高达八成,具体表现为,全程没有merge commit,或者只有极少的merge commit。而根据笔者个人的理解,结对编程这样的模式中,必然存在大量的双人伴随式工作,commit会呈现密集的交叉状,如此少量的merge显然是不太正常的。当然,还有另一种可能,那就是这俩人真的就在一个机子上用同一个commit profile在工作,但是结合上一条结论来看,这种可能性基本站不住脚。这一条结论细思极恐。
- 根据对代码提交变化数据的分析,尤其是其中有效变更率的分析,我们不难发现其中的两极分化。换言之,有一定数量的组可以做到高有效率,而其他的组则有效率极低。但凡用过git的都该清楚,这个地方的有效率过低,基本意味着使用者对git的掌握存在较大问题,比如根本不知道用ignore来确保仓库干净,也很可能在跨系统开发中不知道设置换行符选项导致大面积rewrite,更不知道在操作失误后进行rebase修复commit。
- 通过对代码规模数据的分析,可以大致判断,该年度的结对项目工作量在1k-4k行这个范围,具体工作量随使用的具体工具链以及实现方式等因素浮动。而对于一些极端数据的统计来看,部分组存在直接大面积拷贝开源代码的情况,这说明部分组对相关技术栈及其依赖的理解依然严重短缺,还停留在最为简单粗暴的层面。
- 通过对完成进度数据和提交时间数据的分析,我们可以看出大部分团队依然存在较大的拖延症(废话),对前期时间的利用率十分低下。以及根据对提交时间数据的分析,可以看到后几天大概总提交数在100-200范围,平均到每个组,大概每个组3-5次提交。这样的评测量,只要不是极短时间内扎堆,对于笔者开发经验和能力所可以做到的评测技术,问题不是很大,最起码远远小于OO课程系统的峰值评测量。
- 此外,根据笔者在这一届(也就是自己所在的这届)同学的调研,该届学生对课程的整体评价不高,但是也不算太过于不可接受,最起码形势比当年的旧OO还是乐观不少的。而对于结对编程部分,在这一届实际上真正进行配合的小组和个人恐怕不多,而且民间也普遍并不能理解这样的要求。
2020年敏捷软工
背景分析
然后呢,关于2020年敏捷软工课程,我也简述一下我所了解的情况。
2020年,可能是出于对第一届大类招生的学生情况的不确定,也可能是刚好赶上了疫情的特殊时期(确实挺特殊的,去年我们的有些研究生课程的考核方式都变了),于是这届的情况发生了一些变化。具体来说:
2020年,软工课的结构为,个人编程+结对编程+团队编程。个人编程玩的是一套很奇葩的计算几何题(说到这个笔者有很多粗鄙之语要讲,这个后文有专门片段喷之,敬请期待),然后结对编程是基于这个计算几何,搞个更神奇的GUI出来。
数据分析
该部分需要声明一下,该部分分析主要针对结对编程部分。然而实际上由于个人项目和结对项目在git序列上存在连续性,故有些时候不能绝对划清界限,希望读者对该因素可能存在的潜在干扰有所判断。个人项目大概为期一周,结对项目大概为期两周,前后存在较强的关联性。该部分目前爬取的数据均为结对项目阶段的提交,个人阶段的工作不会被算在内。
在下述的数据中,对于来源非爬虫数据整理的数据项,会标注数据来源。
此外,这年的奇葩结对题目也会必然对结对数据分布造成影响,请读者有所了解和判断。
宏观数据
- 可访问仓库37个
- 总计结对小组42组(来源:2020年课程组)
- 其中42组有效(来源:2020年课程组)
- 全体可访问组共计创建了601条git提交,平均每组16.24条
后续的所有数据将以37个可访问的仓库为基础,并统一称之为全体组。
提交者数据
- 全体组共计出现过73位不同的提交者,出现过共计76个不同的提交邮箱
- 各组仓库全程出现的不同提交者和不同提交邮箱数量如下所示
- 各组出现的不同提交者数分布情况如下
- 各组出现的不同提交邮箱数分布情况如下
可以看到,2020年的整体不同提交者数和不同提交邮箱数明显降低,单邮箱和单提交者的情况变得多了起来,事情似乎变得更加像结对编程了起来。但是结合实际情况来看,这真的是事情的全貌么?恐怕未必,继续看下去。
提交合并数据
- 全体组总计进行过35次合并提交
- 各组仓库出现过的合并提交次数如下如所示
- 各组合并提交次数分布如下图所示
这一年合并的次数也大幅度下降了,更是有不少组全程没有合并。这个情况的变化挺令人吃惊的,后续会详细研究下。
提交变化数据
- 全体组共计提交了538237行新增代码,78736行删减代码,5966次文件变更(单位:文件*次)
- 全体组共计提交了376668行有效新增代码,25707行有效删减代码,2433次有效文件变更(有效指的是包含在净变化中的部分,关于净变化的定义可以参见上文数据项定义),新增、删减和文件变更总体有效率分别为69.98%、32.64%和40.78%。
- 各组提交有效率数据分布如下图所示(由于存在有较多的组由于各种原因,新增、删除和文件变更数据比较极端不便展示且实际意义有限,故仅展示有效率分组数据)
不难发现,有效率数据各组依然存在两极分化现象。不过,肉眼可见有大量的组有效率较高,但依然存在少量的低有效率组。
代码规模数据
- 各组的最终净代码规模值如下所示(最终净代码规模定义见上文;下图已经去除了六组因为git使用问题而导致数据明显异常的样本)
- 被去除的六组数据中,经核查,全部系直接在源代码中大面积拷贝GUI开源代码所致(大约几万行到接近十万行不等)。
通过这个,可以大致判断出2020年结对项目的规模和工作量。
代码提交时间数据
- 全体组的总代码提交次数在整个任务周期内的分布如下图所示
- 各组的代码提交次数在任务周期内的分布如下图所示
可以明显的看到,在任务的中后期,总提交次数有非常明显的提升(果然老拖延症了x3,而且比去年还更严重);而各组图上的数据则看起来相对平滑,只是后期更加密集。
代码完成度数据
- 各组的项目完成度数据分布如下图所示(项目完成度数据计算方式和定义如上文所示)
可以看到,不少组依然还是后场发力型的,后期折线明显陡峭了不少(果然老拖延症了x4)。但是相比于2019年,有一定的进步,7天中场的时候有5组进度已经过半,也有一定数量的组进度超过1/3,更有一个组已经超过了八成的进度。
综合分析
基于上述数据,我们可以对2020年的结对项目得出以下的基本结论:
首先,请注意一个特殊情况——2020年赶上新冠疫情,学校课程大多居家进行,软工结对协作与后期的团队协作也都在线上进行。
根据对宏观数据、提交者数据和提交合并数据的分析,再结合笔者私下的一些走访,推测在2020年,不少组进行了真正的结对编程(课堂上有介绍vs的在线协作功能,以及腾讯会议等工具),然而一部分组却退化为了普通的双人分工协作(一部分因为技术栈门槛原因,另一部分因为时间缺乏,还有一部分在线协作不便的影响在内,其中技术栈门槛为比较重要且普遍的原因),基本上由此分化为了两个截然不同的群体。
根据对提交变化数据中有效率数据的分析,不难发现这届学生很可能对git,尤其是gitignore的运用较好(作为OO助教表示很欣慰),不过实话实话,也需要注意他们的结对工作不是从零开始的,而是基于个人项目阶段成果,跳过了最容易导致git污染的初识阶段,也可能是有效率数据较高的原因,这一点有待进一步观察。
根据代码规模数据,可以推断出这届的结对阶段工作量大概为1k-3k行范围,较之去年有多降低。而对于一些极端数据的统计来看,依然有部分组存在直接大面积拷贝开源代码的情况,这说明部分组对相关技术栈及其依赖的理解依然严重短缺这一问题仍然存在,务必引起我们的持续关注。
代码提交时间数据和代码完成度数据来看,实际上和去年也基本类似,区别在于整体来看,学生们的拖延症似乎加剧了,不知道和居家学习是否有关系。这就导致之前的commit数不足,但是最后一天出现大量提交,超过了200次。不过好在整体来说不算太离谱,事情还在可控范围内。
综合思考与建议
上面两节对两届数据进行了整体和细节上的一些分析。等说完了数据分析,说点对于接下来课程结对项目力所能及的建议。
结对编程!是也?非也?
首先,咱们先看看结对编程这件事。
结对编程(英语:Pair programming)是一种敏捷软件开发的方法,两个程序员在一个计算机上共同工作。一个人输入代码,而另一个人审查他输入的每一行代码。输入代码的人称作驾驶员,审查代码的人称作观察员(或导航员)。两个程序员经常互换角色。
在结对编程中,观察员同时考虑工作的战略性方向,提出改进的意见,或将来可能出现的问题以便处理。这样使得驾驶者可以集中全部注意力在完成当前任务的“战术”方面。观察员当作安全网和指南。结对编程对开发程序有很多好处。比如增加纪律性,写出更好的代码等。
以上描述来自百度百科,关于结对编程的基本定义应该基本上算是清楚的。其关键点在于:
- 两人共用一机(大致这个意思,但未必如此严格,基本思想相符即可)
- 一人编写代码,另一人即时审查并了解思路(这是结对编程的核心思路)
- 两人经常性互换角色(无明确要求,保证思路连续性的前提下适应节奏即可)
这看上去似乎特别理想,对吧?其实没错,从现实角度来说,结对编程确实是个在某些实际开发中有奇效的方法。
但是不得不说,另一方面,就笔者自己的见闻和一些经验来看,这个编程方法却有着显而易见的门槛。具体来说:
- 两个程序员必须都是精锐,技术实力必须均过硬,自己都一知半解的写代码写不出来,帮人看也看不出来啥
- 而且必须对对方的风格与节奏高度熟悉,得充分了解对方喜欢怎么玩,容易犯哪些错误,不然所谓的复审基本上更像是在制造干扰
- 还需要能做到密切配合,不说别的,俩脑回路完全不在一个频道的人这一点基本没可能做到
能做到上面三点,结对编程才有意义。换言之,如果程序员自身水平没有达到能肉眼高速捕捉问题,同时大脑高速构建逻辑展开分析的程度,或者做不到足够了解搭档的习惯、风格与节奏,那么结对编程纯粹就是在胡闹,没有丝毫效率提升反而净会添乱,还不如两个人各自开发,然后基于git在线平台协作来的快,最起码还能发挥并行优势。这是一笔很简单的账——如果两个人结对编程带来的短期和长期效果,达不到一个人独自编程的效果乘上二的话,那么结对编程从结果上来看带来其实是负收益。当然了,实际上结对编程还有另一种可能,那就是纯粹的单方面教学培训,一个老手带一个新手,新手写老手看。这个也是一种比较可取的思路,但是在我们的软工课程中这种模式显然不具备可操作性,也不具备普遍意义(毕竟大部分人就那水平,哪来的那么多大佬,况且大佬自己也得学习),故不作展开讨论。
基于上述分析,结对编程对配合默契的精锐力量才有足够的正面意义。这一点在实际应用中,尤其是在小规模精锐团队中,其实完全可以做到,做不到的话磨合磨合也不是啥大问题。可是反过来看,这样的门槛,放到课程中,给这些尚在学习阶段,知识上未脱离一知半解甚至有些半瓶子咣当,做事上协同意识不够的学生来玩,会意味着什么呢?只怕很可能无法取得期望的效果,具体来说:
- 首先技术上他们都自顾不暇,谈何复审?技术底子好点的到还好些,还能在实践中跌跌爬爬共同学习,而对于其他人,除了能盯着屏幕发呆之外还能干啥?而且ddl还很紧,课业压力还很大,自己对技术不够自信,再耗下去能不能ddl前完事都悬,所以干脆选择分下任务各干各的自然在情理之中。
- 俩人都是临时组队,而且还根据笔者私下走访,由于课程规定结对伙伴在团队项目中不可以同组,因此导致大部分人更愿意将自己熟悉的老伙计放到团队阶段,从而在结对阶段直接就排除了全部自己熟悉的人,而去选择陌生的人作为伙伴(当然,如果他能有超过七八个足够熟悉的老伙计,那大概没这个问题,不过能有如此多实战经验足以做到这件事的人,恐怕这些问题对他来说没啥讨论的必要,毕竟横竖都是躺赢了)。这样选出来的伙伴,熟悉度基本为零,这就成了一道必须迈过去的坎。
- 而配合上,和上一条类似,一切得从零开始,学着配合,还得祈祷别点背选一个和自己搭不上的人。
总而言之,在以往的结对编程阶段中,对于一般同学,在短短十四天周期内,需要完成这么多件事:
- 学会相关的语言/技术栈
- 完成任务本身的程序编写
- 为了能尽可能配合起来,需要快速熟悉对方的风格
- 为了能尽快配合起来,需要快速与对方的脑回路进行磨合
十四天,这么几件事,然后加上大三下,不少人都还有一堆别的事,压力还是不可小看的。于是不少同学就直接选择抛弃后两点,而只选择前两点,把技术栈run起来,代码码起来,赶在ddl之前完事就好了。
说了这些,笔者认为想要解决的话,还是应该回归最根本的一点——首先请务必想明白结对项目到底为了啥而存在,想起到什么样的作用,在课程中扮演什么样的角色。在想明白这个问题后,然后再去说给学生听,并配合恰到好处的规则,让学生要么发自内心去接受最优解,要么迫于规则去接受最优解,要么基于利弊权衡去接受最优解。
懒病为何要治?要怎么治?
通过上文的数据,可以看出比较明显的一点是,同学们的拖延症真的比较严重。
这个结论我相信大家都不感到意外,笔者在此也无意去吐槽这个,毕竟这是人之常情,不信扪心自问自己考期那些DDL都是啥时候完成的。笔者真正想说的一点是,作为课程组,应该想办法去调动同学们前期的积极性。这件事情不仅关乎个人好习惯的养成,更与课程教学效果有直接关系。
因为不说别的,上一节中分析的14天内需要完成的事情,在实际情况下,还需要将另一个因素纳入计算:
- 前期中期磨洋工的时间
别笑,这是真的,不信的话你可以在上面的两张进度图上,画一条连接(0, 0)和(14, 1)的斜线,看看各组都是从什么时候才开始能走高至斜线以上的。虽然我知道有人会反驳,说前期需要学习技术,但是我想请问各位学霸们,你们平常玩起内卷这些无聊事起来一个顶俩,这种关头真的至于如此拖沓么?都好好问问自己吧,你们自我欺骗的样子真的太好笑了,别再丢人现眼了行不。总而言之,实际上根本没几个组能做得到这件事,如果没有足够的约束,那么前期磨洋工基本上是常态。各位做老师做助教的都该清楚一个事实,那就是,一个DDL给30天完成,和给3天完成(如果确实来得及的话),基本上没太大差别,甚至反而可能造成一些人干脆忘了ddl。
而在我们的课程中,在14天这种短周期里,如果这种事情还放任自流的话,那只会造成实际工作时间被进一步挤压,学习效果进一步打折。是,你可以谴责学生如何如何愚蠢短视,但是谴责完了呢,时间回得来么?已经学拧巴的了还扭得回来不?
其实呢,想解决也不算难,治懒病最好的办法那就是持续制造目标,而且还得是非完成不可的那种。对于个人来说,那就是把flag立起来然后自己一懒就会想起flag,亲测有效欢迎尝试。而对我们的课程来说,那就是在前期设置“检查站”,多设立几个阶段,每个阶段需要完成部分功能,然后进行评测,确保每个阶段都充分动起来。这件事在OO的后几个单元已经有过类似的操作,今年可以在软工课程中同样进行尝试。
该知道的就该说,猥琐发育不可取!
在北航这边,我发现不少课程都喜欢强调自学这件事,而且在实践中也深深贯彻这个理念。
当然,笔者认为这件事很重要,甚至可以说是计算机从业者的基本素质之一。可是直接给一系列概念和任务,然后当甩手掌柜,美其名曰“自学”,真的合适么?私以为这是非常无能的做法,之前笔者见过的多个课程,都已经证明了这个做法的糟糕之处。具体来说,虽然自由度大,自主性强了,但是另一方面会造成学生缺乏必要引导,只图解决眼下的问题,因而猥琐发育。而打了个错误的地基,眼下或许没有问题,但是长久的话迟早会有问题暴露的一天,那就太迟了。
具体来说,一些基础的工程知识还是应该普及起来。比如:
- git的基本使用(这个OO基本上教过了),git的基本规范
- gitignore的使用(这个简直重灾区)
- 包管理工具的用法,或者一些正确使用外部依赖的姿势(最起码别再大面积复制开源代码了)
- 编程语言的一些小技巧和知识(别小看这个,哪怕近在眼前,但要是不提一下子的话很多人就会闷头干到累死都不去琢磨哪怕一下)
- 编程的常见基本思路(思想很重要,触类旁通的基础)
诸如此类的基本知识都是有必要说一说的。不过不必说的非常多,大张旗鼓专门介绍更是没有必要,只需要科普一下,或者发些资料即可。
把时间花在对的地方,做好减法!
这一点,笔者在私下走访的时候,反馈比较明显。具体来说,笔者所问的一些技术底子较好,动手能力较强的同学,也都在反馈需要时间去适应技术栈。可想而知,对于更多的人,如果所使用的技术栈存在过高门槛的话,那势必牵扯更多的精力。前文已经提到过,目前使用的C++/C#技术栈,大家对此其实没有想象的那么熟悉,而且这部分所需要的技术积累,和大一程设、数据结构所学的C语言又并不是同一回事。
所以笔者提议,考虑到北航六系本科生的实际学习经历,建议尝试采用Java技术栈进行开发。他们经历过OO课程的洗礼,此外这门课程也是我和老伙计们改革过的,我了解学生的真实情况,这部分只要把作业好好设计,好好做好减法,可以达成较好的效果。
作业本该精细化,作业设计者更该专业化!
这个事情的话,那就真的是老调重弹了。我发现不少助教甚至老师,都觉得作业是个很简单的事,只需要把握住核心思想,然后布置一下就完事了,题目选择啥的更是如此。
可实际上,笔者本人作为一个从小学竞赛到大学,并且出过比赛题和作业题的老竞赛党可以告诉你们,出题可绝对是个技术活,也是个精细活。具体来说,出题这件事,基于其不同的动机,可以分为以下三类:
- 作业题,常见于教学阶段,目的是帮助学生掌握和巩固知识技能
- 考核题,常见于教学考核,目的是检验学生的知识技能掌握水平
- 选拔题,常见于竞赛和面试,目的是在参赛者中选拔出技能达到某种要求
这三者基本上代表笔者所见过的主要题目定位类型,各位出题的时候还请务必思考下出题的定位,这至关重要。而对于软工这样的实操类课程来说,出题的定位基本上为作业题,目的是帮助学生学习。基于这一点,作业则务必考虑与学习曲线匹配,用通俗的语言来说,学生基于课堂内容,你的作业题,以及一些必要的辅助资料和讨论,应该可以达到学习这门知识或技能的效果。基于这样的考量,所以出题之前需要对学生的真实状况及特点,进行具体化精细化的设计。结合到软工课程,作业的设计则应该突出软工这一基本主题,要突出工程方法、工程设计、团队协作等核心要素,并且确保在实际情况下,学生的学习曲线和方向完全符合预期。
这部分的话,大概就是这么回事,作业值得精细化,作业的设计者也应该专业化。实际上竞赛选手,在明确了出题定位后,往往可以做的更好;即便没有条件找到专业人士,现有的出题者也必须对这件事充分重视,切忌轻敌和粗放式操作。
胡言乱语
好了,正事说完了,下面是国际惯例的嘴臭吐槽时间。
首先,必须吐槽下去年的结对题目设计,传送门在此。这是一道关于计算几何的题,大概干的事是计算点和圆的交点,并且需要GUI展示。听说出题的是个ACM大佬,笔者走访了下,此人确实算得上个大佬。在此处我没有冒犯谁的意思,但是我就是感觉这个题目出的很有问题。首先,您身为ACM选手,应该不会不清楚,计算几何这是个坑,别说普通同学了,就算是有一定经验的ACM选手,要是没有专门研究过此类题目的话,都很容易踩坑。具体来说,看上去直线交点啥的似乎不难,高中解析几何知识而已,但是真要是揪细节的话,那门道可就多了去了,比如最常见的几个:
- 笔直向上的直线你咋用数学描述?\(y=kx+b\)恐怕不行吧?\(Ax+By+C=0\)一般式没得跑。
- 平行或重合的直线,你怎么定义这样的交点结果?一般式直线的求解可是依赖矩阵求逆的,行列式为0如何处理?
- 直线和圆的交点怎么算?我指的是,怎么尽可能精确的算。咱们算数学题可以得出解析解,但是计算机可没有这玩意,只有浮点数呢,这个精度损失你打算怎么控制让其不会一阵缩放后直接原地升天?
- 咋的,精度问题你不信?行,你狠。然后下一个问题,多个直线和圆,交于一点,你咋判断?直接等于那可不成,太容易失误了。然后eps多大,能容忍你之前对精度的无视?并且还不进行误判?
以上是小细节上的各种坑,更别提根据笔者走访,当年的题目也将大量元素构建成大规模数据,在算法复杂度上也有较高的要求(基本上是ACM级别的要求了),也更别提还有个GUI部分,需要自己构建一个画板将这些内容进行绘制(坑点一样多的很)。数据上基本没有啥梯度,遍布大型数据(需要特定算法才能解决)以及坑点数据。这些对于竞赛选手来说,考点没啥,但是对于普通学生,最终造成的结果就是个别人高分,其他人几乎没分,而且高分的人主要精力都放在了算法而非工程本身。
各位可以想象一下,大部分同学面对这玩意的时候,心理阴影面积多大了。而且不光阴影面积大,题目的设计还很粗劣,从题目到数据,完全一股子ACM味,丝毫没有精细设计的影子。用选拔题来干作业题该干的事,荒不荒唐?我还很好奇,如果这个出题人是个脑子没动到位或不大好使的非竞赛党,然后没轻没重出了个这样的题,虽然我还是会骂,但是还不算太不可理喻。而此人为著名ACM大佬,WF选手,厉害的不行,居然会连这些问题都看不出来?不会这么有失水准吧?而如果不是这样的话,那又是什么原因呢,是在应付差事,还是为了满足些自己什么别的利益或者欲望呢?然后学生一做不好,就扣人家个蠢人的帽子,挺爽的是么?我无意搞阴谋论或者啥的,那很无聊,也无助于解决问题,我也清楚我并不是人家肚里的蛔虫,没资格代表人家,也不该过度揣测。我只是觉得,一个真正认真负责的助教,况且还是个有真才实学的助教(暂且认为如此吧),出这样的事实属不该。而我的吐槽,也只是一面之词,我希望此人可以有一份有则改之无则加勉的胸襟和眼界。此外我也希望呢,助教就该有个助教的样子,有点责任感和使命感,别用学生的血泪来暖自己,您说呢?
然后接下来,是老调重弹。经过前阵子和一些人和事的接触,我越来越感觉,咱们计算机教育领域真的是光怪陆离。具体来说:
- 教的人呢,理论挺扎实,一套一套的,但是真正的实践却又一知半解,最起码大都不近基层。
- 而懂实践的人呢,都在享受最伟大的福报,沐浴最牢不可破的兄弟情,然后一天一天数着自己掉下的头发茬子,也一天一天数着自己离35岁彻底变成甘蔗渣还有多少天。
- 而大环境呢,又从来容不下像国外那些高龄专家的人,只知道不分青红皂白,将甘蔗丢进榨汁机,榨完了换一茬新鲜的,渣就直接扔掉,至于渣用来干啥,管我们啥事,挖掘价值变废为宝?不存在的!
是啊,挺奇怪的,不最懂的人在作为,真懂的人又无能为力。就像一个单向阀一样,把真正该发挥作用的一茬人源源不断吸走,然后用完了直通垃圾桶。我呢,之前思考过为何国内的现状一直如此,为啥我改了一门OO,其他地方一样该咋样咋样,我们帮扶,我们宣传,也只是白费力气还被当擦脚布。我曾经以为是大多数人太过愚蠢,烂泥扶不上墙,但是我越来越觉得,而相反实际上大部分人聪明得很,他们完全看得清在现有游戏规则下,怎样对自己最有利。而没看清楚这一切的我,才是那个真正的蠢人。表面上是大多数人如何如何没情怀,实际上是他们就没被允许拥有情怀,他们的意志,也不过只是一种更大的潜在意识的体现罢了。而只要这样的环境不有所改变,生态结构不往健康发展,那么做的再多,也只是杯水车薪,只是徒劳和自我安慰罢了。咱们这个领域缺的也从来不是个把英雄老师和英雄助教,就像是大清缺的也不是个把邓世昌,几条铁甲舰,抑或是几箱塞不进炮膛的炮弹。我真心地,希望看到这一天的改变,以及可以的话,希望可以亲自改变这一切。
说完了大的,那说写小点的,也是离我们比较近一些的。我本人是一直提倡助教团队精英化的,不为别的,而是因为一些显而易见的原因:
- 助教本身实力强大了,才更可能对课程的改革提出实实在在可操作的改进,且对课程教学及内容本身有更好的把握性
- 助教本身有技术力量,才更可能推进对课程教学的自动化,参与到开发中来
- 经过精英助教们的改革,课程越来越好,学生大佬们也会越来越感兴趣,越来越愿意继续贡献力量
- 此外,大佬们本身也是有圈子的,经营好了这个人脉,以后很多届的人才都不愁了
基于上述的一系列实际原因,一届经营好的精英助教,足以形成一个顺畅的良性循环。私以为,这是我们领域助教工作开展的正道,也应该是大势所趋,毕竟优势太显然了。不过我却发现,很多课程团队却丝毫没有这样的意识,依然继续用着要积极性没积极性,要真本事没真本事的助教,然后期望他们扛大梁,期望他们创造奇迹。然后每年被吐槽,站出来声泪俱下反思下,然后反思完该咋样继续咋样。我就真的感到无法理解,不去好好经营,不去谋求发展,不去培养新鲜血液,指望一群打杂的扛大梁?这是什么样的一种心态呢,自己干什么去了?就打算这样等着升官发财等着数钱手抽筋么,真是滑稽,和那个蓬头垢面满大街跑,然后时不时张着嘴盯着天指望掉馅饼下来的傻子有何区别?无意冒犯,我只是觉得,甭管做啥,总该走点脑子,也用点真心吧!有欲望不是罪,但是做大梦来追求欲望,那就很好笑了。
最后扯一件事,关于教学用工具链的,这也是老话了,笔者在博客中这是第三回说了。直接摘录下之前的博客吧(来源:【作业】2020年高等软件工程课程期望与笃信)
此外,课程层面上还有另一个值得注意的地方,那就是是否适合直接将产业用技术、方法及其工具链(下文统称产业应用)直接引入课程教学中。这个问题我在之前的面向对象课程中也面对过,曾经使用的JSF是一个不算成熟且有颇多缺陷的实验型工具暂且不论,后续引入的是JML、UML相关工具链,这是都在严格软件工程领域有一定应用的,实际产业应用的推广足以证明其对于产业的价值。但是产业的应用场景和教学的应用场景依然有很大的差别。具体来说,产业应用重在提高产业开发与协作效率,并且常常有一个基本的前提与假设——使用者是在以提高开发效率为目的进行工作的(类似于no evil原则)。而这个假设对于课程应用来说,可能会造成致命的后果,因为学生常常并不能做到这一点,恰恰相反很多学生更像是在为了通过某种考核而工作。而产业应用常常因为其需求性质,而不具备对教育与考核相关功能的充分支持,于是就会造成很多钻空子甚至严重破坏教学与考核秩序的情况出现。当然,说这些不是说不应该引入产业应用,只是说不应该直接盲目地,生搬硬套地在课程中引入产业应用。为了解决这一问题有两种基本思路,其一是基于产业应用,自行设计教学考核用应用,这样可以做到量身定制但是对于课程组而言水平要求相当高;而另一种思路,则是进行充分调研分析后,设计出合理的教学内容与方法,辅助以完善的考核方法与制度,实现公平合理且引导性良好的考核。
关于这件事呢,我相信业界肯定不只有我想到了这件事,而且我也大概不会是在这个问题上想的最深的人。所以我很期待能就这个问题与抱有同样思考的人一块交流。此外,我也希望业内的大家也都思考思考这件事,大抵是没坏处的。
鸣谢
在这次分析中,需要特别鸣谢:
- 本科软工任课老师们的课程资源支持,以及学院方面的认可支持
- 各位助教及非助教大佬们的数据整理支持,以及前辈们的不懈努力
- 业界知名大佬们的技术与非技术指点,以及一些至关重要的牵线搭桥者与引路人
以及还要提前好好感谢下:
- 各位即将选课的敏捷软工学生对我们的信任,以及对我们工作的支持
真的非常感谢,你们所有人的鼎力支持,是我们持续开展工作下去的动力,也是课程不断改善直至最终走向正轨所比不可少的。而我们,也一定不会辜负各位的期望,将课程越变越好,让学生能最大限度掌握知识和技能。
眼下,我作为准助教头子,更是清楚,该做的事与想做的事多得是,有些事情不是一届能做完的,且历史的推进者必须有觉悟直面一切误解。其实想想也都很简单,一届不行,那就两届,两届不行,那就三届,我离开了,那就让我的同志继续做下去,只要思想不滑坡,办法总比困难多。我们的学校生涯,甚至人类的这辈子,都短的很,做不了太多事,但是人的意志和信念才是真正可以不灭的,它不会因人个体的消逝而灰飞烟灭,相反可会更加强大。我们的历史已经无数次证明了这件事,这无需多言。
话差不多也算是该有个头了,最后搬运一下我在做OO助教时,知乎上的一小段回答,其中有些还是热乎的:
- 我们会尽到我们的基本职责,并尽力给学生最好的体验。
- 改革这事,成功不必在我,但我相信每一届人的付出,都不会是白白浪费的。每一届人,也都是站在前人的肩膀上的,这一点,我们也不例外。以及有一天,我们也会成为后人的垫脚石。
- 我也很清楚,无论怎么做,都不可能让所有人都绝对满意,这很正常。不过那又如何,我们应该做的事从来就没变过。我们是课程组,助教团,我们的职责是让这门课程更好,是实实在在帮助学生,而不是涂上红脸蛋穿上花裤衩再蹦个迪取悦学生。
- 我们一直很感谢大家的支持。
- 对于愿意在改变现状上努力付出的人,我们报以最大的敬意。你们的鼎力支持是我们前进的最大动力。
- 对于愿意摆事实讲道理,毫不客气分析并指出课程的问题,甚至给出了建设性意见的人,我们也非常欢迎。你们的批判和指点,是现在和未来学生们学习体验和效果更好的关键保障。
- 对于坐享其成、过河拆桥,或者只是单纯地因为个人恩怨或者自己的情绪,甚至只是看热闹不嫌事大,就恶意攻击、诽谤、带节奏的人,我劝你们善良。不为别的,这是为你们自己好,无脑上头式的狂欢最后到头来作践的是你们自己。希望你们可以放清醒些,长点脑子长点心,对不起谁都成别对不起自己,更不要傻乎乎充当别人的炮灰。
- 对于一些别有用心,甚至意图或正在搞点大动静的人,我呢,不想过度揣测什么,因为我觉得我比起有些又当又立的人还算是稍微有些洁身自好的。但是你们经常念叨的一些话,我想还给你们——“群众的眼睛是雪亮的,历史终会做出评判。”。以及希望你们明白,人在做天在看,多行不义必自毙,老天不毙那就我们来毙,阎王不收那就我们管埋,我们会为了大多数学生本该拥有的利益而保留采取一切必要手段的权利,勿谓言之不预也。
- 此外,欢迎有志于一同建设课程的各方有识之士加入,我们需要志同道合的你,共同实现理想。
好的,就是这样,告辞。