某一開發(fā)團隊為其客戶開發(fā)業(yè)務軟件,系統(tǒng)上線之后存在著很多的業(yè)務需求變更,同時也有很多業(yè)務部門在使用過程中所發(fā)現的軟件缺陷,我們把需求變更和軟件缺陷統(tǒng)稱為變更。開發(fā)團隊需要迅速響應客戶所提出變更請求,把相應的軟件版本修復及時地安裝到生產系統(tǒng)上去。
為了保證產品質量,該開發(fā)團隊建立了以下的軟件發(fā)布流程:
這四個環(huán)節(jié)分別對應以下四種環(huán)境:
開發(fā)環(huán)境:開發(fā)實現客戶的變更請求
測試平臺:開發(fā)團隊把軟件發(fā)布給客戶之前做內部系統(tǒng)測試
準生產環(huán)境:客戶把軟件發(fā)布到生產系統(tǒng)之前做驗收測試
生產系統(tǒng):最終的生產系統(tǒng)
當開發(fā)團隊將變更實現提交用戶驗收測試時,凡是沒有通過驗收測試的變更將被拒絕,只有通過驗收測試的變更才會被部署到生產系統(tǒng)上去。整個流程如下圖所示,假設開發(fā)團隊總共實現了3個變更,其中變更1和變更2通過了系統(tǒng)測試被提交用戶驗收測試,但只有變更1通過了用戶驗收測試,最終只有變更1被部署到生產系統(tǒng)上。
為了支持這種工作流程,該團隊分別在配置管理系統(tǒng)中管理了四種源代碼版本:
凡是通過每一個環(huán)節(jié)的變更所對應的源代碼版本,將被復制到下一個環(huán)節(jié)的版本基線中去??瓷先ミ@一流程非常合理,不是嗎?
讓我們來看這種流程的兩個應用案例。
在下面的例子中,文件f1、f2在修改之前的版本都是1,在實現了變更1、變更2后,它們的版本都變?yōu)榱税姹?,表示為f1(v2)、f2(v2)。在整個的測試過程中,前面三個環(huán)境上測試的代碼版本始終是文件f1和f2的版本2,但是最后變更1沒有通過驗收測試而變更2通過了,那么最終被部署到生產系統(tǒng)上去的版本將是:
f1(v1,這是f1原來在生產系統(tǒng)上的版本)
f2(v2,其中已包含了變更2所對應的版本2)
但f1(v1)應該是跟f1(v1,變更1修改以前的版本)相匹配的版本組合,跟f2(v2)相匹配的版本組合應該是f1(v2),由此可能發(fā)生的結果是:
在生產系統(tǒng)上運行的是未經測試的版本組合!
在下面的例子中,在前面三個測試環(huán)節(jié)中,文件f2被測試的版本都是版本4。當變更2未通過用戶驗收測試時,文件f2最終被復制到生產系統(tǒng)上的版本為3,這個版本是未經測試的。
結果令人難以置信:
在生產系統(tǒng)上運行的是未經測試的版本?!
任何一個軟件系統(tǒng),它的所有代碼應該被作為一個整體來進行交付,而不是象上述例子中那樣只交付部分的代碼(變更相關的代碼),這是造成質量陷阱的根本原因。一個看上去合理的流程存在本質的缺陷。
為了避免以上所述的這些質量陷阱,我們應該改進現有的配置管理流程。
造成以上質量隱患的根本原因是系統(tǒng)代碼沒有被作為一個整體來處理,并且在發(fā)布過程中我們發(fā)布的是源代碼,正確的流程(也是業(yè)界較為通行的做法)應該發(fā)布構建后的目標碼而非源代碼。我們可以建立一個閉環(huán)的質量保證流程(如下圖所示)來批量地進行軟件發(fā)布。
其中系統(tǒng)測試過程中發(fā)現的缺陷應該被開發(fā)人員及時改正,然后再做構建,再測試,直到達到一個比較穩(wěn)定的版本才會發(fā)布到驗收測試環(huán)節(jié)。同樣的,驗收測試中發(fā)現的問題也會回到開發(fā)環(huán)節(jié)進行修復。這應該是一個多次循環(huán)的過程,不斷地發(fā)現錯誤,然后改正,再測試。這個循環(huán)到什么時候結束呢?這個取決于各個軟件項目的實際情況:
◆ 最理想的情況當然是到所有的缺陷都被改正為止,但是所花的時間比較長,可能趕不上項目的進度要求,現實工作不大可能做到這一點。
◆ 折衷的情況是所有嚴重的缺陷(即那些影響系統(tǒng)使用的的缺陷)都必須被改正,但允許有一些已發(fā)現的缺陷遺留到后面再去解決,前提是所遺留的缺陷不會影響其他變更的實現。大家平時在一些商用軟件的新版本中經??梢砸姷?strong>發(fā)布說明(Release Notes)中所列的已知缺陷(Known Defects)就是屬于這種情況。
我們向開發(fā)團隊提出這個建議后,馬上遭到項目經理的反對:“客戶有些緊急的變更需要馬上實現并交付生產運營,幾乎沒有時間來走這樣完整的閉環(huán)流程?!?/p>
通過進一步了解我們發(fā)現:
緊急的變更一般是指影響系統(tǒng)正常使用的軟件缺陷,這些缺陷需要及時的修復;而新增功能請求一般不是那么緊急的,允許開發(fā)團隊有一段時間來開發(fā)實現。
但開發(fā)人員目前是把所有緊急和非緊急的變更請求混雜在一起實現的,往往是一個緊急的缺陷已經修復,但另外一個正在開發(fā)中的新增功能也修改了同一組文件版本,造成兩者之間的版本依賴,從而導致緊急的缺陷修復不能按時提交。
我們建議:
把缺陷的修復工作和新增功能的開發(fā)工作區(qū)分開來。
這就涉及到多個版本的并行開發(fā),開發(fā)團隊主要面臨以下三個版本的開發(fā):
◆ v1.0中的缺陷修復
◆ v1.0的新增功能版本v1.1
◆ 下一個版本v2.0
這樣缺陷修復和新增功能開發(fā)相互獨立,保證緊急的缺陷修復不會受到新增功能的影響。
這個案例中另外有一個不符合配置管理慣例的地方是,在開發(fā)、測試、驗收、生產四個環(huán)節(jié)發(fā)布的都是源代碼,分別需要構建(包括編譯)過后才能部署到相應的運行平臺上。
由于軟件構建的結果很可能會受構建平臺及相應編譯器版本所影響,最終在生產系統(tǒng)上的運行代碼(在生產系統(tǒng)上構建得到)與準生產環(huán)境上的運行代碼(在準生產環(huán)境上構建得到)可能不完全一致,有可能造成質量隱患。
比較通行的做法是所有平臺上運行的構建代碼應該只在構建服務器上生成一次,一次編譯到處運行,這樣才能保證各個平臺上所用到的同版本運行代碼是同一次構建的產物。
構建服務器通常就是由開發(fā)平臺兼任,但如果是發(fā)布多個不同運行平臺的版本的話,可以有多個構建服務器存在,如:同一個軟件既有 AIX + DB2 平臺的運行版本,也有 HPUX + Oracle 平臺的運行版本。
除了某些特殊的運行環(huán)境外,如IBM主機系統(tǒng)(mainframe)上明確要求在運行平臺上對源代碼進行編譯構建,一般軟件系統(tǒng)的開發(fā)都可以遵循這一個工作原則。
對于所發(fā)布的構建版本,我們也需要進行有序的管理,可以用版本號來唯一標識每一個發(fā)布版本。
一般可以把用于開發(fā)團隊內部系統(tǒng)測試的稱之為內部發(fā)布版本,把提交給客戶的稱之為外部發(fā)布版本,這兩種軟件發(fā)布版本都要統(tǒng)一編號管理。
在我們的例子中,內部發(fā)布版本可以簡單地用構建號來表示,如:
v1.0_build_008,表示版本v1.0開發(fā)過程中生成的第8次構建
外部發(fā)布版本可以由版本號和發(fā)布號組合而成,如:
v1.0_rel01,表示版本v1.0的第一個外部發(fā)布版本
對于v1.0中的缺陷修復,我們可以通過補丁的方式來發(fā)布,一個補丁中可以包含有多個缺陷修復,被修復的缺陷需要在補丁的發(fā)布說明(Release Notes)中寫明,補丁名稱可以由版本號、發(fā)布號和補丁號組合而成,如:
v1.0_rel01_p001 表示針對發(fā)布版本v1.0_rel01的第001號補丁
對于v1.0中新增功能,我們需要制定一個發(fā)布計劃,根據客戶新增功能請求的緊急程度來分期分批實現,一次發(fā)布中可以包含多個新增功能,并且包括所有已改正的軟件缺陷,這些改動都必須在發(fā)布說明中寫明,發(fā)布版本號可以在前一個發(fā)布版本的基礎上遞增,如:
v1.1_rel02,表示版本v1.1的第二個外部發(fā)布版本。
對于下一個版本v2.0的開發(fā),則與版本v1.0開發(fā)的發(fā)布管理完全一致,如:
v2.0_build_002 表示版本v2.0開發(fā)過程中生成的第2次構建
在版本發(fā)布管理的流程中,發(fā)布版本的安裝應該由專門的角色負責,可以是配置管理員或者是集成員(integrator)。
開發(fā)人員被禁止向各平臺(測試平臺、準生產環(huán)境、生產系統(tǒng))上安裝任何軟件,并且各平臺上所安裝軟件的版本號都應該有詳細的記錄。
當軟件缺陷被發(fā)現時,我們就可以明確知道問題究竟是出在哪一個版本。
內部發(fā)布版本只會被安裝到測試平臺上,經過 “開發(fā)→ 構建→ 測試→ 發(fā)現缺陷→ 修改代碼” 的多次循環(huán)之后,內部發(fā)布版本的質量趨于穩(wěn)定,開發(fā)團隊才會決定做一個外部發(fā)布版本。
外部發(fā)布版本被安裝到準生產環(huán)境上,并且只有通過用戶驗收測試,它才可以被安裝到生產系統(tǒng)上去。
如果該版本沒有通過用戶驗收測試,那么開發(fā)團隊需要提供相應的補丁來解決用戶驗收中發(fā)現的問題,直到通過用戶驗收后再將該發(fā)布版本及其所有的累積補丁全部安裝到生產系統(tǒng)上去。
有些情況下,最終通過驗收測試的也可能是下一個發(fā)布版本,所以生產系統(tǒng)上安裝的發(fā)布版本前后之間不一定是連續(xù)的,中間可能跳過一些質量不夠成熟的版本。
同樣的,只有通過用戶驗收測試的補丁才會被最終安裝到生產系統(tǒng)上去。緊急的補丁經過用戶驗收測試之后會馬上安裝到生產系統(tǒng)上,不緊急的補丁可以累積幾個以后批量安裝上去。
配置管理工具 IBM Rational ClearCase 可以很好地支持這種并行開發(fā)模式。在 ClearCase UCM (Unified Change Management,統(tǒng)一變更管理流程)工作模式中,我們可以在版本v1.0的發(fā)布版本基線(v1.0_rel01)的基礎上分別創(chuàng)建針對三種版本(v1.0_bugfix, v1.1, v2.0)的開發(fā)項目,如下圖所示。
在 ClearCase 的管理下,這三種版本位于不同的分支上,它們的開發(fā)是獨立的,互不影響;并且版本 v1.0_bugfix 中的缺陷修復可以及時地合并到版本 v1.1 和 v2.0 中去,版本 v1.1 中的新增功能也可以在需要的時候合并到版本 v2.0 中去。(如下圖所示)
ClearCase 也為開發(fā)人員提供了方便易用的工作界面 ClearCase Explorer,開發(fā)人員可以方便地選擇任何一個版本項目來進行開發(fā)工作,ClearCase Explorer 可以迅速準確地準備相應的工作版本。所以這三種不同版本的開發(fā)完全可以由同一組開發(fā)人員來完成,大大提高了開發(fā)的工作效率。
在這個案例學習中我們看到配置管理流程對于保證軟件質量起著非常重要的作用,不恰當的流程可能導致潛在的質量缺陷,開發(fā)團隊需要根據自身項目的情況來制定一個高效合理的配置管理流程。有了一個好的流程,還需要一個好的配置管理工具來簡化我們的管理工作,從而保證開發(fā)人員的工作效率和軟件質量。