楊宇霞
(四川大學計算機學院,成都 610065)
在教學領域中,無論是在線教育還是傳統教育,計算機編程能力都是計算機科學和軟件工程課程要培養的核心能力[1],而教育者/考核者評判編程能力水平的方式是以學生課程期末考核表現為依據,即總結性評估。目前,總結性評估方法主要分為兩大類:線下筆試和線上測驗,如圖1所示。

圖1 編程能力評估方法
線下筆試大多是以理論知識為主,代碼編寫為輔。通過多項選擇、填空及問答等方式考核學生的知識點覆蓋廣度和深度,對學生實際操作關注較少。這種按圖索驥的測驗存在諸多不合理性:
首先,計算機編程是一門以理論為指導,以解決實際問題為目的的實踐學科。其本質在于對計算機的實際應用,而上述評估方法未能充分體現其核心思想;其次,這種不以實踐為中心的考核模式會導致錯誤的學習思維,學生在學習過程中舍本逐末,重理論輕實踐,最終與學習的初衷背道而馳;最后,這種評估方式費時費力,而且評價標準因人而異,難以達到評估的一致性。
Bennedsen和Caspersen提出[2],程序實際上是學生使用計算機上標準的開發環境生成的,在這種開發環境中,學生可以反復提交程序,并且立即獲得反饋,根據測試出現的錯誤(trial-and-error)來調試程序。根據建設性調準(Constructive Alignment)理論[3],學生的學習活動會影響最終的學習結果,因此布置的評估任務應與學習活動保持一致。
因此線上測驗以及自動化評估的必要性對編程能力的評估而言則顯得尤為重要。由圖1可知,線上測驗評估方法可以分為兩種,基于編程產物(源碼)的評估和基于編程行為的評估。本文對現有研究中線上測驗自動化評估的評價指標進行分析總結,并針對其存在的問題提出改進思路。
目前以在線開發環境為背景,實現學生編程能力自動化評估的研究已有40多年了,如牛客網、Leetcode等在線平臺。這些研究/工具大多以產物評估為主,即分析學生提交的代碼。其設計思想分為兩類:
(1)動態分析方法(Dynamic Analysis),評分系統首先根據編程問題的需求生成一個測試集,然后將學生提交的程序在該測試集上運行,最后程序的評分標準以運行的程序在該測試集上通過的測試用例數量為依據[4-6]。早期的自動化評估研究,如TRY[7]、CourseMarker[8]、Online Judge[9]等,大部分都采用動態分析的方法對待測程序的功能完整性。近年來,動態分析的研究重點主要在測試用例構造的改進[10],和針對程序的子功能或結構的局部測試上[11]。
(2)靜態分析方法(Static Analysis),將提交的源碼用抽象的表達方式表示,計算學生的源程序與正確答案的程序代碼之間的相似性,從而實現對程序的評分。如文獻[12]中作者基于程序的語義結構相似性,針對給定編程任務生成一個標準解空間,采用SDG作為中間表示形式,采用語義保留(Semantic Preserving)轉化法對形同依賴圖進行標準化處理,根據標準化后的學生程序與模板程序系統依賴圖的匹配結果評分。文獻[13]中作者提出了基于控制流的抽象語法樹(CFAST)來表示源程序,通過控制結構的數目,計算與正確程序之間的距離。文獻[14]中作者結合詞法、語法和語義分析源程序,采用模式匹配理解程序,抽象語法樹(AST)判斷語義相似性,通過設定不同的權值獲得最終的評分結果。此外,Shashank和Gursirman等人提出采用機器學習的方法,通過對待測代碼的CFG和PDG進行特征提取,訓練單層的神經網絡回歸模型,用以對人工評分進行預測[15-16]。
采用動態分析方法的好處在于其易于實現,并且適用于解空間開放的問題。但是動態分析要求待測程序通過編譯,無法解決無限循環的問題,會造成分析過程中斷,更重要的是,動態分析無法判斷程序是否真正實現了任務需求,也很難為學習者提供有效的支持。而靜態方法可以支持對錯誤程序的評估,且可以檢測出剽竊和投機取巧的現象。然而,這種評估方法也存在局限性,除了需要更多的專業知識以外,其評估結果依賴于模板程序和分析方法的選擇。當程序越復雜,解空間越大的時候,模板程序的設計難度越高,相似性比較難度也隨之激增。
因此許多研究考慮動態與靜態分析相結合,通過靜態分析解決編譯和運行失敗以及可解釋性問題,通過動態分析彌補解空間龐大導致的模板程序設計不全面的問題。
現有研究主要是通過分析學生編程產生的日志文件,或者通過一定粒度的代碼快照,分析學生在編程過程中的某些編程行為,從這些編程行為中提取可量化的特征指標,建立模型,來預測學生的表現或者根據某一屬性對學生進行分類。其編程行為主要分為兩類:
(1)基于擊鍵(Keystroke)的編程行為研究。Thomas[17]表明,編程者會將注意力集中于思考解決方法上,從敲擊一個單詞的角度出發,編程者的打字模式是不受影響的。所以許多研究都在基于單詞水平研究擊鍵行為于編程能力之間的關系,如文獻[18]中作者通過細粒度的代碼快照的方式記錄學生的兩個鍵敲擊的延遲時間,將字符類型分為5個類,如表1所示;將兩字符(Bigraph)之間的關系分為三大類,如表2所示。

