張 慶, 管錦亮
(安徽建筑大學(xué) 網(wǎng)絡(luò)信息中心, 合肥 230022)
在程序設(shè)計(jì)教學(xué)中,學(xué)生不僅要掌握程序靜態(tài)結(jié)構(gòu),還要理解程序執(zhí)行的動(dòng)態(tài)過(guò)程。如果機(jī)械地學(xué)習(xí)一門(mén)語(yǔ)言的語(yǔ)法和規(guī)范,學(xué)生很難形成“將實(shí)際問(wèn)題抽象成程序代碼”的計(jì)算思維能力??梢暬虒W(xué)方法通過(guò)為學(xué)生提供直觀的模型圖,簡(jiǎn)化了對(duì)程序算法的理解,極大提高教學(xué)效率。
然而目前缺少一款高效的、可交互的可視化教學(xué)的輔助工具軟件,使得在進(jìn)行可視化教學(xué)時(shí)大多采用PPT、Flash等工具來(lái)描述模型圖,而這些工具不支持將“模型圖”轉(zhuǎn)換到“代碼”的功能,也不具備交互性特性。桌面應(yīng)用RAPTOR是一款可交互的可視化教學(xué)工具[1-4],但存在編程模型不易發(fā)布共享的問(wèn)題,限制了在師生間溝通和討論問(wèn)題的效果。
本文探討設(shè)計(jì)和實(shí)現(xiàn)HTML5架構(gòu)的可視化教學(xué)平臺(tái)的方法,講解如何實(shí)現(xiàn)流程圖模型的繪制展示,描述如何構(gòu)建解析模型并生成代碼等的功能模塊,詳細(xì)給出開(kāi)發(fā)平臺(tái)過(guò)程中涉及的相關(guān)技術(shù)和方法。
HTML5的Canvas是非常實(shí)用的繪圖控件,用戶不僅可以在Canvas畫(huà)布上繪制各種圖形,也可以制作絢麗的動(dòng)畫(huà)。在頁(yè)面中添加一個(gè)〈canvas〉標(biāo)簽,即可提供一個(gè)強(qiáng)大繪圖區(qū)域[5-6]。流程圖是可視化教學(xué)中最常用的算法模型,是由節(jié)點(diǎn)和連線構(gòu)成。Canvas中的context封裝了很多繪圖功能的對(duì)象,通過(guò)調(diào)用fillRect、lineTo方法,可以方便地繪制出節(jié)點(diǎn)和線條,實(shí)現(xiàn)流程圖模型的繪制。HTML5可現(xiàn)強(qiáng)大的動(dòng)畫(huà)效果,通過(guò)Canvas結(jié)合js的方式模擬出程序執(zhí)行的動(dòng)態(tài)效果。
JSON是一種輕量級(jí)的數(shù)據(jù)交換格式,為純文本格式,支持嵌套結(jié)構(gòu)與數(shù)組。相比與XML,JSON描述數(shù)據(jù)模型時(shí),具有數(shù)據(jù)格式簡(jiǎn)單、易于讀寫(xiě)和解析、支持多種語(yǔ)言、占用帶寬低、傳輸效率高的優(yōu)點(diǎn)??梢暬虒W(xué)平臺(tái)需要利用JSON描述并持久化保存流程圖模型中節(jié)點(diǎn)和連線的關(guān)系,轉(zhuǎn)換為有向圖的形式,并最終通過(guò)解析成為指定語(yǔ)言的源代碼(注: 以解析為C語(yǔ)言的源代碼實(shí)例)。
在生成源代碼后,GCC命令可直接編譯、匯編、鏈接出可執(zhí)行程序。執(zhí)行程序時(shí),Java的Runtime類可將操作系統(tǒng)下的命令封裝為JVM下的進(jìn)程,在Web服務(wù)中加載Servlet,并與頁(yè)面中的WebSocket類通信,將程序編譯和執(zhí)行時(shí)的輸入和輸出信息與基于Web頁(yè)面的前臺(tái)程序關(guān)聯(lián)起來(lái)。本文將詳細(xì)討論如何用Runtime類,將編譯、執(zhí)行環(huán)境封裝為可與Web平臺(tái)交互的進(jìn)程,以及如何利用IO流接收頁(yè)面的輸入信息,及推送輸出信息至頁(yè)面的過(guò)程。
WebSocket協(xié)議是基于TCP的一種新的網(wǎng)絡(luò)協(xié)議,它實(shí)現(xiàn)了瀏覽器與服務(wù)器全雙工通信,允許Web服務(wù)器主動(dòng)發(fā)送信息給瀏覽器客戶端。平臺(tái)的服務(wù)端Runtime類封裝了編譯命令的輸入和輸出流,而WebSocket則負(fù)責(zé)實(shí)現(xiàn)從瀏覽器中獲取輸入數(shù)據(jù),提交給服務(wù)端Runtime封裝的編譯環(huán)境,再將編譯和運(yùn)行的輸出流提交到瀏覽器的頁(yè)面上,實(shí)現(xiàn)編譯環(huán)境Web平臺(tái)的實(shí)時(shí)交互。
整個(gè)可視化教學(xué)平臺(tái)是一個(gè)描述流程圖模型、演示流程圖模型的工具,為了提高學(xué)習(xí)者的抽象思維能力,在“實(shí)際問(wèn)題”和“程序代碼”之間增加一層更為直觀的“可視模型”,同時(shí)也提供了從“模型”生成“代碼”的模塊。輔助學(xué)生形成一套完整的“問(wèn)題-模型-代碼”思維鏈條[7-9]。
根據(jù)模型設(shè)計(jì)和演示的原則,設(shè)計(jì)了如圖1所示的系統(tǒng)架構(gòu), 整個(gè)系統(tǒng)分為2層9個(gè)模塊,客戶端主要負(fù)責(zé)與用戶交互,實(shí)現(xiàn)模型繪制、動(dòng)畫(huà)演示、代碼和運(yùn)行結(jié)果顯示的功能。服務(wù)端負(fù)責(zé)模型的保存,解析,及源代碼的生成、編譯和運(yùn)行控制功能。
客戶端是交互的核心區(qū)域,模型繪制和模型傳輸都依賴于JSON模型的描述,HTML5中提供了一套完整的2D圖形繪制組件,可將流程圖中的節(jié)點(diǎn)與JSON對(duì)象關(guān)聯(lián)起來(lái)。
當(dāng)提交流程圖模型后,JSON模型以.flow文件的形式持久化的保存與后臺(tái)服務(wù)中,生成源代碼時(shí),模型被提交至Web服務(wù)中的模型轉(zhuǎn)換模塊處理,解析模塊將JSON對(duì)象與程序中標(biāo)準(zhǔn)語(yǔ)句元素關(guān)聯(lián)起來(lái),將這些解析后的語(yǔ)句元素填寫(xiě)入基本程序框架(開(kāi)始-輸入-處理-輸出-結(jié)束),生成源代碼。
Runtime類可接管系統(tǒng)程序的輸入和輸出,封裝后的編譯環(huán)境可以將源代碼的編譯結(jié)果以流的形式推送給控制臺(tái)組件顯示出來(lái)。如果編譯成功,則生成的可執(zhí)行程序也用Runtime類封裝,將執(zhí)行結(jié)果同樣以流的形式推送給控制臺(tái)。
圖1 可視化編程平臺(tái)系統(tǒng)架構(gòu)Fig.1 The Architecture of Visual Programming Platform
整個(gè)平臺(tái)包含了流程圖繪制區(qū)、模擬執(zhí)行區(qū)、源碼生成區(qū)和控制臺(tái),如圖2所示。
(a)—界面設(shè)計(jì)圖; (b)繪圖界面效果圖2 可視化編程平臺(tái)界面Fig.2 The interface of visual programming platform
1) 流程圖繪制區(qū): 繪制流程圖模型,包括了繪圖工具箱、畫(huà)布(提供網(wǎng)格)、配置窗口。
2) 模擬執(zhí)行區(qū):可以按步驟自動(dòng)執(zhí)行和按步手動(dòng)執(zhí)行。通過(guò)節(jié)點(diǎn)依次獲取焦點(diǎn)的方式表示當(dāng)前執(zhí)行的語(yǔ)句,并在輸入時(shí)彈出輸入框,控制臺(tái)上同步顯示相關(guān)輸出信息。
3) 源碼生成區(qū): 可根據(jù)流程圖生成相關(guān)代碼,用戶可調(diào)整代碼,并編譯執(zhí)行,代碼可將執(zhí)行結(jié)果返回到控制臺(tái)上。
整個(gè)流程圖模型可以看做節(jié)點(diǎn)和連線,以及輔助的文本描述。節(jié)點(diǎn)區(qū)分為“開(kāi)始|結(jié)束”“語(yǔ)句框”“判斷框”。連線代表了語(yǔ)句處理的方向。描述模型的關(guān)鍵點(diǎn)需要用JSON格式來(lái)描述節(jié)點(diǎn)和連接,并保存為.flow模型文件。
1) 節(jié)點(diǎn)的JSON描述。描述節(jié)點(diǎn)主要包括外觀屬性和業(yè)務(wù)屬性。其中外觀屬性有形狀,坐標(biāo),大小,業(yè)務(wù)屬性有類別、偽代碼、說(shuō)明。因此節(jié)點(diǎn)的JSON表示可以如下:
node={id:“n0”,type:“input”,express:“score”,initValue: 0.0 prompt:“Please input score:”, src: “img/input.png”,x:100,y:100,w:100,h:100...}。
其中節(jié)點(diǎn)類別的type可以分為: input輸入、output輸出、set賦值、call調(diào)用、decision判定、empty空節(jié)點(diǎn)(用于連線匯聚);其輸入、賦值、調(diào)用時(shí)的變量類型,可根據(jù)具體輸入、賦值、調(diào)用時(shí)的常量或變量來(lái)決定變量名和數(shù)據(jù)類型;
2) 連線的JSON描述。連線描述了流程圖語(yǔ)句節(jié)點(diǎn)間的執(zhí)行次序,一條連線必須連接2個(gè)節(jié)點(diǎn),描述連線主要有線條標(biāo)記,起點(diǎn)、終點(diǎn)等信息。因此連線的JSON表示可以如下:
link={id:“l(fā)0”,type:“t_indicator”,from:“n0”,to:“n1”...}。
JSON模型的作用是建立起流程圖和程序代碼間的映射關(guān)系,參照表1流程圖節(jié)點(diǎn)→JSON對(duì)象→代碼元素的映射關(guān)系表。
表1 流程圖節(jié)點(diǎn)-JSON對(duì)象-代碼元素映射關(guān)系Tab.1 Relation of flow-chart’s node and JSON object and code unit
流程圖繪制主要依賴Canvas的使用,Canvas本質(zhì)上是一個(gè)容器,容納著各種圖元對(duì)象。繪圖模塊和JSON描述的節(jié)點(diǎn)和連線是聯(lián)動(dòng)的,每添加一個(gè)節(jié)點(diǎn)和連線會(huì)生成相應(yīng)的JSON模型代碼。要?jiǎng)?chuàng)建一套2D繪圖環(huán)境,主要包括2方面的基本功能:
1) 創(chuàng)建繪圖區(qū)域,在網(wǎng)頁(yè)中添加Canvas標(biāo)簽元素,即可獲得一個(gè)以左上角為坐標(biāo)原點(diǎn),X軸向右延伸,Y軸向下延伸的繪圖區(qū)域。然后獲取繪圖的上下文環(huán)境(Context)。 其中定上下文環(huán)境中定義著所有繪圖2D圖形的屬性和命令,各種繪圖操作都依賴著它。
var context=document.getElementById(“canvas”).getContext(“2d”);
2) 節(jié)點(diǎn)和連線的繪制,在流程圖中節(jié)點(diǎn)可以利用圖片效果展示,比直接使用繪制矩形命令更加簡(jiǎn)單和美觀,也方便實(shí)現(xiàn)節(jié)點(diǎn)的縮放、拖動(dòng)和動(dòng)畫(huà)效果展示。構(gòu)造節(jié)點(diǎn)需要先定義圖片對(duì)象var input_img=new Image(); 再加載圖片文件input_img.src=“img/input.png”; 這樣就可以在指定坐標(biāo)添加圖片對(duì)象context.drawImage(input_img,x,y,w,h);同時(shí)需要設(shè)定拖動(dòng)屬性draggable=“true”和拖動(dòng)事件ondragstart=“drag(event)”支持節(jié)點(diǎn)的拖動(dòng)。連線則利用context.moveTo(x1,y1)和context.lineTo(x2,y2)實(shí)現(xiàn)兩點(diǎn)間的線條繪制,90度折線則采用劃線函數(shù)組合實(shí)現(xiàn),最后以context.fill()/stroke()填充線條相關(guān)風(fēng)格。
流程圖的動(dòng)畫(huà)執(zhí)行分為自動(dòng)執(zhí)行和交互處理,自動(dòng)執(zhí)行可以通過(guò)setInterval(call(),時(shí)長(zhǎng))的函數(shù)設(shè)置每個(gè)節(jié)點(diǎn)執(zhí)行的間隔,call( )為自定義的js函數(shù),實(shí)現(xiàn)了當(dāng)前節(jié)點(diǎn)高亮顯示、代碼表達(dá)式解析、控制臺(tái)信息顯示、標(biāo)記下一個(gè)執(zhí)行節(jié)點(diǎn)的功能。當(dāng)需要交互時(shí)(如:輸入操作),則clearInterval暫停,彈出輸入框。當(dāng)調(diào)用包含算術(shù)表達(dá)式和邏輯表達(dá)式的節(jié)點(diǎn)時(shí),則將字符串的表達(dá)式轉(zhuǎn)換為js的表達(dá)式進(jìn)行計(jì)算和處理。
流程圖模型生成代碼的過(guò)程屬于軟件正向工程的范疇,需要解決模型結(jié)構(gòu)元素和源代碼間的映射問(wèn)題,即是由不同類型的節(jié)點(diǎn)和源代碼之間形成的映射關(guān)系表的管理,例如輸入和輸出節(jié)點(diǎn)可映射為scanf、printf語(yǔ)句,當(dāng)用戶輸入帶小數(shù)點(diǎn)的數(shù)值時(shí)可映射出雙精度變量定義語(yǔ)句等。將解析出JSON文件中節(jié)點(diǎn)元素并按照映射表生成相關(guān)代碼[10-11]。給出了有向圖強(qiáng)連通分量的識(shí)別算法可區(qū)分出判斷框節(jié)點(diǎn)屬于循環(huán)結(jié)構(gòu)或分支結(jié)構(gòu),如圖3所示。描述了包含(a)while和(b)do-while結(jié)構(gòu)的流程圖,轉(zhuǎn)換為相應(yīng)的有向圖, 并通過(guò)深度優(yōu)先搜索識(shí)別圖中是否存在強(qiáng)連通分量,如果存在強(qiáng)連通結(jié)構(gòu)則為循環(huán)結(jié)構(gòu),否則為判斷結(jié)構(gòu)。此外,分析連線的匯聚Empty節(jié)點(diǎn)(B)和判斷框節(jié)點(diǎn)(C)的前后關(guān)系識(shí)別出循環(huán)的種類。如果有向圖存在(B,C)連線為while循環(huán),如果存在(C,B)連線則為do-while循環(huán)。
(a)—while有向圖G中包含(B→C)分量; (b)—do-while有向圖G中包含(C→B)分量圖3 循環(huán)結(jié)構(gòu)對(duì)應(yīng)的有向圖強(qiáng)連通圖Fig.3 The strongly connected graph for cycle structure
在生成代碼后通過(guò)調(diào)用gcc命令編譯為可執(zhí)行文件(.out),例如:“gcc sc.c-o sc.out”。整個(gè)編譯過(guò)程可通過(guò)后臺(tái)Java的Runtime類加載為JVM下運(yùn)行的進(jìn)程。編譯后的可執(zhí)行文件也由Runtime類封裝調(diào)用,并通過(guò)捕獲輸入流、輸出流和錯(cuò)誤流的方式返回執(zhí)行情況。
整個(gè)過(guò)程分為3個(gè)步驟,如圖4所示。
圖4 集成C語(yǔ)言編譯和執(zhí)行模塊的架構(gòu)圖Fig.4 The Integrated Module for Compilation and Execution
首先通過(guò)Runtime調(diào)用可執(zhí)行文件,并捕獲了輸入和輸出流發(fā)布至Web服務(wù),通過(guò)HTTP方式與WebSocket通信,具體如下:
1) Runtime封裝執(zhí)行命令Process p=Runtime.getRuntime().exec(“./sc.out”);調(diào)用該語(yǔ)句后,Process類即可封裝sc.out的執(zhí)行過(guò)程,并提供操作系統(tǒng)管理進(jìn)程的基本操作,例如:waitFor(等待)、destory(殺死)等方法。同時(shí)通過(guò)輸入和輸出流的方式與Process交互,實(shí)現(xiàn)進(jìn)程運(yùn)行時(shí)的輸入、輸出和報(bào)錯(cuò)管理。
2) 捕獲執(zhí)行的信息流,InputStream err=p.getErrorStream()該方法可捕獲執(zhí)行程序時(shí)的報(bào)錯(cuò)信息流。InputStream in =p.getInputStream()該方法將獲得輸入信息流,封裝為BufferReader對(duì)象br,從流中可讀取執(zhí)行程序的輸出信息。當(dāng)String msg=br.readLine()進(jìn)入阻塞狀態(tài)時(shí),可判定為等待輸入。利用OutputStream out=p.getOutStream()該方法將獲得輸出信息流,封裝為BufferWriter對(duì)象bw,通過(guò)bw.write(data)和bw.flush()將輸入值提交給執(zhí)行進(jìn)程,并喚醒阻塞的輸出進(jìn)程。
3) 與前臺(tái)控制臺(tái)交互,需要在Web服務(wù)端定義SocketSrv(繼承自WebSocketServlet),負(fù)責(zé)與頁(yè)面中的WebSocket對(duì)象實(shí)現(xiàn)雙向通信[12]。ws=new WebSocket(“ws:∥localhost:8082/socketService”); 一方面能將后臺(tái)br.readLine()讀取到的消息推送至頁(yè)面ws.onmessage=function(event){console.log(event.data);},另一方面可將前臺(tái)頁(yè)面的輸入數(shù)據(jù)(data)通過(guò)s.send(data); 提交給后臺(tái)的bw.write(data),實(shí)現(xiàn)執(zhí)行程序的輸入。
研究利用HTML5的2D繪圖技術(shù)構(gòu)建一套可視化的編程語(yǔ)言教學(xué)環(huán)境,給出流程圖模型到源代碼轉(zhuǎn)換的基本思路,以及集成編譯環(huán)境的方法。該軟件集成了流程圖繪制、演示和源代碼的生成等功能,且具有靈活的交互界面和發(fā)布方式,已經(jīng)在程序設(shè)計(jì)語(yǔ)言教學(xué)中得到了應(yīng)用,取得了良好的教學(xué)效果。
目前,該平臺(tái)主要生成C語(yǔ)言的源代碼,其他語(yǔ)言則需要重新定義一套新的代碼生成模塊和集成語(yǔ)言編譯環(huán)境模塊。同時(shí),對(duì)于C語(yǔ)言中部分特定的數(shù)據(jù)類型(如:指針、結(jié)構(gòu)體、共同體等)、運(yùn)算符(位運(yùn)算,逗號(hào)表達(dá)式等)和語(yǔ)法結(jié)構(gòu)(如:break,continue,goto等)的支持不足,隨著軟件不斷完善,這些問(wèn)題會(huì)得到很好的解決。
參考文獻(xiàn):
[1]程向前. 基于流程圖的可視化程序設(shè)計(jì)環(huán)境對(duì)大學(xué)計(jì)算機(jī)基礎(chǔ)教學(xué)的影響[J]. 計(jì)算機(jī)教育, 2012(14):56-59.
[2]蔡慧英,陳婧雅,顧小清. 支持可視化學(xué)習(xí)過(guò)程的學(xué)習(xí)技術(shù)研究[J]. 中國(guó)電化教育, 2013(12):27-33.
[3]HU Chunghua,WANG Fengjian. Constructing an integrated visual programming environment[J]. Software-Practice and Experience, 2015,28(7):773-798.
[4]CARLISLE MARTINC. RAPTOR: RAPTOR: A Visual Programming Environment for Teaching Algorithmic Problem Solving[EB/OL]. [2017-05-08]. https:∥www.researchgate.net/publish /221537443_RAPTOR_A_visual_programming_environment_for_teaching_algorithmic_problem_solving.
[5]戴松,許冉,周忠. 基于HTML5的算法動(dòng)畫(huà)可視化平臺(tái)[J]. 系統(tǒng)仿真學(xué)報(bào), 2013(25):2436-2441.
[6]傅金枝,黃世梅. 基于HTML5的數(shù)據(jù)結(jié)構(gòu)算法演示系統(tǒng)的設(shè)計(jì)與實(shí)現(xiàn)[J]. 實(shí)驗(yàn)室科學(xué), 2015(2):72-75.
[7]PRAKASH H O,BHOSHAN R P. Venkataraman integrated visual programming environment[J]. International Journal of Modeling & Optimization, 2013:256-260.
[8]劉孟仁,劉海慶. 軟件可視化技術(shù)及其應(yīng)用研究[J]. 計(jì)算機(jī)應(yīng)用研究, 2002,19(6):26-28.
[9]周忠,強(qiáng)津培,戴松. 算法可視化的計(jì)算機(jī)輔助教學(xué)平臺(tái)設(shè)計(jì)與實(shí)踐[J]. 計(jì)算機(jī)教育, 2014(16):81-84.
[10]王黎明,王幗釹,周明媛,等. 程序流程圖到代碼的自動(dòng)生成算法[J]. 西安電子科技大學(xué)學(xué)報(bào)(自然科學(xué)版), 2012(6):70-77.
[11]HAMID B,KEVIN S. Monarch: Model-based Development of software Architectures[C]∥Proc of the 13th International Conference on Model Driven Engineering Languages and Systems : Part Ⅱ (MODELS 10). Antwerp:Springer, 2010:376-390.
[12]李錫輝,楊麗. 基于WebSocket的服務(wù)器推送技術(shù)研究[J]. 網(wǎng)絡(luò)安全技術(shù)與應(yīng)用, 2014(6):45-46.
[13]趙慧臣. 知識(shí)可視化視覺(jué)表征的形式分析[J]. 現(xiàn)代教育技術(shù), 2012,22(2):25-30.
[14]劉海,李姣姣,張維,等. 面向在線教學(xué)平臺(tái)的數(shù)據(jù)可視化方法及應(yīng)用[J]. 中國(guó)遠(yuǎn)程教育, 2018(1):37-44.
[15]李芒,蔡旻君,蔣科蔚. 可視化教學(xué)設(shè)計(jì)方法與應(yīng)用[J]. 電化教育研究, 2013(3):6-22.
沈陽(yáng)師范大學(xué)學(xué)報(bào)(自然科學(xué)版)2018年2期