陳馨慧
(南方科技大學計算機科學與工程系,廣東深圳 518055)
隨著開源軟件與開源代碼托管平臺如GitHub的蓬勃發展,國內外許多高校已開始將開源項目應用于軟件工程課程實踐教學中。然而,現有課程還存在很多不足:首先,由于編程經驗與背景的限制,學生對開源項目的選擇自由度過小;其次,現有課程往往只關注特定軟件工程概念對開源項目所帶來的影響;再次,對開源項目不熟悉的學生往往會提交低質量代碼,被開源軟件維護人員拒收。同時,一些科技公司,如谷歌成功舉辦了多屆谷歌編程之夏(Google Summer of Code,GSoC)[1]和FindBugs“fixit”[2]等項目,以鼓勵學生為開源項目作出貢獻。本文借鑒這些成功的項目經驗,提出基于開源項目的“GitHub-OSS Fixit”課程作業,并對實施過程中所應用的教案以及學生對于該課程作業的反饋進行闡述。
在軟件工程教學方面,國外高校近年來提出了基于開源軟件的實踐教學模式[3-4],以培養學生“解決復雜工程問題”的能力。該方法在教學方面取得的成效較為顯著,但在學生對于開源社區的選擇自由度方面仍存在不足,目前暫無法大規模應用于超過100 名學生的軟件工程課程。基于開源軟件的實踐教學模式通常由任課教師指定幾個熟悉的開源軟件作為課程作業的基礎,使得學生無法自由選擇感興趣的開源軟件。此外,學生一般缺乏開發與修改大規模軟件項目代碼的經驗,無法系統性地學習如何參與開源社區,為其貢獻代碼。
企業為了推廣開源軟件,創辦了多個以鼓勵學生參與開源軟件為中心的項目,其中包括谷歌編程之夏和Find-Bugs“fixit”。由谷歌舉辦的谷歌編程之夏[1]項目,旨在鼓勵不同技術背景的學生參與開源社區,熟悉相關工作流程,利用暑假時間充分幫助他們鍛煉與提升代碼編寫能力。雖然該項目在鼓勵學生參與開源項目上取得了不錯的成效,但仍存在兩點不足:①有興趣參與該項目的學生必須通過耗時繁瑣的報名與選拔流程才能參與;②在開源項目選擇上,參與學生僅能選擇一些已提前報名參與GSoC的開源機構且只能選擇該機構指定的題目。同時,為了提升靜態分析工具FindBugs的質量,谷歌程序員組織了FindBugs“fixit”[2]。該活動主要基于用戶所提交的缺陷報告,對Findbugs的代碼進行修改,以修復用戶提出的缺陷,提升FindBugs 各方面的可靠性。
本文通過基于開源軟件項目的學期課程作業與基于軟件工程理念的教導自動化工具,進行教學實踐相關研究并提供實踐教學案例,以彌補現有方法的不足。
為了鼓勵學生參與開源項目,筆者將開源項目融入軟件工程的小組課程項目中。小組課程作業共分為3 個方面:項目建議書、項目進展報告和結題報告。如圖1 所示,在共16 周的軟件工程課上,該課程作業貫穿課程全程共10周。在這3 個階段中,由于學生必須在項目建議書上選擇自己感興趣的開源軟件與該軟件所存在的缺陷相關課程內容,因此該階段為整個課程作業的核心部分。

