文/謝偉增 金振乾
各種程序設計課程是高校理工科類學生的必修課程。這些課程不僅使學生的邏輯分析能力、程序設計能力得到訓練,還為后續(xù)的各種與編程有關的專業(yè)課程奠定了學習基礎。目前學習程序設計最常用的方式是通過集成開發(fā)環(huán)境IDE。無論用戶使用何種操作系統(tǒng),都有支持該平臺的集成開發(fā)環(huán)境平臺可供使用。諸如Windows平臺下有微軟公司開發(fā)的Visual Studio,MacOS平臺下有蘋果公司開發(fā)的Xcode,另外還有一些跨平臺開發(fā)環(huán)境如Eclipse、Apache NetBeans和IntelliJ IDEA等等。這些IDE集成了編輯、編譯和調試等實用且強大的功能,適用于各種桌面環(huán)境,但是通常配置也比較復雜,而且往往還有版權方面的限制,使用成本較高。而另一方面,隨著移動通信網絡的迅猛發(fā)展,各種移動通信設備大量普及,無線網絡全面覆蓋,使得幾乎人人都可以通過無線寬帶網絡隨時聯網,始終在線。如果把這個途徑用于程序設計的實踐學習,使學生能夠通過智能手機、平板電腦等各種聯網設備訪問在線編譯器平臺,就能突破時間、空間的限制,以及軟件、硬件方面的約束,充分利用“碎片”時間,通過瀏覽器訪問在線編譯器,完成程序的編輯、編譯等任務。
在線編譯器通常使用瀏覽器/服務器的工作模式,將程序編譯和運行的主要功能放在服務器端,客戶端無需安裝任何開發(fā)環(huán)境和編譯器軟件,直接通過瀏覽器打開Web頁面與服務器進行交互,實現程序編寫、編譯及執(zhí)行的全部過程。這樣不僅避免了在客戶端設備上安裝和配置傳統(tǒng)編譯環(huán)境的麻煩,也擺脫了對客戶端設備類型和性能的限制?;谶@些優(yōu)點,在線編譯器的開發(fā)和應用得到不斷地擴展。目前已有的在線編譯器有多種不同的實現類型,各種類型也都存在一些不足,主要表現在:界面不簡潔,支持編程語言種類少;傳統(tǒng)的物理服務器在部署、資源分配、可靠性等的不足與限制;編寫時無感應顯示框,不能高亮顯示代碼等方面。
因此,我們設計了一個基于Browser/Server模式的在線編譯器,在前端頁面實現了設備適配,允許用戶通過各種網絡終端設備訪問,在服務器端實現了源程序文檔管理、后臺編譯和前后臺信息交互的功能,提供穩(wěn)定的多用戶在線編譯服務。
開發(fā)過程中所選擇的集成開發(fā)環(huán)境為JetBrains公司的產品IntelliJ IDEA。作為目前最主流的Java集成開發(fā)環(huán)境之一,IntelliJ IDEA具備強大的靜態(tài)代碼分析和人機工程學設計,能夠顯著提高開發(fā)人員的生產力,而且還有基于Apache 2.0開放式授權的社區(qū)版本可供使用。IntelliJ IDEA原生支持maven,可進行高級項目管理,實現快速開發(fā)。在開發(fā)環(huán)境中完成項目設計和調試以后,將其部署到服務器上就可以正常訪問了。
編譯服務器是確保在線編譯功能得以實現的核心環(huán)節(jié),既要具備高度的穩(wěn)定性和快速的反應能力,又要能夠支持大量的并發(fā)連接,因此選擇以高性能、高穩(wěn)定性著稱的Linux系統(tǒng),各個主流發(fā)行版均可正常運行,如Debian,Ubuntu和CentOS等。應用軟件方面,采用成熟的OpenJDK 8,Apache Tomcat 8.5,并使用Maria DB 10作為后臺數據庫,為提高并發(fā)能力,還提高了數據庫連接池技術。該配置穩(wěn)定可靠,成本低廉,性能較好。得益于這些軟件的跨平臺能力,同樣的系統(tǒng)也可以運行在Windows平臺上,提高了部署的便捷性。
在線編譯器的應用把編譯和運行放到服務器上進行,消除了在客戶端設備上安裝編譯環(huán)境的需求。但是要實現在線編譯,有兩個核心問題必須要解決:一是如何把用戶在網頁上輸入的源程序代碼交給服務器進行編譯執(zhí)行;二是如何將程序的運行結果或編譯錯誤信息在網頁上輸出。針對這些關鍵問題,我們采用了以下方式來解決。
目前常用的Java語言動態(tài)編譯的實現方案主要有:
(1)使用JavaCompiler接口來實現Java源程序的動態(tài)編譯。
(2)通過StandardJavaFileManager類實現Java源程序動態(tài)編譯。
(3)從內存中動態(tài)編譯Java程序。
這些方式或者缺乏靈活性并效率較低,或者不符合系統(tǒng)需求,或者依賴于某個具體的Java類的版本和方法。因此我們采用了直接生成Runtime對象,并通過Runtime對象生成調用complie命令或run命令的相關進程,實現在服務器端編譯和運行Java程序的核心功能。
在調用complie命令或run命令時,先判斷服務器端操作系統(tǒng)的類型,然后根據類型構建相應的編譯命令行和運行命令行(命令行中還需包含需要執(zhí)行的Java程序的代碼路徑及主類名稱)。首先通過調用相關方法進行編譯操作,編譯過程如果發(fā)現錯誤則返回錯誤信息,如果編譯成功則繼續(xù)調用相關方法進行運行操作,并返回運行結果。核心代碼如下所示:
圖1:程序代碼編輯及運行界面
在編譯和運行Java源程序代碼時,可能會產生兩種信息,一種是運行結果輸出,一種是錯誤信息輸出,需要對這兩種信息都進行捕捉。所以在相關的方法中,我們創(chuàng)建了兩個輸入流,一個用于連接運行結果輸出,另一個用于連接錯誤信息輸出。但一般情況下,這兩種信息不會同時出現,程序正確執(zhí)行時會輸出運行結果,程序執(zhí)行失敗時會輸出錯誤信息。為了方便處理,我們捕捉這兩種信息,但合并到一個字符串對象中一同處理。在運行編譯命令時,如果程序沒有語法問題,不會有任何信息輸出,輸入流不會捕捉到任何信息;如果程序有語法問題,會輸出編譯錯誤或警告信息,輸入流也會捕捉到錯誤或警告信息。因此,如果編譯沒有出錯,捕捉到的信息對象為空,則可以繼續(xù)執(zhí)行運行代碼的命令。如果編譯出錯,則到此結束,將捕捉到的編譯錯誤信息返回頁面顯示。
為了方便用戶直接在Web頁面上編輯程序,直接在頁面代碼中集成了名為CodeMirror的代碼編輯器組件。CodeMirror是一個基于MIT授權的開源項目,是基于JavaScript實現的通用文本編輯器,專門用于源代碼編輯,并附帶了許多能實現高級編輯功能的語言模式和插件,如代碼自動補齊、代碼著色、代碼折疊、快捷鍵綁定等。為了簡化代碼并節(jié)約服務器資源,程序中僅設置了必要的幾項功能和有限的幾種主題配色方案。實際上CodeMirror支持超過100種編程語言和許多種主題配色方案,這也為項目將來的功能擴展提供了有力的支撐。
前端開發(fā)過程中使用了完全開源的Bootstrap前端開發(fā)框架,實現了基本的響應式布局,使得用戶注冊、登錄,源代碼編輯等各個頁面都能夠有效適配手機、平板等各種移動終端設備和PC等桌面終端設備。響應式交互頁面具備一般的靜態(tài)頁面所沒有的許多優(yōu)點,既能避免針對不同設備的重復開發(fā),有效節(jié)約成本,又能確保顯示的內容適應不同的平臺和不同的設備,保障用戶體驗。在線編譯器平臺本身的功能要求決定了其前端的頁面結構設計無需過于復雜,但必須保證在各種終端設備上都能被良好地呈現,因此在線編譯器的前端開發(fā)也更適合響應式頁面。
由于本項目在運行過程中面對的是大批量的學生,每名學生都有可能有多個源程序代碼需要管理,因此在后臺進行用戶認證、用戶信息提示以及用戶源代碼文檔處理的時候,我們引入了免費的、基于Apache許可證2.0版本發(fā)布的FreeMaker。FreeMaker是一種模版引擎,模版的編寫是通過專用的FreeMaker模版語言(FTL)實現的。通過這個引擎,可以在代碼中指定模版和需要變動的數據集,然后就可以通過引擎自動生成包含相應數據的文本內容。
圖2:移動設備端程序輸入界面
用戶界面是用戶與在線編譯器進行交互的接口,既要具備必要的功能,又要足夠簡潔,避免增加用戶的學習負擔。在線編譯器的重點功能是實現源代碼的提交和修改,并獲得程序的編譯錯誤信息和運行結果。對這些信息的交互和功能的實現做到集中展示和合理布局才能提供更好的用戶體驗,提高用戶使用在線編譯器的效率。因此,我們的設計思路是在用戶登錄到系統(tǒng)之后,所有的源程序選擇、源代碼編輯、執(zhí)行編譯運行功能、查看運行結果、查看編譯錯誤信息等主要功能都呈現在一個頁面中,用戶無需在多個頁面中來回跳轉,也無需頻繁刷新頁面以顯示信息。
這個布局共有三個區(qū)域,覆蓋了用戶的源代碼的管理、提交、修改、運行、查看輸出結果的所有功能需求。當用戶登錄到在線編譯器系統(tǒng)后,在左側源代碼文件列表區(qū)域可顯示該用戶已經編制過的所有源代碼程序列表,通過點擊列表中某項,則該項對應的源代碼自動呈現到源代碼提交/編輯區(qū)域,用戶可對源代碼內容進行審核與編輯;編輯完成后,通過點擊“提交運行”按鈕,將編輯區(qū)域的源代碼提交到編譯服務器進行保存,然后由服務器端調用相關代碼進行編譯操作,如果編譯不成功,則獲取編譯錯誤信息并輸出到編譯錯誤信息顯示區(qū)域;如果編譯成功,則繼續(xù)調用相關代碼執(zhí)行程序并獲取程序運行結果,然后將運行結果輸出到程序運行結果顯示區(qū)域。
如圖1所示,當以合法用戶身份登錄以后,在左側的現有源代碼程序列表中選擇一個已經存在的源程序,其源代碼自動出現在右上側的源代碼編輯區(qū)域;圖1中所顯示的一段完整的Java源程序代碼,該程序代碼沒有任何語法錯誤,因此當用戶點擊“提交運行”按鈕之后,程序的運行結果將會自動顯示在右下側的程序運行結果顯示區(qū)域。
通過手機、平板電腦等移動設備訪問編譯服務器,并以合法用戶身份登錄后,也可以正常進行源代碼提交和編輯,并顯示程序運行結果或編譯錯誤提示信息等功能。需要注意的是,在移動設備上訪問在線編譯器的時候,受限于移動設備顯示屏幕的面積大小,這些元素無法同時顯示在屏幕上,但是可以通過上下滾動的方式進行查看。圖2所示的是在手機上進行源代碼輸入的界面,由于手機屏幕的面積有限,而虛擬鍵盤又遮擋了小部分屏幕,留給用戶的顯示面積并不算多,用戶能夠同時看到的源代碼也不多。雖然可以通過滾動的方式顯示位于編輯區(qū)域各個位置的代碼,但是用戶體驗始終不夠完美。因此在移動設備上訪問在線編譯器應主要以源代碼的提交、審閱和微量修改為主,同時輔以程序編譯和運行功能的實現,不適宜大量源代碼的持續(xù)輸入。不過由于智能手機等移動設備在學生的學習和生活當中占據了大量的時間,可以以智能手機訪問在線編譯器進行網絡在線編程,對分散的知識點及小規(guī)模的程序進行編程驗證,然后在實驗課上側重對綜合性及創(chuàng)新性的程序進行調試。該模式打破了傳統(tǒng)實驗室上機實踐在時間與空間上的限制,使編程實踐貫穿于課程教學的全過程,實現了信息技術與教學的有效融合。這種靈活多樣的編程實踐環(huán)境確實能使學生的編程能力得到提升。
在線編譯器在計算機編程語言教學過程中有很大的應用需求,根據我們在2018級計算機應用技術專業(yè)兩個教學班級進行對照教學(一個班級按照常規(guī)的教學實踐環(huán)境進行編程訓練,對照班級將常規(guī)的教學實踐與在線編譯器的編程練習相結合)的結果表明,在線編譯器的使用能夠有效延長學生進行編程訓練的時間,在線編程作為常規(guī)的集成開發(fā)環(huán)境編程的有益補充,為學生提供了多樣化的編程實踐平臺,有力提高了學生自主學習的積極性和主動性。
在實踐當中我們也發(fā)現了這個在線編譯器目前存在的一些問題,例如對程序邏輯錯誤的檢測缺乏必要的手段;程序執(zhí)行過程中缺乏必要的交互;編譯錯誤信息在源代碼編輯窗口的定位功能尚未實現。這些問題都會在后續(xù)的版本更新中逐步予以解決。將來該系統(tǒng)還可以擴展為在線學習平臺,不僅實現在線編譯的功能,還能夠實現編程作業(yè)的提交和審核、平臺使用情況數據的采集和統(tǒng)計、學習進度和學習問題反饋、代碼分享和編程協作等功能,以更低的成本和更高的靈活性,在編程語言教學領域發(fā)揮更大的作用。