表1 按鍵類型

表2 字符之間的關系分類
目前基于擊鍵的研究大多止于底層行為,即主要是基于鍵敲擊延遲、強度、持續時間、Bigraph、Trigraph等原始數據的特征。但編程能力更多是體現在各種底層行為的組合運用中,因此僅僅研究底層的編程行為是遠遠不夠的,其能夠反映的編程能力的信息十分有限,應從這些底層行為中挖掘出高階的編程行為來進行建模。
(2)基于日志(Log Data)的編程行為研究。編程者在編程過程中反復進行的代碼編譯和編輯操作。大量實證研究也表明,日志文件可以十分準確地表達編程者編譯和調試的熟練度,而編譯和調試能力的強弱會影響編程者編譯錯誤的個數和類型,從而影響最終的考核結果[19-20]。
如文獻[21]中作者通過日志文件收集學生在編程過程中產生的四種數據:編譯、運行、代碼編輯以及提示使用,根據編譯和使用提示的次數以及先后順序,給學生在該編程任務上的表現評分,根據一段時間多次任務的表現評分軌跡,預測學生是否能夠順利通過課程;文獻[22]中作者通過日志文件中的對同一文件的連續編譯的行為,根據編譯是否成功,錯誤信息,錯誤類型,錯誤行以及編輯時間等特征預測學生的編程能力;文獻[23]中作者選擇基于Web的開源編輯器Cloud-Coder作為開發平臺,通過日志文件收集學生的編程過程中產生的三種數據:編譯、運行和代碼編輯。研究學生編譯產生的錯誤數量,錯誤類型,錯誤位置以及編輯位置等特征與編程結果的關系。
基于日志的研究在某種程度上確實可以很好地反映學生的編譯調試行為與編程能力之間的關系,包含了很多高階的編程行為,與編程能力的相關性也更強。但是,它依然只是編程過程中的一部分,不能代表編程過程中的所有行為,因而也無法準確表示編程能力的強弱;此外,基于日志的編譯調試行為是廣義上的編程行為,只知道最后一次的編輯結果,而兩次編譯之間的其他行為無法記錄。因此準確地說,基于日志的方法不能記錄完整的編譯調試行為。
通過對現有研究的總結分析,目前對編程能力的評估仍然存在以下幾點問題值得深入研究和改進:
(1)基于理論以及實證研究提出一種標準的編程能力結構,對學生編程能力的全面定義,以促進編程能力自動化評估的發展。無論是基于產物還是基于行為的編程能力評估,研究者并未對編程能力進行標準化定義,這造成評估人員對能力的主觀因素直接影響實驗結果,此外,由于缺乏統一的能力結構定義,自動化評估方面的研究依然具有主觀性。
(2)建立一個編程行為集合,記錄編程過程中產生的所有編程行為,通過集合評估學生的編程能力,如圖2所示。現有研究中,基于產物的評估模型丟失了未能傳播到代碼中的行為,基于擊鍵的編程行為特征選取大多基于底層,如鍵敲擊延遲、強度、持續時間等,會丟失部分語義信息;基于日志的編程行為直接記錄上層行為,如編譯、運行、調試等,丟失了部分底層數據。上述方法均存在行為丟失的現象,所以建立一個編程行為集合是有必要的。

圖2 基于編程行為的理想能力框架
(3)對底層編程行為集合進行抽象,獲得高層的行為模式,建立編程行為與編程能力之間的映射關系模型,如圖2所示。基于編程行為的研究中,高層行為特征包含更豐富的語義信息,其實驗結果更具有價值。