Fig.1 Time schedule for team-based project assignment圖1 小組課程作業時間安排
在項目建議書階段,學生需編寫4 個主要模塊:①開源軟件選擇;②課程作業題目選擇;③課程項目整體規劃;④小組成員角色擬定。在進展報告階段,學生需要對課程作業進展進行匯報,詳細匯報內容包括不同靜態分析工具的分析報告以及有效測試用例數量與代碼覆蓋率,體現出所編寫代碼的質量與規范性。在結題報告階段,學生需要匯報:①整個學期所修復的開源軟件缺陷的數量及所提交補丁的數量;②所選擇缺陷的重要性與危害程度;③總結所學習到的軟件工程知識與相關知識在項目中的應用;④未來將會繼續改進的各類下一步工作。
由于基于Java的程序設計課是軟件工程課的先修課程,筆者認為學生已經掌握了編寫基本Java 程序的技能,同時也因此限定了學生必須統一選擇基于Java 編程語言的開源軟件項目,但是GitHub 開源倉庫上仍擁有上萬個基于Java的開源軟件項目供學生選擇。為了解決開源軟件的選擇問題,筆者為學生提供了如何編寫項目建議書的詳細指導與說明。
在開源軟件選擇上,提供以下選擇基準供學生參考:①易用性:每名小組成員需要成功編譯所選擇的Java 項目。如果成員所選擇的是安卓應用,該應用程序需要在手機或者安卓系統模擬器上成功運行;②現有的測試用例:該項目需要有一些測試用例,以方便檢查修改代碼后引入的回歸錯誤;③受歡迎程度:該軟件在GitHub 需要擁有超過100顆星(stars);④開源項目近期維護積極性程度:該軟件項目需要擁有近一年的代碼提交記錄(commit history);⑤尚未解決的缺陷報告(GitHub Issues)數量:該軟件項目需要擁有至少15 個未解決(open)的缺陷報告,所選擇的類型需以修復缺陷或者滿足用戶需求為目的,不能是回答用戶問題、僅涉及文檔修正或者僅優化測試用例;⑥貢獻指南:需檢查該開源項目是否有提供任何貢獻指南(contribution guidelines),如有,附上指南鏈接。
以上基準皆用于指導學生選擇一些受歡迎且有一群積極維護開發者的開源軟件,選擇受歡迎的開源軟件可以確保開源軟件的普及性。筆者認為,積極維護開源軟件的開發者可視為學生的第二導師,通過審查學生所提交的補丁,指導學生如何提交高質量并符合該開源社區規范(符合貢獻指南標準)的代碼。
當學生確定了開源軟件后,需選擇該軟件項目上未解決(open)的缺陷。為學生提供以下選擇基準:
(1)缺陷重要性。所選擇的缺陷需要有一定的重要性,例如,一些重要的Issue 會被開發者添加“供選擇”(“up for grab”)或者“尋求幫助”(“help wanted”)等標記。同時,大多數開源項目會在“貢獻”(“contribute”)鏈接底下列出適合初學者修復的缺陷。
(2)無提交記錄。該缺陷報告(Issue)中不能有已修復該缺陷的提交記錄(commit history),要求不能選擇已被開發者或者其他用戶已經解決過的缺陷。
(3)缺陷可被復現。學生需要為該缺陷編寫至少一個測試用例,確保該缺陷的可復現性,如果不了解該缺陷所提出的具體細節,請不要選擇該缺陷。
(4)預計需要增加或修改的代碼行數。學生需要選擇相關項目中具有一定修復難度的缺陷,不能被輕易地解決。通常,筆者要求學生解決該缺陷需要增加或者修改至少10 行代碼。
(5)預計所需使用的時間。學生所選擇的缺陷如要修復需要花費一定時間。預計所花費時間至少是一到兩周。
以上基準是為了保證學生選擇既重要又需編寫大量代碼進行修復的缺陷,確保每名學生花費與其他學生相似的時間(以確保公平性),完成該課程作業。
為了培養學生的任務規劃能力,筆者讓學生選擇并規劃整個學期的課程作業任務。學生需根據以上提到的“開源軟件的題目選擇基準”,選擇5~10 個備選缺陷,最終所選擇的缺陷數量取決于小組成員人數、缺陷難度和預計修復缺陷的時間。為了確保每個學生在課程作業中用時相當,筆者指定每名成員預計該學期共花費至少6 周的時間。由于學生在課程項目規劃方面缺乏經驗,筆者為學生提供了課程任務規劃表的樣例。表1 為學生需提交的規劃表,其中包括缺陷的鏈接、類型、預計修復時間、負責修復缺陷的人數與預計的難度評級。由于極限編程提倡結對編程(兩名程序員并坐在同一臺電腦前,面對同一個顯示器,使用同一個鍵盤、同一個鼠標一起編寫程序),筆者限制每個缺陷的修復人數不超過兩人,讓學生可以自主地選擇是否進行結對編程。

Table 1 Iteration planning for GitHub issues表1 GitHub 問題的迭代規劃
由于學生可能會選擇修復一些簡單且無需編寫代碼的缺陷(例如潤色開源項目文檔和增加測試用例等),筆者在說明中表明只能選擇缺陷或者功能需求(feature request)類型的Issue。在課程作業的最終目標說明上,筆者也提到學生需確保每名成員該學期至少修復兩個缺陷(每個階段修復一個缺陷)。此外,筆者也強調學生應該根據預計難度,先修復一些因為簡單可能很快被其他人修復的缺陷,以免被別人捷足先登,同時也可以避免提交重復的補丁。
為了培養學生團隊精神并鼓勵學生互相幫助解決作業上遇到的問題,該課程作業通過學生自由組隊的方式進行,通常一個完成作業的隊伍由5~6 名學生組隊完成。為了確保學生所提交代碼的質量,讓學生在項目建議書上選擇每名小組成員所扮演的角色并附上表2。

