摘要:討論了當(dāng)前軟件工程存在的問(wèn)題和敏捷軟件開(kāi)發(fā)對(duì)相應(yīng)問(wèn)題的解決方法;針對(duì)軟件工程在教學(xué)中遇到的問(wèn)題,提出了基于敏捷軟件開(kāi)發(fā)組織教學(xué)內(nèi)容和教學(xué)實(shí)踐的方法,并分析了這種方法的優(yōu)點(diǎn)。
關(guān)鍵詞:敏捷軟件開(kāi)發(fā);極限編程;軟件工程;教學(xué)
0 引言
在《軟件工程》教學(xué)過(guò)程中,由于教學(xué)內(nèi)容和教學(xué)方法等諸多原因,上課效果并不十分理想,許多學(xué)生反映課程內(nèi)容抽象,缺乏實(shí)踐,難以理解,認(rèn)為軟件工程課程不實(shí)用,不重要。大多數(shù)同學(xué)編寫(xiě)軟件的方法還是處于原始的編碼和調(diào)試階段,軟件開(kāi)發(fā)是沒(méi)有計(jì)劃的,軟件的設(shè)計(jì)是在編寫(xiě)的過(guò)程中臨時(shí)決定的。這種做法在編寫(xiě)小軟件時(shí)還夠用,但是當(dāng)真正參與開(kāi)發(fā)商業(yè)軟件時(shí),由于軟件的復(fù)雜性大大增加,修改或增加功能都會(huì)很困難,而且軟件錯(cuò)誤變得越來(lái)越多并難以排除,系統(tǒng)開(kāi)發(fā)完后需要相當(dāng)長(zhǎng)的測(cè)試階段,甚至?xí)X(jué)得項(xiàng)目的完成遙遙無(wú)期,從而對(duì)會(huì)項(xiàng)目產(chǎn)生了嚴(yán)重的影響。所以系統(tǒng)的學(xué)習(xí)軟件開(kāi)發(fā)技術(shù)是十分重要的。
然而《軟件工程》本身也存在問(wèn)題,學(xué)生難以深入理解和掌握《軟件工程》所涉及的知識(shí)點(diǎn)也有其原因。軟件工程的提出是受其他工程學(xué)科(如土木工程)的啟發(fā),希望通過(guò)指定嚴(yán)格而詳盡的計(jì)劃,讓軟件開(kāi)發(fā)過(guò)程更加可預(yù)測(cè)和有效率,所以像其他工程學(xué)科一樣,軟件工程非常強(qiáng)調(diào)軟件開(kāi)發(fā)之前的計(jì)劃,強(qiáng)調(diào)在編寫(xiě)代碼之前做詳盡的需求分析,總體設(shè)計(jì)和詳細(xì)設(shè)計(jì)。當(dāng)前國(guó)內(nèi)外主要的軟件工程教學(xué)也都是基于此組織教學(xué)內(nèi)容,教學(xué)過(guò)程中強(qiáng)調(diào)文檔的編寫(xiě),從可行性研究、需求分析到總體設(shè)計(jì)、詳細(xì)設(shè)計(jì)都要編寫(xiě)大量的文檔。這種做法存在兩個(gè)問(wèn)題:一、在編寫(xiě)這些文檔之前需要做大量的需求調(diào)查工作,而編寫(xiě)這些文檔的過(guò)程是十分枯燥的,許多同學(xué)都不愿意寫(xiě)文檔。二、需求是非常容易變更的,很多時(shí)候用戶(hù)并不清楚自己到底想要什么樣的軟件,只有在用戶(hù)使用軟件一段時(shí)間后,對(duì)軟件的需求才逐漸清晰起來(lái)。所以需求的變動(dòng)是不可避免的,而由于需求的變更,維護(hù)軟件工程中編寫(xiě)的眾多文檔的一致性更是需要耗費(fèi)大量的時(shí)間。在軟件開(kāi)發(fā)社區(qū)中,基于大量文檔的軟件工程方法被認(rèn)為是繁瑣的官僚做法。
敏捷軟件開(kāi)發(fā)的提出是為了在沒(méi)有計(jì)劃的軟件開(kāi)發(fā)和過(guò)度計(jì)劃的軟件工程上面尋找一個(gè)平衡點(diǎn)。由于敏捷軟件開(kāi)發(fā)也屬于軟件工程范疇,所以下面將基于大量文檔工程型的軟件工程稱(chēng)為傳統(tǒng)軟件工程。敏捷軟件開(kāi)發(fā)只要求盡量少的文檔,而且認(rèn)為最根本的文檔是源代碼。Martin Fowler認(rèn)為敏捷軟件開(kāi)發(fā)過(guò)程和基于傳統(tǒng)軟件工程開(kāi)發(fā)的本質(zhì)區(qū)別在于以下兩點(diǎn):
(1)敏捷軟件開(kāi)發(fā)是基于適應(yīng)的,而傳統(tǒng)軟件工程是基于預(yù)測(cè)的。傳統(tǒng)軟件工程試圖對(duì)一個(gè)軟件項(xiàng)目在很長(zhǎng)的時(shí)間跨度內(nèi)做出詳細(xì)的計(jì)劃,然后依計(jì)劃進(jìn)行開(kāi)發(fā)。這種方式的前提是需求確定下來(lái)后就不再修改了,所以,傳統(tǒng)軟件工程本質(zhì)上是抵制變化的。而敏捷開(kāi)發(fā)方法則是主動(dòng)去適應(yīng)變化。
(2)敏捷軟件開(kāi)發(fā)方法以人為導(dǎo)向,而傳統(tǒng)軟件工程方法則以過(guò)程為導(dǎo)向。傳統(tǒng)軟件工程的目標(biāo)是定義一個(gè)過(guò)程,不論誰(shuí)來(lái)執(zhí)行這個(gè)過(guò)程都能完成任務(wù);而敏捷軟件開(kāi)發(fā)方法則認(rèn)為沒(méi)有任何過(guò)程能替代開(kāi)發(fā)團(tuán)隊(duì)的技能,軟件過(guò)程的作用是對(duì)開(kāi)發(fā)團(tuán)隊(duì)提供支持。
敏捷軟件開(kāi)發(fā)是一種軟件開(kāi)發(fā)的理念,它包含很多實(shí)際的方法,如極限編程(XP),Scram和精悍開(kāi)發(fā)(LeanDevelopment)等,在教學(xué)實(shí)踐上,需要選定一種開(kāi)發(fā)方法指導(dǎo)學(xué)生進(jìn)行實(shí)際開(kāi)發(fā),以加深對(duì)敏捷軟件開(kāi)發(fā)的理解。由于在以上方法中,極限編程最為流行,所以本文選用極限編程作為教學(xué)的軟件開(kāi)發(fā)方法。
1 需求分析
傳統(tǒng)軟件工程希望盡可能全面地確定需求,在軟件開(kāi)發(fā)之前進(jìn)行需求分析,要求編寫(xiě)出完整的需求文檔。而現(xiàn)實(shí)的情況是大部分項(xiàng)目需求很難固定下來(lái),主要原因是客戶(hù)對(duì)需求的理解也需要經(jīng)歷一個(gè)過(guò)程,客戶(hù)在使用軟件之后,才確認(rèn)軟件是否滿(mǎn)足他們的需求,并且會(huì)在使用過(guò)程中不斷學(xué)習(xí),并結(jié)合當(dāng)前市場(chǎng)的競(jìng)爭(zhēng)變化,更新他們的想法,提出新的需求,所以需求的本質(zhì)是易變的。敏捷軟件開(kāi)發(fā)的解決方法是通過(guò)頻繁的迭代開(kāi)發(fā),在盡量短的時(shí)間內(nèi)不斷迭代開(kāi)發(fā)出實(shí)際可運(yùn)行的、具備部分功能的軟件交付給用戶(hù),在獲取用戶(hù)的使用反饋后,項(xiàng)目組再根據(jù)反饋不斷調(diào)整軟件功能以符合用戶(hù)需求。
在極限編程項(xiàng)目的生命周期中,首先由用戶(hù)通過(guò)編寫(xiě)故事定義業(yè)務(wù)需求,故事是從系統(tǒng)使用者的角度對(duì)系統(tǒng)行為的簡(jiǎn)短描述。再由程序員評(píng)估開(kāi)發(fā)這些故事需要多長(zhǎng)時(shí)間,用戶(hù)根據(jù)故事的價(jià)值和需要完成的時(shí)間對(duì)這些故事進(jìn)行排序,再根據(jù)每個(gè)故事需要的開(kāi)發(fā)時(shí)間和一次迭代開(kāi)發(fā)周期的時(shí)間確定在此次迭代中能實(shí)現(xiàn)哪些故事。由于用戶(hù)故事描述得相當(dāng)簡(jiǎn)潔,很多細(xì)節(jié)沒(méi)有寫(xiě)清楚,所以開(kāi)發(fā)者在開(kāi)發(fā)中碰到不清楚的問(wèn)題,就需要詢(xún)問(wèn)客戶(hù)。極限編程要求客戶(hù)和開(kāi)發(fā)人員一起工作,現(xiàn)場(chǎng)及時(shí)解答開(kāi)發(fā)者的問(wèn)題,這相對(duì)軟件工程中通過(guò)需求工程先捕獲所有需求細(xì)節(jié)的做法來(lái)說(shuō),現(xiàn)場(chǎng)咨詢(xún)客戶(hù)獲取需求細(xì)節(jié)的做法更快,更準(zhǔn)確。在教學(xué)實(shí)踐過(guò)程中,教員可以預(yù)先準(zhǔn)備好案例,讓自己扮演客戶(hù),而讓學(xué)生扮演開(kāi)發(fā)人員,通過(guò)現(xiàn)場(chǎng)模擬的方式,演示如何通過(guò)故事描述需求,并現(xiàn)場(chǎng)解答疑問(wèn)。
2 估算項(xiàng)目開(kāi)發(fā)時(shí)間
在傳統(tǒng)軟件工程中,估計(jì)完成項(xiàng)目所需要的時(shí)間是十分困難的,因?yàn)樾枨蟮淖儎?dòng)和其他各種不可預(yù)知的因素會(huì)使得項(xiàng)目的進(jìn)展和事先預(yù)想的不一致。在極限編程中,項(xiàng)目的估算以估計(jì)每一個(gè)故事需要多少時(shí)間為基礎(chǔ),再根據(jù)每個(gè)迭代周期的時(shí)間,算出多少個(gè)迭代能完成所有的功能。在開(kāi)發(fā)過(guò)程中,團(tuán)隊(duì)根據(jù)實(shí)際的開(kāi)發(fā)進(jìn)度情況,動(dòng)態(tài)的調(diào)整項(xiàng)目完成需要的時(shí)間。由于每個(gè)用戶(hù)故事的粒度比較小,所以經(jīng)驗(yàn)豐富的團(tuán)隊(duì)可以比較精確的估計(jì)開(kāi)發(fā)一個(gè)故事所需要的時(shí)間。在教學(xué)過(guò)程中,很多學(xué)生開(kāi)始時(shí)不會(huì)估算開(kāi)發(fā)故事所需要的時(shí)間,這主要是由于學(xué)生沒(méi)有多少開(kāi)發(fā)經(jīng)驗(yàn),只要實(shí)際完成幾個(gè)故事,就能學(xué)會(huì)估算完成類(lèi)似的故事需要的時(shí)間。如果遇到某些有技術(shù)難度的故事,需要先弄清楚關(guān)鍵的技術(shù)難點(diǎn)再進(jìn)行估計(jì)。學(xué)生對(duì)故事得出估算的結(jié)果后要為每個(gè)故事標(biāo)上系數(shù),如1、1.5或2等,系數(shù)的單位是天。根據(jù)每個(gè)成員所能完成的故事就可以推算出一個(gè)迭代期內(nèi)能完成多少個(gè)用戶(hù)故事。
3 設(shè)計(jì)
傳統(tǒng)軟件工程非常重視設(shè)計(jì),這主要是源自于其他工程(如土木工程)中對(duì)設(shè)計(jì)的強(qiáng)調(diào)。在實(shí)際實(shí)施一個(gè)項(xiàng)目之前,工程師會(huì)先畫(huà)出一系列的圖紙,這些圖紙準(zhǔn)確地說(shuō)明了要做什么以及如何做。軟件工程和其他工程有兩個(gè)主要區(qū)別:
(1)建一座橋梁時(shí),設(shè)計(jì)費(fèi)用一般占整個(gè)工程的lO%,左右,余下的90%左右為施工建造費(fèi)用。而在軟件開(kāi)發(fā)中,編碼所占的時(shí)間一般要少得多。McConnell指出在大型項(xiàng)目中,編碼和單元測(cè)試只占15%,即使把所有測(cè)試工作都算作是建造的一部分,設(shè)計(jì)仍要占到50%。
(2)對(duì)于土木工程來(lái)說(shuō),木工程師使用的模型是基于多年的工程實(shí)踐,并結(jié)晶在工程典章中;一些設(shè)計(jì)上的關(guān)鍵部分,如應(yīng)力作用,都是建立于堅(jiān)實(shí)的數(shù)學(xué)分析之上。而一個(gè)用UML做出的設(shè)計(jì)要達(dá)到交給程序員就能直接編碼的狀態(tài)則非常困難,用UML那樣的語(yǔ)言做出的設(shè)計(jì)在紙上看起來(lái)非常漂亮,而實(shí)際編程時(shí)可能會(huì)發(fā)現(xiàn)嚴(yán)重的缺陷。Jack Reeves提出源代碼應(yīng)是設(shè)計(jì)文檔,而建造應(yīng)該是編譯和鏈接。
敏捷軟件開(kāi)發(fā)倡導(dǎo)的是簡(jiǎn)單設(shè)計(jì),極限編程提倡用簡(jiǎn)單的設(shè)計(jì)方法實(shí)現(xiàn)系統(tǒng)功能,在需要的時(shí)候再利用重構(gòu)改善設(shè)計(jì),這種方式也被稱(chēng)為演進(jìn)式設(shè)計(jì)。對(duì)于教學(xué)來(lái)說(shuō),如何讓學(xué)生理解設(shè)計(jì)相關(guān)的知識(shí)是十分困難的,因?yàn)閷W(xué)生缺乏足夠的開(kāi)發(fā)經(jīng)驗(yàn)?,F(xiàn)在采用的軟件工程教材中,軟件設(shè)計(jì)這部分內(nèi)容顯得空洞和教條,許多知識(shí)都已經(jīng)比較陳舊,教學(xué)效果比較差。采用基于敏捷軟件開(kāi)發(fā)的教學(xué),學(xué)生首先考慮的是如何用最簡(jiǎn)單的方法實(shí)現(xiàn)功能,隨著系統(tǒng)功能和需求的增加,學(xué)生會(huì)主動(dòng)思考改善現(xiàn)有的代碼以滿(mǎn)足新的需求,這時(shí)就可以引導(dǎo)學(xué)生學(xué)習(xí)各種設(shè)計(jì)模式來(lái)解決問(wèn)題,學(xué)生也能深刻理解設(shè)計(jì)的作用。
4 實(shí)現(xiàn)
軟件工程把編碼和測(cè)試統(tǒng)稱(chēng)為實(shí)現(xiàn)。在軟件工程課程的教學(xué)中編碼所占比重很少,其原因是編碼被認(rèn)為是一項(xiàng)體力勞動(dòng),所有需要?jiǎng)?chuàng)造性的腦力勞動(dòng)都已在設(shè)計(jì)階段做完,編碼不過(guò)是將設(shè)計(jì)翻譯成代碼。而事實(shí)上用UML做出達(dá)到可以交給程序員就能直接編程的設(shè)計(jì)是十分困難的,更多的時(shí)候是在編程的過(guò)程才中發(fā)現(xiàn)設(shè)計(jì)中存在的嚴(yán)重缺陷。敏捷軟件開(kāi)發(fā)非常強(qiáng)調(diào)編程的重要性,因?yàn)閺谋举|(zhì)上說(shuō),它們將代碼看成是設(shè)計(jì)的一部分。極限編程強(qiáng)調(diào)測(cè)試先行,表達(dá)意圖。在完成某個(gè)功能前,先寫(xiě)測(cè)試代碼,這種測(cè)試代碼叫單元測(cè)試,然后編寫(xiě)代碼,使測(cè)試得以通過(guò)。測(cè)試先行的優(yōu)點(diǎn)在于,在編寫(xiě)功能之前,先將注意力集中在此功能的接口和使用方式上。先寫(xiě)測(cè)試代碼被稱(chēng)為測(cè)試驅(qū)動(dòng)開(kāi)發(fā),它能提供更好的設(shè)計(jì)。對(duì)于教學(xué)來(lái)說(shuō),讓學(xué)生在寫(xiě)功能性代碼之前,先編寫(xiě)單元測(cè)試是非常有益的,這會(huì)迫使學(xué)生考慮所寫(xiě)的功能如何被使用,如何取一個(gè)表達(dá)其功能的方法名,這個(gè)方法應(yīng)該具有的功能,該方法應(yīng)該屬于哪個(gè)類(lèi)等問(wèn)題。當(dāng)然學(xué)生在開(kāi)始學(xué)習(xí)的時(shí)候一般沒(méi)有這方面的經(jīng)驗(yàn),如果學(xué)生們沒(méi)有想明白如何寫(xiě),則可先動(dòng)手寫(xiě)代碼實(shí)現(xiàn)其功能,再根據(jù)一些設(shè)計(jì)性原則(如單一職責(zé)原則)來(lái)檢查代碼,通過(guò)重構(gòu)改善代碼質(zhì)量。
5 集成驗(yàn)收測(cè)試
在傳統(tǒng)的軟件工程中,軟件集成驗(yàn)收測(cè)試是在軟件開(kāi)發(fā)完之后進(jìn)行的。敏捷軟件開(kāi)發(fā)的原則是盡可能早盡可能頻繁地進(jìn)行集成驗(yàn)收測(cè)試。因?yàn)樵诩沈?yàn)收測(cè)試之間所等待的時(shí)間越長(zhǎng),中間積累的軟件錯(cuò)誤就越多,調(diào)試錯(cuò)誤的成本就越高。人工進(jìn)行測(cè)試需要非常多資源,所以不可能以人工的方式進(jìn)行頻繁測(cè)試。敏捷軟件開(kāi)發(fā)所提出的頻繁測(cè)試是建立在自動(dòng)化測(cè)試的基礎(chǔ)上,通過(guò)使用測(cè)試框架和編寫(xiě)(或者用測(cè)試工具自動(dòng)生成)測(cè)試腳本而頻繁進(jìn)行的單元測(cè)試、集成測(cè)試和回歸測(cè)試。從教學(xué)角度來(lái)說(shuō),學(xué)生需要學(xué)習(xí)編寫(xiě)和運(yùn)行測(cè)試腳本,學(xué)習(xí)使用代碼管理工具(如CVS、SVN),在編寫(xiě)單元測(cè)試和實(shí)現(xiàn)相應(yīng)功能代碼后,就將代碼提交到版本庫(kù)。在完成一個(gè)故事之后,編寫(xiě)故事的集成驗(yàn)收測(cè)試腳本,從版本庫(kù)導(dǎo)出最新版本的代碼,運(yùn)行單元測(cè)試和集成驗(yàn)收測(cè)試,捕獲并解決錯(cuò)誤,重新運(yùn)行單元測(cè)試和集成測(cè)試,直到通過(guò)所有測(cè)試為止,這種技能的訓(xùn)練對(duì)學(xué)生畢業(yè)后參加實(shí)際項(xiàng)目開(kāi)發(fā)非常有幫助。
6 團(tuán)隊(duì)協(xié)作
在教學(xué)中如何讓學(xué)生學(xué)會(huì)團(tuán)隊(duì)協(xié)作是比較困難的。在實(shí)施基于極限編程的教學(xué)中,教師要將用戶(hù)故事分解為任務(wù)并分配到每個(gè)同學(xué)。由于班級(jí)里同學(xué)們的水平經(jīng)常是參差不齊,編程能力比較弱的同學(xué),學(xué)習(xí)動(dòng)力一般也比較差,上機(jī)課也經(jīng)常開(kāi)小差,采用極限編程中的結(jié)對(duì)編程是一個(gè)比較好的解決辦法。在上機(jī)實(shí)踐課上,讓兩位同學(xué)坐在一臺(tái)電腦面前,一位同學(xué)講實(shí)現(xiàn)思路,另一位同學(xué)輸入代碼,這樣可以相互督促對(duì)方不做與課程無(wú)關(guān)的事情,還可以相互探討實(shí)現(xiàn)的細(xì)節(jié)問(wèn)題,這種做法會(huì)讓兩位同學(xué)都高度集中地去編寫(xiě)代碼,在編寫(xiě)的過(guò)程中體會(huì)到合作的作用和樂(lè)趣。教師也可以通過(guò)記錄故事完成的進(jìn)度作為期末成績(jī)的一項(xiàng)指標(biāo),這會(huì)激發(fā)同學(xué)們的學(xué)習(xí)熱情。
7 教材和教學(xué)安排
教材可以選用《敏捷軟件開(kāi)發(fā)原則、模式與實(shí)踐》。這本書(shū)由Robeert,M.artin編寫(xiě),獲得了美國(guó)Software Development雜志每年一度評(píng)選出的技術(shù)圖書(shū)類(lèi)最高獎(jiǎng)項(xiàng)Jolt大獎(jiǎng)。其內(nèi)容安排也比較合理,第一部分是敏捷開(kāi)發(fā),第二部分是敏捷設(shè)計(jì),第三到第六部分是案例研究,全書(shū)注重以實(shí)例為依托講解知識(shí)要點(diǎn),注重從實(shí)踐中獲取知識(shí)。教學(xué)過(guò)程可以先略講開(kāi)發(fā)理念,配以用實(shí)例講解加深理解,再上機(jī)實(shí)踐獲取實(shí)戰(zhàn)經(jīng)驗(yàn)。
8 結(jié)束語(yǔ)
敏捷軟件開(kāi)發(fā)所提倡的開(kāi)發(fā)理念能較好地解決軟件工程教學(xué)的問(wèn)題。本文提出并分析了基于敏捷軟件開(kāi)發(fā)的軟件工程教學(xué),選用極限編程通過(guò)結(jié)合理論和實(shí)際軟件開(kāi)發(fā)項(xiàng)目來(lái)教授軟件工程知識(shí),通過(guò)選擇用戶(hù)故事,把故事分解為任務(wù),編寫(xiě)測(cè)試和實(shí)現(xiàn)代碼,通過(guò)集成測(cè)試腳本等,讓同學(xué)們?cè)趯?shí)踐中理解軟件開(kāi)發(fā)的理論與方法。