持續(xù)交付與傳統(tǒng)敏捷的矛盾
我在采用持續(xù)交付的組織中和開發(fā)團隊工作一起工作,發(fā)現(xiàn)很多開發(fā)者認為的正確的敏捷團隊的工作方式,在這里跑得不是很順暢。我認為傳統(tǒng)敏捷與持續(xù)交付的矛盾的根本在于,二者是采用不同的方式把軟件變得“可以發(fā)布“(ready to release)的。
軟件交付的演進
使軟件變得可以發(fā)布的過程一直在不停進化,下面是一個簡要的介紹:
瀑布模型
瀑布模型認為,當(dāng)一個軟件所有的功能都發(fā)開完畢的時候(也就是功能完整的時候),才可以發(fā)布。
敏捷:
敏捷引入的思想是,在整個開發(fā)過程中,軟件都應(yīng)該“可以發(fā)布”。許多敏捷的版本(在這篇文章里被稱為傳統(tǒng)敏捷)都認為,“可以發(fā)布”應(yīng)該在固定周期的間隔點上完成。
持續(xù)交付:
持續(xù)交付是敏捷的一個子集,在持續(xù)交付中團隊會保持軟件在開發(fā)過程的所有時間內(nèi)都可以發(fā)布。它和傳統(tǒng)敏捷不同之處在于,持續(xù)交付在開發(fā)過程中不會有停下來然后創(chuàng)建發(fā)布版本的過程。
持續(xù)性交付不是指更短的周期
從傳統(tǒng)的敏捷開發(fā)流程變成可持續(xù)性交付,不是指把軟件發(fā)布的周期變短。每天晚上做發(fā)布版本仍然不是可持續(xù)性交付。可持續(xù)性交付是說要把”做可以發(fā)布的軟件”這個動作本身從開發(fā)過程中去掉,取而代之的是保持軟件在開發(fā)的過程中始終是可以發(fā)布的。
可以發(fā)布不是意味著真正的發(fā)布
有一個普遍的誤解是可持續(xù)性交付就是非常頻繁地發(fā)布出產(chǎn)品。而當(dāng)一些組織把每天數(shù)次發(fā)布軟件當(dāng)作是持續(xù)交付的標(biāo)桿時,就更加深了這一誤解。可持續(xù)性交付不是一定要頻繁的發(fā)布,它只是要求在開發(fā)過程中的任何一個點上,用非常少的工作,軟件就能夠發(fā)布(可參考Jez Humble的文章,可持續(xù)性交付VS可持續(xù)性部署)。盡管具備這一能力為更加頻繁的發(fā)布敞開了大門,但是許多團隊還是從持續(xù)交付的實踐中,找到了壓倒性的證據(jù),來證明即便發(fā)布不是很頻繁時,持續(xù)交付也是有用的。
持續(xù)交付和傳統(tǒng)敏捷的沖突點
我前面講過,有時候持續(xù)交付和開發(fā)團隊所認為是“正確”的敏捷實踐流程有一些矛盾。
沖突點:當(dāng)有工作沒有完成時,軟件依然是可發(fā)布的
其中一個沖突點是,一個迭代結(jié)束時,代碼庫中是否可以包含未完成的用戶故事(user stories)或者bug修復(fù)。我在上一篇關(guān)于迭代的帖子中做了探討。這個問題主要是源于,傳統(tǒng)敏捷認為在迭代結(jié)束時,team停止開發(fā),并且來做準備軟件發(fā)布的一些額外工作,但是,如果團隊采用持續(xù)交付,讓軟件可發(fā)布就沒什么額外的工作需要做。
更有甚者,持續(xù)交付團隊甚至認為,通過使用功能切換等技術(shù),他們的代碼即使在還有功能沒有完成也可以發(fā)布成產(chǎn)品。這也從另外一個方面說明,團隊在迭代結(jié)束時能夠達到可以發(fā)布的要求,即使有未完成的用戶故事。
這可能稍微有點難理解,團隊肯定還是可以要求在迭代結(jié)束點上所有的工作都必須完成,但是這容易讓人感覺是團隊原有的正常開發(fā)的節(jié)奏被隨便打斷了。持續(xù)交付不是要求沒有時間盒的迭代,這兩種實踐其實是互補的。
沖突點:snapshot(軟件快照)/發(fā)布版本(release build)
許多開發(fā)團隊把軟件的版本分為“snapshot”版本和“release”版本。這個并不是敏捷所特有的,而是隨著Maven的興起,被深深植入了Java開發(fā)中,因為Maven把snapshot的概念放入了它的設(shè)計核心中。這種方案把開發(fā)周期劃分成兩個階段,在軟件開發(fā)過程中使用snapshot,當(dāng)軟件成為可以發(fā)布狀態(tài)時才創(chuàng)建release版本。
很明顯,這種發(fā)布周期的劃分和持續(xù)交付的“軟件應(yīng)該總是可以發(fā)布”的理念是相沖突的。持續(xù)交付通常采用的方式是只在開始創(chuàng)建一次版本,然后通過不同階段的測試驗證等一系列串行工作來對版本進行改進,如果使用Maven,要用兩種方式創(chuàng)建版本,這種方式就不行了。
其實完全可以使用Maven做持續(xù)交付,比如說,為每個版本創(chuàng)建一個release build。當(dāng)然,這個會和Maven的“release build只以生產(chǎn)部署為目的,不會經(jīng)常創(chuàng)建”的理念矛盾。而且,像Nexus和Artefactory這樣的私服都有刪除舊的snapshot版本的清理功能,但不允許刪除release版本。所以一個活躍的持續(xù)交付團隊,一天可以產(chǎn)生幾十個版本,這樣很容易就吃掉服務(wù)器上幾G到幾T的空間。
矛盾點:更著重測試可部署性
標(biāo)準的持續(xù)交付的實踐方式是,通過基本的持續(xù)集成自動地把每個版本部署到與真實生產(chǎn)環(huán)境盡量貼近的模擬環(huán)境中,使用相同的發(fā)布流程和工具。這對驗證每次提交的代碼是否是“可以發(fā)布”是至關(guān)重要的,但是這樣對持續(xù)集成的要求比現(xiàn)在大部分開發(fā)團隊正在使用的要高很多。
舉個例子,在沒有要求持續(xù)發(fā)布的持續(xù)集成,可能會使用Ant或者Maven將應(yīng)用發(fā)布到嵌入應(yīng)用服務(wù)器然后進行自動的功能測試。開發(fā)者使用和維護都很方便,但是這很可能不是生產(chǎn)環(huán)境中應(yīng)用發(fā)布的方式。
所以持續(xù)交付團隊會自動化發(fā)布到一個更貼近真實生產(chǎn)的環(huán)境,包括不同的網(wǎng)頁/app/數(shù)據(jù)層,并且使用在真正生產(chǎn)中使用的部署工具。當(dāng)然,這種更像生產(chǎn)的部署階段更加可能出錯,因為它增加了復(fù)雜性,而且可能對開發(fā)者而言更難以維護和修正,因為這些工具更像是給系統(tǒng)管理員而不是給開發(fā)者使用的。
不過這是個機會,可以和管理運營團隊一起創(chuàng)建一個更可靠、更易于支持的部署流程。但是實現(xiàn)和穩(wěn)定這一流程的難度會比較大,可能會影響開發(fā)的進度。
值得采用持續(xù)交付嗎?
考慮到有這么多沖突的地方,那持續(xù)交付有什么好處,值得我們從傳統(tǒng)敏捷遷移過來呢?特別是對于那些實際上不太可能在一次迭代中有好幾次發(fā)布到生產(chǎn)環(huán)境的團隊來說,更是要問這個問題。值得這么做的原因如下:
盡早發(fā)現(xiàn)部署可能遇到的問題以降低風(fēng)險
增加靈活性,組織可以選擇在任何時候發(fā)布,并把附加的代價和風(fēng)險控制到最小
把生產(chǎn)發(fā)布涉及的每個人拉進來(比如QA、運營等),使得整個流程更有效率。組織必須識別出流程中的困難區(qū)域,并且通過自動化、更好的協(xié)作或者改進工作方法等方式找到克服它們的方法。
通過持續(xù)的演練發(fā)布流程,組織會對這個過程很精通,然后發(fā)布就會變得自動化,就像陣痛過后自由的呼吸,像生孩子一樣。
提升軟件質(zhì)量,因為團隊不能再像以前一樣把問題留到后面,他們必須現(xiàn)在就解決。
消除沖突
當(dāng)引入持續(xù)交付的時候,我以上所說的沖突點就會頻繁出現(xiàn)。我希望當(dāng)這些問題出現(xiàn)的時候,了解沖突的根本原因,可以有助于更好地討論并解決它們。如果開發(fā)者一開始不愿意打破他們習(xí)慣的“正確”做事方式,或者認為持續(xù)交付所帶來的串行工作太復(fù)雜,或者很難理解這些實踐的目的和價值,那么我希望他們可以盡量開放地給自己一個機會去嘗試一下。一旦這些實踐方式根植于一個組織并且變得成熟,團隊成員們往往會覺得很難退回到以前的做事方式。
編者按:我重新定義了“傳統(tǒng)敏捷”中讓軟件可以發(fā)布的方式。這個定義不是適用于所有敏捷實踐,但是就我看到的,大部分主流概念都認為敏捷需要停下工作來將軟件變得可發(fā)布。
我在采用持續(xù)交付的組織中和開發(fā)團隊工作一起工作,發(fā)現(xiàn)很多開發(fā)者認為的正確的敏捷團隊的工作方式,在這里跑得不是很順暢。我認為傳統(tǒng)敏捷與持續(xù)交付的矛盾的根本在于,二者是采用不同的方式把軟件變得“可以發(fā)布“(ready to release)的。
軟件交付的演進
使軟件變得可以發(fā)布的過程一直在不停進化,下面是一個簡要的介紹:
瀑布模型
瀑布模型認為,當(dāng)一個軟件所有的功能都發(fā)開完畢的時候(也就是功能完整的時候),才可以發(fā)布。
敏捷:
敏捷引入的思想是,在整個開發(fā)過程中,軟件都應(yīng)該“可以發(fā)布”。許多敏捷的版本(在這篇文章里被稱為傳統(tǒng)敏捷)都認為,“可以發(fā)布”應(yīng)該在固定周期的間隔點上完成。
持續(xù)交付:
持續(xù)交付是敏捷的一個子集,在持續(xù)交付中團隊會保持軟件在開發(fā)過程的所有時間內(nèi)都可以發(fā)布。它和傳統(tǒng)敏捷不同之處在于,持續(xù)交付在開發(fā)過程中不會有停下來然后創(chuàng)建發(fā)布版本的過程。
持續(xù)性交付不是指更短的周期
從傳統(tǒng)的敏捷開發(fā)流程變成可持續(xù)性交付,不是指把軟件發(fā)布的周期變短。每天晚上做發(fā)布版本仍然不是可持續(xù)性交付。可持續(xù)性交付是說要把”做可以發(fā)布的軟件”這個動作本身從開發(fā)過程中去掉,取而代之的是保持軟件在開發(fā)的過程中始終是可以發(fā)布的。
可以發(fā)布不是意味著真正的發(fā)布
有一個普遍的誤解是可持續(xù)性交付就是非常頻繁地發(fā)布出產(chǎn)品。而當(dāng)一些組織把每天數(shù)次發(fā)布軟件當(dāng)作是持續(xù)交付的標(biāo)桿時,就更加深了這一誤解。可持續(xù)性交付不是一定要頻繁的發(fā)布,它只是要求在開發(fā)過程中的任何一個點上,用非常少的工作,軟件就能夠發(fā)布(可參考Jez Humble的文章,可持續(xù)性交付VS可持續(xù)性部署)。盡管具備這一能力為更加頻繁的發(fā)布敞開了大門,但是許多團隊還是從持續(xù)交付的實踐中,找到了壓倒性的證據(jù),來證明即便發(fā)布不是很頻繁時,持續(xù)交付也是有用的。
持續(xù)交付和傳統(tǒng)敏捷的沖突點
我前面講過,有時候持續(xù)交付和開發(fā)團隊所認為是“正確”的敏捷實踐流程有一些矛盾。
沖突點:當(dāng)有工作沒有完成時,軟件依然是可發(fā)布的
其中一個沖突點是,一個迭代結(jié)束時,代碼庫中是否可以包含未完成的用戶故事(user stories)或者bug修復(fù)。我在上一篇關(guān)于迭代的帖子中做了探討。這個問題主要是源于,傳統(tǒng)敏捷認為在迭代結(jié)束時,team停止開發(fā),并且來做準備軟件發(fā)布的一些額外工作,但是,如果團隊采用持續(xù)交付,讓軟件可發(fā)布就沒什么額外的工作需要做。
更有甚者,持續(xù)交付團隊甚至認為,通過使用功能切換等技術(shù),他們的代碼即使在還有功能沒有完成也可以發(fā)布成產(chǎn)品。這也從另外一個方面說明,團隊在迭代結(jié)束時能夠達到可以發(fā)布的要求,即使有未完成的用戶故事。
這可能稍微有點難理解,團隊肯定還是可以要求在迭代結(jié)束點上所有的工作都必須完成,但是這容易讓人感覺是團隊原有的正常開發(fā)的節(jié)奏被隨便打斷了。持續(xù)交付不是要求沒有時間盒的迭代,這兩種實踐其實是互補的。
沖突點:snapshot(軟件快照)/發(fā)布版本(release build)
許多開發(fā)團隊把軟件的版本分為“snapshot”版本和“release”版本。這個并不是敏捷所特有的,而是隨著Maven的興起,被深深植入了Java開發(fā)中,因為Maven把snapshot的概念放入了它的設(shè)計核心中。這種方案把開發(fā)周期劃分成兩個階段,在軟件開發(fā)過程中使用snapshot,當(dāng)軟件成為可以發(fā)布狀態(tài)時才創(chuàng)建release版本。
很明顯,這種發(fā)布周期的劃分和持續(xù)交付的“軟件應(yīng)該總是可以發(fā)布”的理念是相沖突的。持續(xù)交付通常采用的方式是只在開始創(chuàng)建一次版本,然后通過不同階段的測試驗證等一系列串行工作來對版本進行改進,如果使用Maven,要用兩種方式創(chuàng)建版本,這種方式就不行了。
其實完全可以使用Maven做持續(xù)交付,比如說,為每個版本創(chuàng)建一個release build。當(dāng)然,這個會和Maven的“release build只以生產(chǎn)部署為目的,不會經(jīng)常創(chuàng)建”的理念矛盾。而且,像Nexus和Artefactory這樣的私服都有刪除舊的snapshot版本的清理功能,但不允許刪除release版本。所以一個活躍的持續(xù)交付團隊,一天可以產(chǎn)生幾十個版本,這樣很容易就吃掉服務(wù)器上幾G到幾T的空間。
矛盾點:更著重測試可部署性
標(biāo)準的持續(xù)交付的實踐方式是,通過基本的持續(xù)集成自動地把每個版本部署到與真實生產(chǎn)環(huán)境盡量貼近的模擬環(huán)境中,使用相同的發(fā)布流程和工具。這對驗證每次提交的代碼是否是“可以發(fā)布”是至關(guān)重要的,但是這樣對持續(xù)集成的要求比現(xiàn)在大部分開發(fā)團隊正在使用的要高很多。
舉個例子,在沒有要求持續(xù)發(fā)布的持續(xù)集成,可能會使用Ant或者Maven將應(yīng)用發(fā)布到嵌入應(yīng)用服務(wù)器然后進行自動的功能測試。開發(fā)者使用和維護都很方便,但是這很可能不是生產(chǎn)環(huán)境中應(yīng)用發(fā)布的方式。
所以持續(xù)交付團隊會自動化發(fā)布到一個更貼近真實生產(chǎn)的環(huán)境,包括不同的網(wǎng)頁/app/數(shù)據(jù)層,并且使用在真正生產(chǎn)中使用的部署工具。當(dāng)然,這種更像生產(chǎn)的部署階段更加可能出錯,因為它增加了復(fù)雜性,而且可能對開發(fā)者而言更難以維護和修正,因為這些工具更像是給系統(tǒng)管理員而不是給開發(fā)者使用的。
不過這是個機會,可以和管理運營團隊一起創(chuàng)建一個更可靠、更易于支持的部署流程。但是實現(xiàn)和穩(wěn)定這一流程的難度會比較大,可能會影響開發(fā)的進度。
值得采用持續(xù)交付嗎?
考慮到有這么多沖突的地方,那持續(xù)交付有什么好處,值得我們從傳統(tǒng)敏捷遷移過來呢?特別是對于那些實際上不太可能在一次迭代中有好幾次發(fā)布到生產(chǎn)環(huán)境的團隊來說,更是要問這個問題。值得這么做的原因如下:
盡早發(fā)現(xiàn)部署可能遇到的問題以降低風(fēng)險
增加靈活性,組織可以選擇在任何時候發(fā)布,并把附加的代價和風(fēng)險控制到最小
把生產(chǎn)發(fā)布涉及的每個人拉進來(比如QA、運營等),使得整個流程更有效率。組織必須識別出流程中的困難區(qū)域,并且通過自動化、更好的協(xié)作或者改進工作方法等方式找到克服它們的方法。
通過持續(xù)的演練發(fā)布流程,組織會對這個過程很精通,然后發(fā)布就會變得自動化,就像陣痛過后自由的呼吸,像生孩子一樣。
提升軟件質(zhì)量,因為團隊不能再像以前一樣把問題留到后面,他們必須現(xiàn)在就解決。
消除沖突
當(dāng)引入持續(xù)交付的時候,我以上所說的沖突點就會頻繁出現(xiàn)。我希望當(dāng)這些問題出現(xiàn)的時候,了解沖突的根本原因,可以有助于更好地討論并解決它們。如果開發(fā)者一開始不愿意打破他們習(xí)慣的“正確”做事方式,或者認為持續(xù)交付所帶來的串行工作太復(fù)雜,或者很難理解這些實踐的目的和價值,那么我希望他們可以盡量開放地給自己一個機會去嘗試一下。一旦這些實踐方式根植于一個組織并且變得成熟,團隊成員們往往會覺得很難退回到以前的做事方式。
編者按:我重新定義了“傳統(tǒng)敏捷”中讓軟件可以發(fā)布的方式。這個定義不是適用于所有敏捷實踐,但是就我看到的,大部分主流概念都認為敏捷需要停下工作來將軟件變得可發(fā)布。
posted on 2012-07-20 10:04 順其自然EVO 閱讀(254) 評論(0) 編輯 收藏 所屬分類: 測試學(xué)習(xí)專欄