Table 2 Roles of group members表2 小組成員所扮演的角色
如表2 所示,除負責編寫代碼的開發者外,還添加了一些重要的軟件團隊角色,包括設計師、測試員及開發與文檔維護者,目的在于確保軟件開發中各重要部分(如軟件測試、軟件設計、軟件文檔等)都有專人參與并監督其進度。同時,筆者也鼓勵學生在不同階段嘗試扮演不同的角色,以提高對軟件開發過程中不同角色的認知。
南方科技大學的軟件工程課程以極限編程方法論為基礎,對多個涉及軟件開發與維護的重要概念進行教學。該課程共有16 周,每周有2 小時的理論課與2 小時的實驗課。軟件工程課程教案如表3 所示。

Table 3 Lesson plan for Software Engineering course表3 軟件工程課程教案
如表3 所示,軟件工程課程通過在理論課上灌輸版本控制、程序分析、軟件測試與持續集成的理念,加強學生對軟件開發與維護的理解。同時,筆者針對每個重要理念,設計相關的實踐練習題,將一些自動化工具(如單元測試工具JUnit、變異測試工具PIT 和靜態分析工具PMD 等)作為實踐練習題的基礎,目的在于教導學生如何應用自動化工具分析與維護代碼,從而保證代碼質量,降低軟件維護時間與成本。
同伴輔導(Peer Tutoring)指一個有經驗的學生在教師的適當指導下去幫助另一個或者多個年齡相仿的學生去學習某個技能或概念。目前,同伴輔導已廣泛應用于各類教學活動。由于大部分學生對開源項目不熟悉且對自己的編程能力不自信,筆者使用同伴輔導的方式,通過借鑒學長學姐的開源項目經驗,以建立學生的自信心。筆者分別通過兩種不同的方式進行同伴輔導:①微信采訪;②分享學長學姐錄制的視頻。同伴輔導的主題為“如何從零開始參與開源項目”,在微信采訪環節,筆者采訪了軟件工程課程的前助教王同學,該生曾為知名開源項目Kubernetes貢獻過代碼。他提到以下幾個方面:①熟悉Git 操作及GitHub的工作流程;②使用某個開源軟件,然后發現不足;③參與開源軟件維護,幫助開發者解決問題。在學長錄制的視頻方面,筆者邀請曾上過軟件工程和軟件測試課的徐同學錄制視頻。該生在所錄制的視頻中[8]展現了從零開始參與開源項目的親身經歷:①在開源安卓應用程序上尋找合適的缺陷;②基于測試驅動開發理念,準備用于復現缺陷的測試用例;③在開源安卓應用程序上進行缺陷的細粒度分析;④編寫詳細的缺陷報告;⑤提交修復該缺陷的補丁;⑥該補丁被開發者接受并歸入開源項目。
本文從兩方面評估了基于開源項目的課程作業對學生的影響:①學生對該課程作業的評價;②學生對開源項目的貢獻度。在評估學生對該課程作業的總體評價方面,采用李克特五點量表(選項包括:1.強烈反對;2.反對;3.不贊同也不反對;4.贊同;5.強烈贊同),調查學生對于“總的來說,我會推薦基于開源軟件的課程作業為日后的課程項目”問題的想法。圖2 顯示了學生對課程作業的評價,大部分學生(82%)強烈贊同或贊同基于開源軟件的課程作業并且會推薦該項目為日后的課程項目。

Fig.2 Students’feedback for team-based project assignment圖2 學生對課程作業的評價
此外,在評估學生對開源項目的貢獻度上,本文收集了學生所提交的補丁數量和補丁被開發者合入開源代碼庫的數量。該課程總共有154 名學生,在該學期結束前共為24 個不同的開源軟件提交了總計214 個補丁,其中有93個補丁被開發者接受并合入開源代碼庫,有46 個缺陷報告被開發者標記為已解決。根據收集到的這些數據,該項目在鼓勵學生為開源項目作出貢獻方面效果突出。
本文提出了基于開源軟件的課程作業并詳細闡述了課程作業的說明及實踐教學案例。本次共有154 名學生參與軟件工程課程學習,共為各大開源軟件提交了214 個補丁且大部分補丁都被開發者接受并合入開源代碼庫。此外,經統計后的評價結果表明,學生對于基于開源軟件的課程項目大致上表示認可并愿意推薦為日后的課程作業。然而,在學生所提交的補丁中有部分仍未被開發者接受,這些補丁的代碼質量仍有待提升,后續將進一步加強代碼規范性與可讀性的教學環節,以提升學生所提交補丁的質量,達到更好的授課效果。整體而言,基于開源軟件的課程項目在提升軟件工程實踐能力上成效顯著。詳細的教學實踐實施方法可以參見相關教材[9],包括:課件、課程作業及詳細說明與學生錄制的視頻等。在今后教學工作中,還將引入更多前沿的軟件工程技術與工具,進一步提升教學內容的新穎性與多樣化,增強學生的理論基礎并提升實踐動手能力。