各位同志們大家好,我又回來磨嘰了,前陣子忙於肝程式碼而鴿了一陣,實在不大好意思?。由於接下來會參與北航本科敏捷軟工的課程改革,並且在技術開發這一層面而言,重點將會是結對作業部分。上過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助教時,知乎上的一小段回答,其中有些還是熱乎的:
- 我們會盡到我們的基本職責,並盡力給學生最好的體驗。
- 改革這事,成功不必在我,但我相信每一屆人的付出,都不會是白白浪費的。每一屆人,也都是站在前人的肩膀上的,這一點,我們也不例外。以及有一天,我們也會成為後人的墊腳石。
- 我也很清楚,無論怎麼做,都不可能讓所有人都絕對滿意,這很正常。不過那又如何,我們應該做的事從來就沒變過。我們是課程組,助教團,我們的職責是讓這門課程更好,是實實在在幫助學生,而不是塗上紅臉蛋穿上花褲衩再蹦個迪取悅學生。
- 我們一直很感謝大家的支援。
- 對於願意在改變現狀上努力付出的人,我們報以最大的敬意。你們的鼎力支援是我們前進的最大動力。
- 對於願意擺事實講道理,毫不客氣分析並指出課程的問題,甚至給出了建設性意見的人,我們也非常歡迎。你們的批判和指點,是現在和未來學生們學習體驗和效果更好的關鍵保障。
- 對於坐享其成、過河拆橋,或者只是單純地因為個人恩怨或者自己的情緒,甚至只是看熱鬧不嫌事大,就惡意攻擊、誹謗、帶節奏的人,我勸你們善良。不為別的,這是為你們自己好,無腦上頭式的狂歡最後到頭來作踐的是你們自己。希望你們可以放清醒些,長點腦子長點心,對不起誰都成別對不起自己,更不要傻乎乎充當別人的炮灰。
- 對於一些別有用心,甚至意圖或正在搞點大動靜的人,我呢,不想過度揣測什麼,因為我覺得我比起有些又當又立的人還算是稍微有些潔身自好的。但是你們經常唸叨的一些話,我想還給你們——“群眾的眼睛是雪亮的,歷史終會做出評判。”。以及希望你們明白,人在做天在看,多行不義必自斃,老天不斃那就我們來斃,閻王不收那就我們管埋,我們會為了大多數學生本該擁有的利益而保留採取一切必要手段的權利,勿謂言之不預也。
- 此外,歡迎有志於一同建設課程的各方有識之士加入,我們需要志同道合的你,共同實現理想。
好的,就是這樣,告辭。