何凱
(黃驊市職業(yè)技術(shù)教育中心 河北省黃驊市 061100)
筆者在實(shí)際工作中,發(fā)現(xiàn)傳統(tǒng)的教學(xué)模式會(huì)讓C 語言初學(xué)者感覺學(xué)習(xí)很困難,教學(xué)質(zhì)量很難保證。目前國(guó)內(nèi)外已經(jīng)研究并開發(fā)出了許多測(cè)評(píng)系統(tǒng),但是總是因?yàn)槟承┰虿痪哂型ㄓ眯?。一方面因?yàn)橛行┫到y(tǒng)不是開源的,我們無從加以利用;另一方面有些系統(tǒng)雖然開源,但是并不符合我們的自身需求,系統(tǒng)所針對(duì)的人群是有限制的,不滿足當(dāng)前教學(xué)需求。為此,需要為特定的教學(xué)環(huán)境研究和設(shè)計(jì)一套合適的系統(tǒng),以便提高學(xué)生的學(xué)習(xí)興趣和主動(dòng)性,并及時(shí)反饋學(xué)生的學(xué)習(xí)情況,進(jìn)而幫助教師改善教學(xué)過程,提高整個(gè)課程的教學(xué)質(zhì)量。
程序評(píng)測(cè)系統(tǒng)的設(shè)計(jì)是有一定的目標(biāo)群體作為基礎(chǔ),所設(shè)置的題目也是針對(duì)這些群體的特定需求所設(shè)定的。此次教學(xué)模式改革和系統(tǒng)設(shè)計(jì)開發(fā)所針對(duì)的使用人群是中等職業(yè)學(xué)校的學(xué)生,學(xué)習(xí)的算法規(guī)模較小,學(xué)習(xí)的理論知識(shí)比較淺顯,程序比較簡(jiǎn)單。因此每個(gè)題目都僅僅考察一個(gè)知識(shí)點(diǎn),包括編程題,編程題的絕大部分代碼系統(tǒng)都會(huì)提供,僅僅需要學(xué)生寫很少的代碼,讓學(xué)生稍微一想就能成功,這樣才能激發(fā)他們的學(xué)習(xí)興趣與主動(dòng)性。
對(duì)于系統(tǒng)的要求是方便攜帶,教師很方便地推送測(cè)試題目,學(xué)生通過簡(jiǎn)單操作就能正常運(yùn)行題目,通過動(dòng)態(tài)測(cè)試判定正確與否。因此,我們對(duì)于每個(gè)題目只需要判定對(duì)與錯(cuò)就可以,因?yàn)闇y(cè)試題目本身就沒有太多的步驟。
根據(jù)以上分析,我們對(duì)系統(tǒng)進(jìn)行如下設(shè)計(jì)。
結(jié)合《C 語言程序設(shè)計(jì)》教學(xué)大綱,為每個(gè)知識(shí)點(diǎn)制定相應(yīng)配套的選擇題和編程題,適合中職生的題目,形成題庫(kù),保存在數(shù)據(jù)庫(kù)中。系統(tǒng)采用ACCESS 數(shù)據(jù)庫(kù),ACCESS 數(shù)據(jù)庫(kù)小巧、方便,便于攜帶,但是對(duì)于并發(fā)訪問的控制不理想,那么該系統(tǒng)如何提高ACCESS 數(shù)據(jù)庫(kù)的并發(fā)訪問數(shù)量呢。
系統(tǒng)采用了簡(jiǎn)單而有效的方法:對(duì)數(shù)據(jù)庫(kù)文件的讀寫訪問分開,讀寫互不影響;所有的讀進(jìn)程使用互斥,將讀進(jìn)程線性化,所有的寫進(jìn)程使用互斥,將所有的寫進(jìn)程線性化,這樣同時(shí)訪問該數(shù)據(jù)庫(kù)文件的進(jìn)程最多只有兩個(gè),這樣就不會(huì)因?yàn)椴l(fā)訪問量大而報(bào)錯(cuò),通常情況10 多個(gè)并發(fā)訪問,Access 數(shù)據(jù)庫(kù)就可能報(bào)錯(cuò),經(jīng)過這樣處理后,同時(shí)幾百個(gè)客戶端訪問都不成問題。
服務(wù)器與客戶端使用datasnap 三層架構(gòu),當(dāng)客戶端連接服務(wù)器時(shí),服務(wù)器會(huì)創(chuàng)建一個(gè)新的線程,該線程中對(duì)數(shù)據(jù)庫(kù)文件進(jìn)行打開和查詢。多個(gè)客戶端連接服務(wù)器時(shí),服務(wù)器就會(huì)創(chuàng)建多個(gè)線程,那么這些線程都會(huì)對(duì)數(shù)據(jù)庫(kù)文件進(jìn)行打開和查詢,并且在服務(wù)器內(nèi)存中保存了相應(yīng)的數(shù)據(jù)。除了采用上面互斥的方法外,當(dāng)線程讀取數(shù)據(jù)后,客戶端要關(guān)閉自己的鏈接,這樣會(huì)引起服務(wù)器將相應(yīng)的線程關(guān)閉,包括關(guān)閉數(shù)據(jù)庫(kù)文件,釋放服務(wù)器內(nèi)存中的數(shù)據(jù),這樣能保證服務(wù)器內(nèi)存夠用,數(shù)據(jù)庫(kù)文件不會(huì)因?yàn)椴l(fā)而報(bào)錯(cuò)。
將題目的自動(dòng)化評(píng)測(cè)放在學(xué)生機(jī)上運(yùn)行。當(dāng)客戶端得到題目的同時(shí),也得到了測(cè)試題目的字符串,客戶端自身使用測(cè)試字符串測(cè)試學(xué)生編寫的程序,將測(cè)試結(jié)果提交服務(wù)器。服務(wù)器與客戶端對(duì)應(yīng)的線程將測(cè)試結(jié)果,使用消息發(fā)給服務(wù)器主線程,服務(wù)器主線程負(fù)責(zé)寫數(shù)據(jù)庫(kù)文件。教師檢查學(xué)生的答題情況。
(1)當(dāng)客戶端查詢數(shù)據(jù)時(shí),服務(wù)器的線程fdquery2 查詢到數(shù)據(jù)題目,將數(shù)據(jù)傳遞給clientdataset1,隨后關(guān)閉線程與數(shù)據(jù)庫(kù)文件的連接,服務(wù)器通過DataSetProvider2 將clientdataset1 中的數(shù)據(jù)提供給客戶端。代碼如下:
(2)當(dāng)客戶端把學(xué)生作答情況提交給服務(wù)器時(shí),服務(wù)器線程通過消息報(bào)告給服務(wù)器主線程,由主線程寫入數(shù)據(jù)庫(kù)文件,代碼如下:
(3)當(dāng)學(xué)生交卷時(shí),服務(wù)器線程將信息做成消息發(fā)送給服務(wù)器主線程處理,將考生信息寫入消息里,使用SendMessage 發(fā)送消息,操作如下:
(4)服務(wù)器主線程接收到消息后,將學(xué)生作答情況寫入數(shù)據(jù)庫(kù),由于是寫數(shù)據(jù)庫(kù),所以要使用臨界區(qū),保證寫數(shù)據(jù)庫(kù)這個(gè)操作的原子性,代碼如下:
在系統(tǒng)啟動(dòng)時(shí),進(jìn)行臨界區(qū)的初始化,代碼如下:
(1)客戶端下載下載試題,clientdataset2.Open 時(shí)下載數(shù)據(jù),如果數(shù)據(jù)量比較大,則會(huì)出現(xiàn)假死的情況,卡在那里,特別是對(duì)于廣域網(wǎng)的時(shí)候,可能需要點(diǎn)時(shí)間,所以我們?cè)黾恿司€程的處理機(jī)制。把下載數(shù)據(jù)放到了線程里。并且通過myThread.Finished 來判斷數(shù)據(jù)是否下載完畢,期間可以更新界面。代碼如下:
(2)數(shù)據(jù)下載完畢后,通知服務(wù)器已經(jīng)下載完畢,服務(wù)器作相應(yīng)的標(biāo)記,而后客戶端通過SQLconnection1.Close 關(guān)閉整個(gè)鏈路,以便服務(wù)器釋放內(nèi)存、數(shù)據(jù)庫(kù)、線程池等資源。代碼如下:
(3)客戶端提交學(xué)生作答,提交后,通過sqlconnection2.Close 關(guān)閉這條與服務(wù)器的鏈路,也就是說每次提交作答,客戶端都要先連接服務(wù)器,提交作答后再關(guān)閉鏈接,釋放資源,這個(gè)過程相對(duì)于我們審題做題的過程來說,用時(shí)很少。特別是對(duì)于使用了花生殼一類的軟件來說,我們局域網(wǎng)的服務(wù)器可以作為廣域網(wǎng)的服務(wù)器來使用,但是花生殼限制了鏈接數(shù),該系統(tǒng)現(xiàn)在的設(shè)計(jì)正好滿足花生殼的這個(gè)限制,同一時(shí)刻只有少量的TCP 鏈路存在,其他鏈路都及時(shí)關(guān)閉了。相關(guān)代碼如下:
(4)對(duì)于選擇題和填空題,客戶端直接將學(xué)生作答信息發(fā)送給服務(wù)器;而對(duì)于編程題,該系統(tǒng)在客戶端進(jìn)行分析。服務(wù)器的數(shù)據(jù)庫(kù)中事先準(zhǔn)備好以下材料:編程題題目,測(cè)試用字符串,測(cè)試用結(jié)果??蛻舳私邮盏骄幊填}目的同時(shí),也得到了測(cè)試用字符串。舉例說明,以下編程題目要求實(shí)現(xiàn)功能:通過鍵盤輸入n、m,統(tǒng)計(jì)n 到m 的累加和,m 和n 計(jì)算在內(nèi),sum 用于輸出累加和。
編制題目時(shí),在題目中設(shè)置標(biāo)志,如上程序所示的注釋部分,只能在標(biāo)志范圍內(nèi)編寫學(xué)生自己的程序,其他地方不可以編輯,客戶端會(huì)對(duì)各部分做校驗(yàn)。學(xué)生嘗試編寫程序完成既定功能,當(dāng)學(xué)生點(diǎn)擊提交的時(shí)候,客戶端利用命令行argc 和argv 將測(cè)試用字符串輸入到程序中,對(duì)學(xué)生作答的程序進(jìn)行測(cè)試運(yùn)行,并將產(chǎn)生的運(yùn)行結(jié)果作為作答提交給服務(wù)器,服務(wù)器進(jìn)行判斷。
由于本方案是特定的服務(wù)器,使用了用戶自定義的用戶網(wǎng)絡(luò)協(xié)議,因此業(yè)界通用的一些測(cè)試程序不能很好的完成測(cè)試。鑒于此,筆者自己設(shè)計(jì)了測(cè)試方案。模擬多用戶鏈接服務(wù)器,進(jìn)而模擬大量用戶連接服務(wù)器,服務(wù)器都能穩(wěn)定的運(yùn)行,并且符合項(xiàng)目各項(xiàng)要求。