譚火彬,林廣艷
(北京航空航天大學(xué) 軟件學(xué)院,北京 100191)
程序設(shè)計(jì)課程是軟件工程專業(yè)低年級(jí)本科生的專業(yè)基礎(chǔ)課程,傳統(tǒng)的程序設(shè)計(jì)課程教學(xué)更多地關(guān)注底層程序結(jié)構(gòu)的設(shè)計(jì)和實(shí)現(xiàn),側(cè)重于算法和數(shù)據(jù)結(jié)構(gòu)的應(yīng)用。學(xué)生學(xué)習(xí)時(shí)將重點(diǎn)放在各個(gè)知識(shí)點(diǎn)的語法學(xué)習(xí)和實(shí)踐上。因此很多同學(xué)在上完程序設(shè)計(jì)課程之后,更多只是掌握了語法,而不能在實(shí)踐項(xiàng)目中進(jìn)行有效的應(yīng)用。這樣的程序設(shè)計(jì)課程與實(shí)際軟件工程思想是完全脫節(jié)的。
面向?qū)ο蟮某绦蜃鳛槟壳白钪髁鞯木幊谭缎?,其程序設(shè)計(jì)課程的教學(xué)更應(yīng)該體現(xiàn)如何解決問題的工程化思想。課程教學(xué)重點(diǎn)不應(yīng)該關(guān)注類、繼承等語法結(jié)構(gòu)的編寫,而需要為學(xué)生建立面向?qū)ο蟮某绦蛟O(shè)計(jì)思想,更多地關(guān)注如何封裝為類、如何應(yīng)用多態(tài)建立穩(wěn)定的系統(tǒng)結(jié)構(gòu)等。通過這種在低年級(jí)程序設(shè)計(jì)課程中就逐步灌輸軟件工程化思想,從而為后續(xù)的軟件工程相關(guān)課程奠定堅(jiān)實(shí)的語言基礎(chǔ)。
將程序設(shè)計(jì)課程的教學(xué)核心目標(biāo)從讓學(xué)生掌握一門編程語言,轉(zhuǎn)變?yōu)榕囵B(yǎng)學(xué)生利用程序設(shè)計(jì)語言解決實(shí)際工程問題的能力。為此,在課程內(nèi)容設(shè)計(jì)時(shí),面向?qū)ο蟮某绦蛟O(shè)計(jì)課程不再是簡單地圍繞語言自身的語法展開,而是以傳授面向?qū)ο蟮木幊趟枷霝橹骶€,通過系統(tǒng)地學(xué)習(xí)面向?qū)ο蟮木幊趟枷?,從而掌握面向?qū)ο筌浖こ汤碚摵蛯?shí)踐,這也為后續(xù)軟件工程相關(guān)課程的教學(xué)奠定基礎(chǔ)[1]。經(jīng)過多輪的課程調(diào)研和培養(yǎng)方案改革,最終制定的課程體系如圖1所示。
圖1 面向?qū)ο蟪绦蛟O(shè)計(jì)課程體系
作為一門面向?qū)ο蟪绦蛟O(shè)計(jì)課程,學(xué)生首先應(yīng)該具備基本的程序設(shè)計(jì)知識(shí)。本門課程以C++作為授課語言,課程開設(shè)在本科一年級(jí)第二學(xué)期,學(xué)生在第一學(xué)期已經(jīng)學(xué)習(xí)了C/C++結(jié)構(gòu)化編程基礎(chǔ)知識(shí),因此本學(xué)期以C++作為面向?qū)ο蟮木幊陶Z言是非常適合的[2],不需要額外地補(bǔ)充結(jié)構(gòu)化編程知識(shí)。課程開篇的“認(rèn)識(shí)對(duì)象”并不講授語言本身,而是介紹面向?qū)ο蟮木幊趟枷?,介紹什么是類、什么是對(duì)象,為什么要封裝類等基本的面向?qū)ο笏枷?。這樣讓學(xué)生從第一學(xué)期程序設(shè)計(jì)課程中轉(zhuǎn)變過來,學(xué)生不再把這門課程作為結(jié)構(gòu)化程序設(shè)計(jì)課程的延續(xù),而是作為學(xué)習(xí)軟件工程思想的開始。
后面的主體內(nèi)容就是系統(tǒng)地介紹面向?qū)ο缶幊痰母鱾€(gè)核心概念,包括類的封裝、繼承、多態(tài)和異常處理等主線概念和C++編程實(shí)現(xiàn);而模板的內(nèi)容作為另一種封裝方法,體現(xiàn)了泛型編程思想,可以根據(jù)學(xué)時(shí)的多少調(diào)整相應(yīng)的內(nèi)容。第8章以C++中流庫的使用為背景,介紹如何高效地使用C++類庫,從而極大地提高編程效率。第9章介紹一些圖形化編程的思想和實(shí)踐,對(duì)于C++而言,以QT或MFC圖形框架為例進(jìn)行簡單的講解。通過這些內(nèi)容的教學(xué),學(xué)生基本上掌握了編寫一個(gè)軟件系統(tǒng)所應(yīng)具備的編程能力和技巧,能獨(dú)立完成一個(gè)簡單的業(yè)務(wù)系統(tǒng)。當(dāng)然,我們根據(jù)課程學(xué)時(shí)的情況,調(diào)整課程內(nèi)容,如果課時(shí)足夠,模板、GUI編程內(nèi)容可以適當(dāng)增加,這些都是比較實(shí)用的編程技能。
上機(jī)實(shí)踐是程序設(shè)計(jì)課程最重要的環(huán)節(jié),程序一定要在實(shí)踐中掌握和應(yīng)用。因此如何設(shè)計(jì)好實(shí)踐內(nèi)容是確保完成教學(xué)目標(biāo)的重要保障。在確保覆蓋課程知識(shí)點(diǎn)的同時(shí)如何充分體現(xiàn)工程化思想,讓學(xué)生在實(shí)踐中掌握面向?qū)ο缶幊趟枷耄@是課程實(shí)踐體系改革所關(guān)注的重點(diǎn)。
以往的程序設(shè)計(jì)課程大多是按照每個(gè)知識(shí)點(diǎn)設(shè)計(jì)專門的編程練習(xí),這可以有效地確保知識(shí)點(diǎn)的覆蓋,但面向?qū)ο蟮某绦蛟O(shè)計(jì)不僅僅是要掌握簡單的一個(gè)知識(shí)點(diǎn),比如讓學(xué)生學(xué)會(huì)寫一個(gè)類,并使用類的對(duì)象,這個(gè)單一的知識(shí)點(diǎn)很好掌握。但更重要的是要讓學(xué)生理解為什么要封裝成為一個(gè)類,封裝這個(gè)類的好處是什么。封裝為類的目的是為了以后更方便的使用,并為后續(xù)的繼承和多態(tài)奠定基礎(chǔ)。為了達(dá)到這個(gè)目標(biāo),就必須讓學(xué)生在后續(xù)的實(shí)踐中繼續(xù)使用這個(gè)類,并基于這些類來搭建目標(biāo)系統(tǒng)。因此整個(gè)實(shí)踐體系應(yīng)該建立在一個(gè)完整的項(xiàng)目基礎(chǔ)之上,通過多次實(shí)踐完成一個(gè)大項(xiàng)目;每次實(shí)踐都是在上一次成果之上繼續(xù)封裝和擴(kuò)展,最終形成一個(gè)有一定功能的軟件項(xiàng)目。通過這樣系統(tǒng)化的項(xiàng)目式實(shí)踐,從而讓學(xué)生充分理解軟件工程思想,達(dá)成教學(xué)目標(biāo)[3,4]。
整個(gè)課程上機(jī)實(shí)踐過程由易到難,穿插在課程教學(xué)過程中,配合課程知識(shí)點(diǎn),圍繞一個(gè)完整的項(xiàng)目,設(shè)計(jì)了多個(gè)上機(jī)實(shí)踐內(nèi)容,并最終構(gòu)建出目標(biāo)項(xiàng)目。在這個(gè)過程中,每次實(shí)踐都是以前一次實(shí)踐內(nèi)容為基礎(chǔ),讓學(xué)生充分理解面向?qū)ο蟪绦蛟O(shè)計(jì)中的各類原理和機(jī)制的應(yīng)用。具體的課程案例會(huì)根據(jù)使用情況定期進(jìn)行更新。
以下以近幾個(gè)學(xué)年實(shí)踐課程使用的學(xué)生選課系統(tǒng)為例,說明具體的實(shí)踐內(nèi)容安排。這個(gè)項(xiàng)目本身背景與學(xué)生緊密相關(guān),對(duì)于低年級(jí)本科生來說難度合適,也不需要太多的業(yè)務(wù)知識(shí)。圖2給出了體現(xiàn)系統(tǒng)最終結(jié)構(gòu)的類圖(只包含了一些重要的屬性和方法),圖中共涉及的7個(gè)類,通過8次上機(jī)實(shí)驗(yàn)課程完成。具體的實(shí)踐內(nèi)容如下。
(1)運(yùn)用類封裝機(jī)制,設(shè)計(jì)并實(shí)現(xiàn)日期類(Date),包括判斷閏年、求下一天等功能實(shí)現(xiàn);
(2)使用類對(duì)象,封裝新的學(xué)生類(Student),并復(fù)用日期類作為學(xué)生的生日(birthDate);
(3)封裝課程類(Course),實(shí)現(xiàn)基本的學(xué)生選課功能,同時(shí)為已完成的三個(gè)類實(shí)現(xiàn)運(yùn)算符重載;
(4)運(yùn)用類的繼承,為課程類添加必修課(Obligatory Course)和選修課(Elective Course)兩個(gè)子類,實(shí)現(xiàn)學(xué)生選必修課和選修課的功能;
(5)運(yùn)用多態(tài)機(jī)制,完成學(xué)生選課、登記課程成績、查詢課程成績等功能;
(6)為選課系統(tǒng)添加異常處理機(jī)制(MyException);
(7)運(yùn)用流技術(shù),將學(xué)生選課信息、成績信息等存儲(chǔ)到文件;
(8)封裝界面類(Console),實(shí)現(xiàn)基本的用戶交互過程;可進(jìn)一步結(jié)合圖形界面技術(shù),實(shí)現(xiàn)復(fù)雜的圖形界面。
通過一個(gè)學(xué)期的課程學(xué)習(xí)和實(shí)踐,每個(gè)學(xué)生都可以自主完成這樣一個(gè)有一定規(guī)模的學(xué)生選課系統(tǒng),這對(duì)學(xué)生來說就是軟件開發(fā)的第一次實(shí)踐經(jīng)歷。很多學(xué)生在大四的求職簡歷上寫的自己完成的第一個(gè)軟件項(xiàng)目就是本課程的實(shí)踐內(nèi)容,這也是對(duì)整個(gè)課程實(shí)踐內(nèi)容的認(rèn)可。
圖2 面向?qū)ο蟪绦蛟O(shè)計(jì)實(shí)踐系統(tǒng)設(shè)計(jì)方案
筆者自2004年開始,就為北京航空航天大學(xué)軟件學(xué)院本科一年級(jí)學(xué)生講授C++程序設(shè)計(jì)方面的課程,課程名稱從最早的“C++程序設(shè)計(jì)”,到后來的“高級(jí)語言程序設(shè)計(jì)(2)”,再到目前正式命名的“面向?qū)ο蟮某绦蛟O(shè)計(jì)”;經(jīng)過多年的課程建設(shè),課程體系和內(nèi)容不斷改進(jìn)和完善,并最終形成了現(xiàn)有的課程框架、主體內(nèi)容和實(shí)踐體系。在多年的教學(xué)實(shí)踐中,課程內(nèi)容和教學(xué)效果也得到了學(xué)生們的廣泛認(rèn)可。為了客觀地評(píng)價(jià)目前課程改革的實(shí)際教學(xué)效果,自2014年開始,我們?cè)诿繉W(xué)期授課結(jié)束后均開展了完全匿名的教學(xué)效果問卷調(diào)查,整個(gè)問卷調(diào)查內(nèi)容分為4個(gè)部分,共計(jì)14個(gè)問題,下面詳細(xì)介紹2014—2016這3年的調(diào)查結(jié)果。
首先是對(duì)面向?qū)ο蟾拍畹目傮w理解,包括兩個(gè)問題,調(diào)查結(jié)果如表1所示。調(diào)查表涉及3年的數(shù)據(jù),調(diào)查對(duì)象全部為上課的學(xué)生,其中2014年81人參與調(diào)查,2015年80人,2016年71人,3年總計(jì)232人參與調(diào)查(下同)。表中詳細(xì)給出了各個(gè)問題選項(xiàng)的人數(shù)和百分比,并計(jì)算了3年的總體百分比情況。
從表中可以看出,有將近一半(42.67%)的學(xué)生表示完全理解了面向?qū)ο蟮木幊趟枷耄纠斫獾膶W(xué)生占53.88%。這表明通過課程學(xué)習(xí),絕大部分學(xué)生(96.55%)都能夠順利掌握面向?qū)ο蟮木幊趟枷?。而在?duì)面向?qū)ο蠓庋b、繼承和多態(tài)這三個(gè)最核心概念的理解上,有一半的學(xué)生(52.59%)選擇了封裝,這是面向?qū)ο罄镒罨A(chǔ)也是最重要的一個(gè)概念,學(xué)生的選擇結(jié)果也符合預(yù)期。
問卷調(diào)查的第2部分是針對(duì)面向?qū)ο蟾鱾€(gè)具體知識(shí)點(diǎn)的調(diào)查,包括6個(gè)問題,調(diào)查結(jié)果如表2所示。包括封裝、繼承、多態(tài)、模板和異常處理5個(gè)核心知識(shí)點(diǎn),以及對(duì)“封裝”這個(gè)最基礎(chǔ)知識(shí)點(diǎn)的進(jìn)一步調(diào)查問題。
從表2中可以看出,超過90%的學(xué)生至少基本理解了各個(gè)知識(shí)點(diǎn)(不理解比例少于10%)。而相對(duì)來說,模板這個(gè)知識(shí)點(diǎn)掌握程度不是很好,有13.79%的學(xué)生表示沒有理解C++中的模板,這也是在預(yù)料之中,由于課時(shí)緊張,模板只有3個(gè)學(xué)時(shí),而且沒有安排單獨(dú)的實(shí)踐學(xué)時(shí),在課程教學(xué)大綱設(shè)計(jì)時(shí),此部分內(nèi)容只作為介紹性的章節(jié),不作深入要求。
表1 面向?qū)ο蟾拍畹目傮w理解情況
表2 面向?qū)ο蟾髦R(shí)點(diǎn)的掌握情況
第3部分是針對(duì)上機(jī)實(shí)踐方式和效果的調(diào)查,包括3個(gè)問題,從實(shí)踐難度、遞增式實(shí)踐方式和教學(xué)效果這3個(gè)方面展開。調(diào)查結(jié)果如表3所示。
從表3中可以看出,首先從難度上來說學(xué)生們普遍認(rèn)可題目的難度,實(shí)踐題目設(shè)計(jì)符合當(dāng)前的學(xué)生水平。而對(duì)于這種遞增式實(shí)踐方式,得到了絕大部分學(xué)生(96.55%)的認(rèn)可。從實(shí)踐效果來說,在全部調(diào)查對(duì)象中,只有1個(gè)學(xué)生不認(rèn)可這種遞增式的項(xiàng)目實(shí)踐方式有助于加深理解面向?qū)ο缶幊趟枷耄?0%的學(xué)生認(rèn)為有很大的幫助。
最后一部分是針對(duì)C++語言和其他語言應(yīng)用情況調(diào)查,這部分是延伸的調(diào)查,主要是了解學(xué)生對(duì)于編程語言的學(xué)習(xí)情況和后續(xù)計(jì)劃,對(duì)后續(xù)的課程改革有借鑒意義。調(diào)查結(jié)果如表4所示。需要注意的是,最后兩個(gè)問題是多選題,給學(xué)生提供了多個(gè)選項(xiàng),學(xué)生可以根據(jù)自己的情況選擇多項(xiàng),表4中只給出了學(xué)生選擇最多的4個(gè)語言的情況。
表3 上機(jī)實(shí)踐方式和效果
表4 C++和其他程序設(shè)計(jì)語言應(yīng)用情況
從表4中可以看出,大部分學(xué)生(78.45%)還是比較認(rèn)可C++語言,并表示會(huì)繼續(xù)學(xué)習(xí)和使用該語言;而對(duì)于其他語言,被學(xué)生廣泛認(rèn)可的語言包括Java、C#、Python和JavaScript,其中Java語言是認(rèn)可度最高的,這也符合目前編程語言的實(shí)際使用情況。
除了標(biāo)準(zhǔn)的問卷調(diào)查內(nèi)容外,部分學(xué)生在問卷的最后對(duì)課程的教學(xué)效果給出了高度評(píng)價(jià),一些比較有針對(duì)性的評(píng)價(jià)如下:①OOP的好用之處、具體的設(shè)計(jì),還是得通過一段時(shí)間的編程才能感受到,在我們都這么菜的情況下,老師的教學(xué)實(shí)在是相當(dāng)棒了?、谶@門課讓我對(duì)C++從上學(xué)期的排斥漸漸對(duì)它感興趣,喜歡上了編程。③課講授得很好,讓我對(duì)面向?qū)ο缶幊逃辛艘粋€(gè)較好的理解,對(duì)于我學(xué)習(xí)Java非常有幫助。
當(dāng)然,也有個(gè)別學(xué)生提出了一些改進(jìn)的建議,這些都為以后的課程內(nèi)容改革提供了思路:①希望加強(qiáng)設(shè)計(jì)的程序豐富度,提高各種功能種類,或者提供其他工程的設(shè)計(jì)思路作為額外作業(yè)。②可以設(shè)計(jì)一項(xiàng)大作業(yè),期末提交,代替筆試的最后一道題,我認(rèn)為這樣更有利于大家從整體上對(duì)程序的設(shè)計(jì)和編寫有一個(gè)好的思考和理解。
程序設(shè)計(jì)語言是軟件工程師必備的基本技能,只有有效地掌握編程技能和所體現(xiàn)的編程思維,才能更好地理解軟件工程。為此,拋棄傳統(tǒng)低年級(jí)程序設(shè)計(jì)課程側(cè)重于語法教學(xué),而將重點(diǎn)轉(zhuǎn)向傳授和灌輸面向?qū)ο缶幊趟枷?,讓學(xué)生盡早接觸和理解軟件工程,在大一就能夠通過一門程序設(shè)計(jì)課程完成一個(gè)相對(duì)完整的項(xiàng)目實(shí)踐,從而為學(xué)生以后的軟件工程專業(yè)課程學(xué)習(xí)和實(shí)踐奠定了堅(jiān)實(shí)的基礎(chǔ)。
教學(xué)效果的好壞,最直接的評(píng)價(jià)來自于學(xué)生的認(rèn)可,通過多輪的匿名問卷調(diào)查收集到學(xué)生真實(shí)的評(píng)價(jià)信息,評(píng)價(jià)結(jié)果有效地說明課程改革方案和實(shí)踐體系得到了學(xué)生普遍認(rèn)可,達(dá)到了預(yù)期的效果。