成人午夜激情影院,小视频免费在线观看,国产精品夜夜嗨,欧美日韩精品一区二区在线播放

當前位置:首頁>>軟件教程>>新聞內容  
協作開發中的質量保證技術
作者:司徒彥南 發布時間:2003-12-30 15:06:31 | 【字體:

——并行版本控制、每日構建和交付工程

目錄

  • 摘要
  • 問題的提出
  • 并行版本控制——多人協作開發的有效保障
  • 代碼提交和同步
  • 編碼過程中的溝通紐帶——commit mail
  • 日常測試——每日構建
  • 有效的版本控制——代碼分支、版本標記
  • 特性凍結與代碼凍結
  • 交付工程
  • 總結
  • 參考文獻
  • 作者簡介
  • 摘要

    本文以cvs為例,介紹了軟件工程中,編碼過程中對于版本控制的運用的一些技巧。在最后部分,還介紹了軟件工程最后的“交付工程”。

    問題的提出

    編碼過程是軟件工程的重要一環。這一部分工作的好壞直接關系到軟件產品的質量。高效率的多人協作開發,依賴于團隊精神、設計師對于軟件架構的整體把握、好的并行版本控制技術,以及制度化的每日構建和最后階段的交付工程。

    今年六月,我有幸在一家開發安全軟件的公司觀摩了他們的每日構建和交付工程中的活動。他們對于并行版本控制、每日構建技術熟練而深入的應用給我留下了非常深刻的印象。在此,我愿與讀者一同分享我自己的學習體會,這其中的某些部分得益于在那家公司的實地觀摩,另一些則來自于我自己參加的實際軟件工程項目的體會。

    毫無疑問地,一個軟件工程項目最有價值的部分還是在它的設計階段。良好的設計能夠讓實現環節變得更有效率,從而極大地提高勞動生產率;而好的編碼規范,則是協同開發的重要基石。限于篇幅,對于前述兩項內容本文將不會過多設計,我將著重介紹軟件工程中編碼與測試環節的一些經驗,這些經驗對于已經擁有優秀的軟件設計師和編程、測試人員,而苦于由于連調、最終測試導致發布頻頻延期的開發團隊來說是非常有益的。

    并行版本控制——多人協作開發的有效保障

    設想一個有4名編程人員的小型開發團隊(以下簡稱“TJRP開發組”),Tom、Jason、Robert和Pat分別負責4個模塊,按照傳統的軟件開發模式,開發將經歷編程-連調-測試-發布4個階段。

    如果最初的設計正確,并且,四個開發人員都是Guru級的程序員而且配合默契,那么這個模式將會運轉良好。然而遺憾的是,Pat剛剛參加工作不久,對于設計師撰寫的設計文檔的理解不夠透徹,而Robert則自作主張地對設計進行了一些修正,更糟糕的是,項目組會議的時候,這些問題沒有及時地被暴露出來,導致Pat和Robert代碼在設計上的“分歧”越來越大。結果,進入連調的階段,Pat和Robert發生了激烈的爭執,在吵得不可開交之后,項目經理終于讓4個人坐到了一起來解決問題,最后,連調階段整整多花了一倍的時間。

    但倒霉的事情還沒有結束。Jason在測試中發現,原本正常的代碼的行為被改變了,并且,他驚訝地發現代碼被某個“別人”改過,在翻箱倒柜地找出某份正常版本的副本之后,他又發現,“別人”修改中的某些地方是必要的。代碼合并和重新測試使得測試階段足足花掉了原先預想3倍的時間。

    可憐的Tom運氣更差,作為主要的代碼復審人員,他不得不閱讀所有的代碼。Robert和Pat的爭吵導致了大量的代碼變動,他不得不重新審核代碼,而Jason的代碼合并引發的新問題又讓他不得不分神去幫助Jason進行調整。

    最后的結果是,軟件開發的成本是預期的2.4倍,發布時間也拖后了不少。我并不是在開玩笑,上面所講的是一個發生在那家安全軟件公司的真實故事。他們的技術經理介紹,在施行了規范的開發制度,以及啟用并行版本控制系統之后,他們認為開發達到了一個全新的水平。并行版本控制系統本身并沒有產生任何代碼,但由于使用這樣的系統,開發的效率被大大地提高了。

    所謂版本控制其實并不是什么復雜的概念。對于開發活動的絕大多數參與者來說,版本控制系統在某種意義上能夠幫助他們做好開發過程中的記錄工作,并且,通過保存文件在不同時期的版本,交付工程師和代碼復審員能夠很容易地縮小搜索問題代碼的范圍,而程序員則可以通過這樣的系統更好地并行協作。一般來說,源代碼的版本控制系統能夠實現以下一些最基本的功能:

    • 保存任意一個源代碼文件的不同版本
    • 記錄修改者、修改原因
    • 當兩個用戶同時修改一個文件時,盡可能地自動合并修改;在不能合并時,給出提示
    • 比較不同版本之間,或與本地副本之間的差異
    • 獲取最新版本的全部源代碼供測試,并允許回退到所保存的源代碼的任意版本
    • 創建代碼分支,便于軟件發布和后期維護(后面將會提到);新的代碼可以合并到這些分支中。
    • 對不同的源代碼給出標記,方便日后審查
    • 訪問控制:阻止未經授權的修改和查閱

    我們知道,技術不是解決一切問題的靈丹妙藥,但是誰也不會否認大規模的機械化生產的效率高于人拉肩扛的手工業作坊,一旦運用得當,技術將極大地改善我們的工作和生活。我們可以看到,上面的功能有效地解決了TJRP開發組所面臨的絕大部分問題,例如:

    • 由于能夠同時修改代碼,并獲取對方的修改,Pat和Robert能夠有效地、盡早地進行溝通
    • 促進開發者之間的交流,每一個修改都必須給出原因,并記錄提交者
    • 測試和連調可以盡早開始,避免模塊之間的不兼容在最后階段被暴露出來而阻礙發布
    • 不同開發者的修改能夠及時合并,并避免由于版本不一致導致的沖突
    • 代碼復審可以針對某一代碼分支進行,從而,允許一些開發者持續地開發下一個版本,而穩定的代碼則可以交付給用戶

    更進一步,以管理者的角度,還有了一些額外的好處,如:

    • 每日構建和測試能夠讓項目經理更好地把握工程的進度
    • 誰作了多少工作,誰工作的更出色,可以在版本控制系統中清晰地體現
    • 分工明確,通過訪問控制,可以避免不了解整個代碼體系的開發人員偶然的錯誤修改導致的全盤崩潰
    • 更重要地,版本控制系統中將保持大量的開發經驗,這對于一個開發團隊來說是一筆無價的財富

    我們可以看到,上述改進集中地體現了一個重要的思想,即:

    及時溝通以預防問題的出現;盡早發現、盡早解決問題;明確獎懲制度,激發開發人員的積極性。

    下面我們將以非常常見的版本控制系統——cvs[1]為例,介紹并行版本系統一些基本的使用原理。

    代碼提交和同步——從update和commit說起

    每當我們開始一個新的修改之前,首先要做的是從代碼庫中提取出一份最新的副本(通過update操作完成);在本地修改、粗調之后,則應盡快將代碼提交回代碼庫(通過commit操作完成)。

    基本的update和commit操作流程如下圖所示:


    圖1. cvs update和commit

    這兩項操作也解決了日常開發大約80%的問題。絕大多數情況下,這部分的工作是相當簡單的,除非出現兩個開發者同時修改同一個文件的情況,例如,兩個開發者同時地修改了同一個文件的同一個版本,這種情形稱為沖突:

    圖2. cvs并行開發中的沖突

    可能開發者B的動作比較快,或者,修改的東西比較簡單,于是他首先提交。在A、B從代碼庫中提取代碼時,最新版本是1.1,于是,B提交的版本被版本控制系統命名為1.2。

    但不久,A想要提交代碼,版本控制系統將拒絕他的提交,因為他的修改基于代碼的1.1版,而目前的最新版本已經是1.2了。cvs提供了自動合并功能,允許在兩個人修改的不是同一行代碼的前提下,自動合并本地修改和最新的代碼,當然,如果趕上兩個人同時修改同一行代碼的情況,cvs也會非!奥斆鳌钡匕褍蓚“英雄所見略同”的地方合并。

    但如果兩個人恰好都修改了同一行代碼,而且改的不一樣怎么辦?cvs會告訴后一個提交的開發者發生了這樣的情況,并且要求他解決問題。代碼中存在的差異將以<<<和>>>標記出來,以方便進行修改。

    簡單說來,當發生沖突時,我們通常約定由后一個提交者解決沖突——當然,他可以選擇忽略這些沖突,但這些操作都會被記錄,更何況,統計顯示,同時將一行代碼修改為兩種不同的樣子這樣的情況在實際開發中很少出現。于是,修改流程繼續,如下圖:

    圖3. 開發者A解決沖突,并提交

    極端情況下,可能出現多個開發者同時修改同一個文件的問題。這一問題基本上可以按照上述的方法解決。當然,為了避免發生這樣的情形,在設計的時候就應該讓每個人工作的代碼盡可能地不重疊。

    下面是非常基本的cvs update/commit操作規范:


    簡單的cvs操作約定

    • 修改文件之前首先update。這意味著修改時的版本盡可能新,一旦發生沖突,解決它的工作量會比較小。
    • 及時commit。本地代碼與代碼庫中的代碼差異越小,別人合并的難度也就越小(他們有比較大的概率能夠拿到新的版本)
    • 將不同的功能單元修改分開commit。一方面,這樣做能夠盡早地commit,減少別人合并的難度;另一方面,由于cvs提供了回退到先前版本的能力,一旦由于某項功能修改造成問題,也很容易將那次修改的內容,而不是整個修改回退到正常的代碼。
    • 同一功能涉及的所有代碼一次commit。不希望將涉及同一功能修改的代碼分開commit,因為這會給日后的追蹤帶來麻煩。
    • 先調試后提交。這將減少別人不會因為同步了中間結果引發問題,甚至發生提交沖突的可能。
    • 寫清commit log(提交日志)。cvs中允許保存commit log,在這里可以寫為什么進行代碼的修改,以及進行了什么樣的修改,清楚的commit log能夠幫助其他開發者在不仔細閱讀代碼的情況下了解修改的內容,從而極大地提高開發效率;另一方面,這些日志對于開發者自己,以及整個開發團隊,都是非常寶貴的財富。

    同步代碼(update)和提交代碼(commit)占到了cvs日常操作的80%以上。從上面的介紹我們可以看出,僅僅依靠這兩項非常簡單的功能,cvs就能極大地改善開發流程,并提高軟件工程的可控性。簡單地說:

    • 全體開發者使用同一個中央代碼庫,從而消除了由于來回復制文件導致的不一致。
    • 發生沖突時,后提交的開發者必須解決它。這名開發者能夠知道是誰引入了沖突,他可以自己解決沖突,也可以與引入沖突的開發者商量如何解決沖突。
    • 測試可以貫穿編碼過程的始終,任何時候引入的新問題都能夠被及時追蹤、快速定位,從而更有效地解決。
    • 由于存在中央代碼庫,代碼審核人員和每日構建人員能夠及時地了解代碼是否存在問題,并幫助項目經理保證開發進度。
    • 有助于幫助開發人員養成嚴謹的工作習慣——規則要求他們將盡可能地提交正確的代碼,并且每個修改必須寫commit log進行說明。
    • 有助于建立更公平的工作質量評估機制。 cvs能夠記錄每個人完成的實際工作量,包括他們因為修正問題等等所作的勞動,以及他們完成代碼的質量情況。這樣,管理者能夠為優秀的開發人員提供更好的工作機會、報酬,等等,這對于鼓舞整個團隊的士氣、提高開發人員的工作積極性都是非常有益的。
    • 促進開發人員之間的交流。盡管cvs本身無法代替交流,但commit log,以及cvs系統獲取任意版本之間差異的能力,能夠幫助開發人員了解對方的想法,并促進他們共同提高。
    • 降低程序開發人員的門檻。由于提供了許多非常方便的協同開發手段, 使用cvs能夠減少協同開發所需要的磨合期,同時,不同層次的開發者之間由于能夠進行經常性的溝通,從而把編碼過程從技能型工作向熟練性工作又推進了一步。這意味著高層次的開發人員能夠去進行更能發揮他們特長的工作,而新手則可以很快地融入到日常的開發活動中來,從而提高勞動生產率,降低開發成本。

    編碼過程中的溝通紐帶——commit mail

    cvs是一項開放性很強的工具,它可以被非常容易地訂制。一般來說,cvs服務器會架設在一臺Unix主機上(我們推薦使用FreeBSD),通過使用腳本語言(例如,Perl),cvs能夠完成一些額外的功能。

    commit mail是commit log在郵件系統上的延伸。下面是一封典型的commit mail,它來自FreeBSD開發團隊:

    phk 2003/10/21 23:32:20 PDT

      FreeBSD src repository

      Modified files:
        sys/geom geom_io.c
      Log:
        Forgotten commit: If a provider has zero sectorsize, it is an
        indication of lack of media.

        Tripped up: peter

      Revision Changes Path
      1.50     +3 -6   src/sys/geom/geom_io.c

    我們看到,上面的這封commit mail中提到了開發者(phk)、提交時間(太平洋時間2003年10月21日23:32:20)、涉及的代碼庫名字(FreeBSD src repository)、修改過的文件(sys/geom的geom_io.c)以及commit log。最后,commit log還提到了提交后文件的最新版本(1.50),修改規模(+3 -6)以及代碼的實際路徑。

    實現上面的功能并不復雜,實際上,您只需要下載一套經過定制的FreeBSD cvs代碼庫(壓縮包不超過40KB),并作少量的調整,就能夠直接使用這些功能(我們將在不久以后發布這些內容)。進行這些訂制甚至不需要基本的Perl和C/C++常識就能夠完成——當然,我想這樣的常識對于軟件開發人員來說,并不算是很高的要求。

    commit mail可以通過郵件列表發給全體開發者。許多大的軟件公司,以及開放源代碼團體,都采用這樣的方式來協調開發活動。

    日常測試——堅持每日構建

    傳統的軟件工程中,測試發生在連調之后。這么做的理論依據是,測試依賴于一份一致的、至少能夠正常編譯并啟動的代碼。而這個條件在連調之前是無法滿足的。

    然而在有了版本控制系統(如, cvs)之后,連調變成了開發中的日常行為。代碼幾乎在每一時刻都處于高度的一致狀態,甚至在許多時候,代碼會處于可用狀態,從而為測試創造非常有利的條件。

    許多大型開發團隊會使用一臺甚至多臺被稱作TinderBox的機器來完成每日構建和測試。簡單的每日構建流程如下:

    • 測試工程師,或代碼復審員從代碼庫中提取一份代碼的快照
    • 相關人員在TinderBox上進行編譯
    • 編譯的任何錯誤被追蹤,測試工程師或代碼復審員將回退代碼到上一次能夠成功編譯的點,并與此后進行代碼提交的其他開發者進行聯系,解決問題
    • 測試工程師對于代碼進行測試

    其中,第一、二步是可以通過腳本定時、自動完成的,不需要人工干預。第三步中的編譯錯誤在軟件開發中偶爾會發生(這可能來自于沖突合并時引發的問題,但由于開發人員的本地測試,這種文體不會是經常性的),習慣上,這些錯誤會由代碼復審員去追蹤和處理,并交給相關的開發人員解決。

    測試工程師可以將編譯好的版本交付給一個測試組,甚至用戶去進行測試。測試工程師可能隨時發布軟件的“快照”版本。

    實際上在許多大公司中,每日構建是非!凹页1泔垺钡氖虑。我們看到的Internet Explorer版本,如6.0.2600或者類似6.0 Build 2600中的2600的意思就是這份代碼之前已經經歷了2600次每日構建操作(當然,中間肯定進行過不少修改,而且,也不排除這個2600是故意湊整得到的,但總之,他們進行了相當多的日常構建工作)。

    在軟件開發的后期,由于發布的迫在眉睫,每日構建很可能會演化為持續構建,即,每次commit觸發一次構建操作。所有問題立即得到反饋。

    為了支持每日構建或持續構建,比較理想的方法是采用Makefile完成構建操作。對于Unix系統,make工具通常是pmake(BSD Make)或gmake(GNU Make);對于Visual C++,則是nmake。大的開發團體通常使用一組腳本來完成所有的make操作,而對于中小型項目,手工地使用類似VC++這樣的IDE本身的構建功能也是可以接受的。

    基本的每日構建規范如下:


    基本的每日構建和測試注意事項

    • 避免在存在開發人員大規模地進行commit時提取快照。此時提取的中間結果很可能有問題,并導致每日構建從頭做起。通常,測試工程師和代碼復審員在多數開發人員下班的時候開始每日構建,因此,每日構建有時也被稱作每晚構建(Nightly Build)。
    • 標記(tag)每日構建中能夠正確編譯的版本。這將減少第二天每日構建中的麻煩。
    • 及時通知造成問題的開發人員,即,所涉及代碼的提交者。某些公司甚至要求員工開著手機和尋呼機,以保證工期。

    作為commit mail的有效補充,許多項目開發組會建立郵件列表來傳遞一些相關的信息。測試日報通常會發給整個開發團隊的參加人員,此外,保留一個出現過的問題記錄,對于測試環節也會有相當大的好處——這些問題在隨后被反復測試,以保證最終的RELEASE不出現這些問題。

    每日構建并不是可有可無的工作,作為日常測試的重要手段,每日構建能夠有效地幫助管理者了解工程進度,幫助開發者盡早發現問題,同時,也會促進開發組中的交流。

    有效的版本控制——版本標記、代碼分支

    三個文件的“最新版本”分別是1.5, 1.3, 1.4,但最新版本不一定是我們需要的。在這種情況下,版本控制系統提供了一個非常重要的機制——版本標記。例如,我們目前已經確認三個文件的1.4, 1.3, 1.4組合在一起能夠正常運行,于是我們在三個文件的這些版本上標注標記TAG_1,如下圖:

    圖4. TAG_1標記被打到三個文件的不同版本上

    需要說明的是,標記是可以被移動的。這意味著一旦發現標記打錯了,可以把標記移動到別的位置。但在實踐中,標記往往同另一個非常重要的版本控制機制——代碼分支一起使用。在詳細討論標記(tag)的重要意義之前,我們先來看看代碼分支時什么:

    圖5. 比較復雜的情形,一個正在開
    發的項目中的某個文件,已經完成了
    2.0和2.1的發布; 其中,BP是指劃分
    分支的切分點(Branchpoint)

    所謂代碼分支是版本控制中的一個非常關鍵的概念。當開發到某個階段的時候,可以交付一個版本,而主要的開發者則把精力投入到最新版本的開發中。第一個交付分支(2.0)中的一些問題,以及引入的新功能隨后在RELENG_2分支中被修正,公司決定發布2.1版本;此后,2.x中的問題繼續在RELENG_2中被修正,而一些安全更新,則被合并到2.1-RELEASE中(RELENG_2_1)。

    圖5展示的是一個文件上的版本分支。實際的軟件工程項目的源代碼會由大量文件組成,盡管在本質上分支是針對每一個文件說的,但在被標注了同一分支名稱的文件,就像版本標記一樣,能夠表達一組特定版本文件的集合。

    cvs的版本分支功能有一個很大的缺陷,即,大量文件的切分點(Branchpoint, 即某一個分支最初的版本號)在cvs中很難被指定(cvs支持按某一分支、某一特定時間、某一特定版本來提取文件,但通常不同的文件的版本號并不統一,特別是在大型項目中,肯定有某些文件因為被提交的次數很多,而版本號很“高”的情況)。為了消除這個缺陷,在實踐上,我們采用版本標記與分支結合的方法,即,在劃分新的分支之后,在這一分支的這些文件的版本上增加一個版本標記。

    例如:對于軟件的2.0版,在劃分時,將切分出RELENG_2(2.x),RELENG_2_0(2.0)兩個分支,而這時的文件的版本,同時被打上一個RELENG_2_0_0_BP的標記。這樣一來,在以后比較版本時,我們可以使用RELENG_2_0_0_BP來指定這個版本。當不同的分支又增加了許多修改之后,這個標記將極大地減輕代碼復審員的工作量。

    注意,代碼分支并不僅限于版本上的用法。事實上,基于同一代碼基礎的多個不同的軟件也可以采用代碼分支的方法進行開發。而最終,這些代碼還可以合并為一個。

    您可能已經注意到最左邊的一組版本序列:1.1, 1.2, 1.3, 1.4, 1.5. 1.6。在cvs中,這一序列被稱為“主分支(MAIN Branch)”。盡管并非必須,但習慣上,主分支通常是活躍的開發分支。在這個分支中,人們不斷地引入最新的特性,當然,不可避免地,這也可能引發一些問題,而這些引入主分支的問題在隨后將被追蹤、修訂。經過一段時間之后,被“沉淀”下來的代碼可以進入另一個叫做“穩定分支”的代碼系。

    這樣的開發模式通常被稱作“多頭并進”模式,這樣的模式在許多開放源代碼的軟件開發中非常常見,例如,Linux的單、雙號版本、FreeBSD的-STABLE和-CURRENT[2],等等。在一般的商業軟件開發中,這種模式也相當常見,特別是在大公司的開發中。擁有多頭并進這一能力對于大型軟件的開發尤為重要,因為大型軟件很可能包含相當多的模塊,通過版本控制,問題能夠很容易地被整個開發團隊追蹤。

    多頭并進的開發環境中,開發人員可以在粗略熟悉了某個分支的代碼體系的情況下參與開發或維護,這意味著,即使某個代碼分支的維護人員突然離去,其他人也不用擔心通盤閱讀不同分支的代碼可能造成的理解困難,換言之,對于新的維護人員的要求被降低,從而,軟件的開發和維護過程能夠更為有序地進行。

    據我所知,FreeBSD的軟件開發過程極大地得益于多頭并進的開發模式。下面簡單地介紹一下FreeBSD所采用的軟件開發模式:


    案例:FreeBSD開發模式中對于多頭并進的應用

    FreeBSD包括了兩個主要的開發分支:4-STABLE和5-CURRENT,以及若干安全分支。其中,4-STABLE(RELENG_4分支)代表的是FreeBSD 4.x系列的開發,其關注的焦點是系統的穩定性和性能;5-CURRENT(HEAD分支)代表的是FreeBSD 5.x系列的開發,它關注的焦點是盡可能多地引入最新的操作系統特性,全新的設計思想,等等。除此之外,還有一些被稱作安全分支的分支,它們分別代表FreeBSD 2-STABLE, 3-STABLE, 4.6-RELEASE, 4.7-RELEASE, 4.8-RELEASE以及即將推出的4.9-RELEASE等等,但這些分支完全不引入任何新的特性,只有安全更新能夠被加入到這些分支中。

    FreeBSD的“安全分支”是一個非常重要的概念,在FreeBSD的開發中,這些分支基本上只由一個包括了少量開發者(目前只有兩人)的,被稱為“FreeBSD安全官”的團隊維護。對于很多用戶來說,他們并不在乎操作系統是否擁有新的特性——他們不愿意嘗試新版本的軟件,因為現有的系統工作的非常好。這些用戶使用“安全分支”的FreeBSD操作系統,因為他能夠提供必要的安全更新,而操作系統特性并不會因此發生變化(無論這種變化是否能夠改進性能,或提供一些眩目的功能,甚至支持新的硬件,因為用戶的系統已經放在那里了)。

    CURRENT分支走的是另外一個極端。所有的新特性,一旦被特定的工作人員(committer)測試通過(大的變化需要核心團隊,即core team的批準,但這種情況并不是很多),就允許被引入CURRENT分支。盡管CURRENT分支在絕大多數時間都能夠被正確地編譯,但引入新特性有時會不可避免地帶來一些問題,例如硬件適應性問題。

    在這兩個極端之間,有一條中間路線,即STABLE分支。在CURRENT分支中提交的代碼通常會被指定一個MFC(Merge from -CURRENT)時間,在這個時間之后,如果沒有人提交關于代碼的問題,則這些代碼會被引入STABLE分支。

    這樣,STABLE分支的代碼幾乎都是經過相當長時間測試的代碼,對于大多數用戶來說,STABLE分支是一個很好的選擇。

    一般來說,FreeBSD中的代碼會經歷下面的歷程:

    • 代碼被引入CURRENT分支
    • 相關開發者獲得來自用戶的反饋; 在確認基本沒有問題的情況下,代碼被引入STABLE分支
    • 大多數最終用戶使用STABLE分支的代碼來支持他們的計算機

    我們可以看到,上面的開發模式同時照顧到了開發者和用戶群體的利益。一方面,活躍的開發不會因為影響到了大量的普通用戶而遭到指責;另一方面,在開發分支(CURRENT)的代碼經過一段時間被引入STABLE,最終用戶能夠得到那些新的操作系統功能。

    事實上,上述開發模式已經被證明是相當成功的。由于開發過程中每一天都有相當多的人對新的CURRENT和STABLE分支的代碼進行測試,因此,在最近的幾年中,FreeBSD的開發一直呈現著良好的態勢。

    交付工程(Release Engineering)基礎——特性凍結和代碼凍結

    許多參與過大型項目開發的讀者可能都經歷,至少是聽說過特性凍結和代碼凍結這樣一個概念。所謂“特性凍結”實際上是一個開發者之間的約定,在這個階段中,不再允許添加新的功能。

    特性凍結(Feature Freeze)通常在一個開發分支(Development Branch)躍變為交付分支(Release Branch)的時候開始。之所以需要特性凍結,是因為增加新的特性很有可能引入新的問題,而這將給代碼復審帶來沉重的負擔,甚至導致一次不成功的最后交付。

    當然,對于那些已經明確地定義了特性表的小型軟件工程項目(例如,傳統的瀑布開發模型)來說,特性凍結沒有什么意義,因為在這些工程中,詳細設計完全是在編寫代碼之前進行的,這意味著,代碼將要寫成什么樣子已經在詳細設計中明確地定義。但在實際的項目中,詳細設計往往會包括兩類不同的類型要求——一部分是“必須實現的特性(Must have feature)”,另一部份則是“希望實現的特性(Desired Feature)”。在交付之前,所有“希望實現的特性”都會在特性凍結時被明確成“實現特性”和“不實現特性”。

    我們注意到,這種情況下,某些特性被延遲到接近交付的時候才被明確成“必須實現”,而另一些“希望實現的功能”則被作為“不實現”,從而轉化為我們先前熟悉的樣子,即詳細設計文檔中明確地定義了軟件中的所有特性。

    這樣做的結果是軟件工程項目具有更大的靈活性。由客戶需求產生的功能設計,很顯然地,應該列為“必須實現的特性”,而那些開發團隊提出的能夠提高軟件整體可擴展性、可伸縮性或其他性能的特性,則應列為“希望實現的特性”。在特性凍結之后,整個開發團隊將專注于那些“實現特性”(盡管這些特性可能還沒有被正式的實現)更加穩定,從而將生產出更高質量的軟件。

    根據我個人的經驗,特性凍結應該發生在預期編碼時間已經用去大約2/3的時候。這時,項目經理應該組織開發人員舉行一次會議討論特性凍結,而在特性凍結之后,在軟件正式交付之前,任何開發人員都不應該再去考慮那些被列為“不實現特性”的功能。

    代碼凍結是一個與特性凍結類似的概念,在這個階段,只允許對被凍結代碼分支中的錯誤進行修正,而不允許任何其他的、涉及功能的修改。實踐上,這個過程中,只有交付工程師(通常是一個或多個對于整個系統架構非常了解的、有豐富開發經驗的代碼復審員)被授予審查和批準代碼提交的權力,任何代碼修改,只要沒有經過交付工程師的批準,就不能被提交到代碼庫中。

    代碼凍結的時間一般不需要太長。對于中等規模的項目,這一過程通常會持續一至兩周,對于大型項目,這一過程則有可能持續一個月甚至更長的時間。在這個階段,交付工程師主要負責代碼復審,而測試工程師則有責任及時反饋集中的測試中暴露出的問題,并與相關的開發人員聯系、解決這些問題。

    技術上,代碼凍結可以通過修改cvs中的配置來實現。不過,更好的辦法是通過制度來保證代碼凍結。

    交付工程——編碼階段的總結

    交付工程的好壞在某種意義上,是直接關系到用戶利益的部分。前面已經說了相當多的關于軟件開發過程中通過版本控制技術來提高開發效率的技巧和方法,這里我將繼續說一說交付工程。

    前面提到了每日構建中在代碼上適當地打上版本標記,以及在劃分版本分支時在切分點上增加版本標記,這些對于交付工程都具有非常重要的意義。交付工程,在軟件工程項目中是一個融合了代碼復審和集中測試的重要階段。


    交付工程的一般程序

    • 在項目進行到某個特定的階段,交付工程師同其他主要的項目管理者商議決定宣布代碼凍結和交付工程開始。
    • 交付工程師對代碼進行集中的復審,而測試工程師則組織進行大規模的集中測試。
    • 交付工程過程中,交付工程師每隔一段時間發布一個“交付候選版本(Release Candidate)”,測試工程師跟隨安裝并測試這些交付候選版本。
    • 此間,測試工程師隨時向交付工程師反饋問題,交付工程師將問題分類、整理,并約見相應的開發人員,予以解決。
    • 最終,某個“交付候選版本”被最終指定為交付版本(Release)。代碼凍結結束,軟件被交付給客戶。

    一些讀者可能已經注意到,交付工程的絕大多數任務事實上已經被融入了我前面所描述的開發過程——在編碼階段的整個過程中,代碼復審、問題反饋和測試一直是持續地進行的,只是,在“交付工程”階段,代碼復審和測試被提升到了一個更為核心的地位,在這一階段,開發的重要任務是查錯和排錯,而不再是將軟件的功能推向一個嶄新的水平。

    總結——基于版本控制、每日構建的編碼過程

    前面我們已經介紹了通過引入版本控制系統改善軟件工程中編碼和測試階段過程的一些方法。這些方法來自于我本人所參與的,以及通過一些其他途徑了解到的實際項目的開發經驗。文中介紹的內容以cvs (Concurrent Version System)為主,這是因為cvs比較容易得到(它本身是開放源代碼軟件),并且,比較成熟。另外,由于關于cvs本身的細節并沒有涉及很深,因此,讀者也很容易將這些經驗套用在其他版本控制系統,如Bit Keeper, Perforce, Clear Case等等之上。

    引入版本控制、每日構建之后,項目管理人員和開發者可以明顯地感受到以下改善:

    • 問題能夠盡早暴露,并被解決。測試過程被滲透到開發過程中,有利于及早發現問題。日常的每日構建和測試意味著更多的測試者可以盡早地參加到測試工作中,并與開發團隊并肩作戰,及時地為他們提供第一手的資料;而最終的交付工程中進行的測試,只是驗證軟件的質量確實達到了設計要求,而不再肩負發現問題的重大責任,這意味著很難出現最后階段發現嚴重問題而導致工期大大加長的尷尬局面。
    • 每個人做了多少工作在版本控制系統中能夠非常有效地體現,這對于更客觀地評價一位開發者的能力,明確獎懲和提高員工積極性,都有非常積極的意義。
    • 管理者能夠隨時觀察工程的進度情況,并且,每日構建的到的版本也可以交付給客戶,從而改善軟件開發團隊同客戶之間的交流。
    • 版本控制系統記錄的軟件工程的進展,對于今后的開發將是一筆寶貴的財富。

    最后,讓我們用圖片的形式,重新描述一下上面的那些過程:

    圖6. 日常開發過程

    圖7. 交付工程

    這樣,我們已經粗淺地討論了關于并行版本控制技術如何改變軟件開發過程的一些大致的方法,以及其中的一些先進思想。在文中我盡可能地回避了類似cvs系統的操作具體細節,并且,避開了一些cvs特有的功能;旧希疚闹刑峁┑姆椒,特別是其中的一些思想,能夠適應任何一種版本控制系統,因此,這些方法具有相當大的普遍意義。

    參考文獻

    [1] CVS - 并行版本系統 http://www.cvshome.org
    [2] FreeBSD 4.4交付工程, Murray Stokely
    [3] CVS使用手冊- CVS WinCVS CVSWeb CVSTrac,車東
    [4] 4.3BSD交付工程, Marshall Kirk McKusick, Michael J. Karels, and Keith Bostic

    作者簡介

    李鑫,北京工業大學計算機學院2000級學生,目前擔任計算機學院學生科協主席、放飛技術網技術總監。您可以通過電子郵件 ( delphij@frontfree.net 與他聯系 )。

    版權聲明

    本文版權歸原作者和放飛技術網共同所有,轉載本文必須同我們聯系并獲得同意(書面或PGP簽署的許可)。


    文章來源:放飛技術網
     放生
     愚愛
     夠愛
     觸電
     白狐
     葬愛
     光榮
     畫心
     火花
     稻香
     小酒窩
     下雨天
     右手邊
     安靜了
     魔杰座
     你不像她
     邊做邊愛
     擦肩而過
     我的答鈴
     懷念過去
     等一分鐘
     放手去愛
     冰河時代
     你的承諾
     自由飛翔
     原諒我一次
     吻的太逼真
     左眼皮跳跳
     做你的愛人
     一定要愛你
     飛向別人的床
     愛上別人的人
     感動天感動地
     心在跳情在燒
     玫瑰花的葬禮
     有沒有人告訴你
     即使知道要見面
     愛上你是一個錯
     最后一次的溫柔
     愛上你是我的錯
     怎么會狠心傷害我
     不是因為寂寞才想
     親愛的那不是愛情
     難道愛一個人有錯
     寂寞的時候說愛我
    主站蜘蛛池模板: 宁安市| 甘孜县| 朔州市| 凌源市| 玛曲县| 潼关县| 土默特左旗| 鄂托克旗| 阿坝县| 中卫市| 漯河市| 宁国市| 个旧市| 博客| 烟台市| 宁晋县| 治县。| 江陵县| 无极县| 呼玛县| 西安市| 专栏| 南华县| 泸州市| 韶山市| 泉州市| 东城区| 青河县| 宜章县| 客服| 南川市| 明水县| 疏勒县| 应用必备| 郁南县| 马公市| 铁力市| 北安市| 东台市| 察哈| 安仁县|