一区二区久久-一区二区三区www-一区二区三区久久-一区二区三区久久精品-麻豆国产一区二区在线观看-麻豆国产视频

重溫大師經典:Martin Fowler 的持續集成

  英文原文:Continuous Integration

  (作者:Martin Fowler,譯者:滕云)

  原文發布時間:2006年5月1日   翻譯時間:2012年2月25日

  持續集成是一種軟件開發實踐,在實踐中項目成員頻繁地進行集成,通常每個成員每天都會做集成工作,如此,每天整個項目將會有多次集成。每次集成后都會通過自動化構建(包括測試)來盡快發現其中的錯誤。許多團隊都發現這種方法大大地減少了集成問題并且能夠快速地開發出高內聚性的軟件。本文簡要地總結了持續集成技術及其現狀。

  我還清楚地記得我剛加入一個大型軟件項目時的情形,那時我正在英國一個電子公司做暑期實習。我的經理(屬于QA部門)領我參觀了一個巨大并很壓抑的倉庫,里面堆滿了大塊頭的主機。經理告訴我這個項目已經開發了有些年頭,現在正在做集成,并且已經集成了好幾個月了。經理還告訴我說,沒有人真正知道完成集成工作需要多少時間。由此我學到了軟件項目的一個通病:軟件集成是一個漫長并且無法預測的過程。

  然而,軟件集成不必像這樣的。在ThoughtWorks的大多數項目還有世界上許多其它組織的軟件項目中,軟件集成并不是什么難事。每個開發人員離共享的工程狀態只有咫尺之遙,并且可以在幾分鐘之內將自己的代碼集成進去。任何集成錯誤都能被快速地發現并得到快速的修正。

  這種鮮明的對比并不是源自于后者有多么昂貴或復雜的工具,而關鍵在于每人都頻繁集成這種簡單實踐,通常是每天向一個被管控的代碼庫集成。

  當我向人們闡述這種實踐時,通常得到兩種反應:“(在我們這里)行不通”和“無關緊要”。當人們嘗試了這種實踐之后,他們發現其實做起來比說起來簡單,而且這樣的實踐對于開發“至關重要”。因此有了第三種反應:“是的,我們就是這么做的,不然該怎么活啊?”

  “持續集成”源自于極限編程(XP),并且是XP最初的12種實踐之一。當我以咨詢師的角色加入ThoughtWorks時,我鼓勵我的團隊使用這種技術。Matthew Foemmel將我的建議變成了實實在在的行動,由此軟件集成從少有發生并且復雜的狀態變成了一樁易事。Matthew和我將我們的經驗寫在了本文的第一版中,而本文也是我的個人網站上最受歡迎的文章之一。

  雖然持續集成并不需要使用特別的工具來部署,但是我們發現擁有一臺持續集成服務器將大有益處,其中最著名的有開源的CruiseControl,該軟件最初由ThoughtWorks的幾個員工開發,現在由一個很大的社區維護著。后來幾款其它的持續集成服務器也相繼出現了,有開源的,也有商業化的,包括ThoughtWorks Studios的Cruise。

  在開發中使用持續集成

  對于我來說,解釋持續集成及其工作原理最簡單的方法便是以一個小的軟件功能的開發為例來進行演示。假設我們需要向軟件添加一點功能,至于是什么樣的功能并不重要,我們假定它很小并且可以在幾個小時內完成。

  首先我們需要在本地機器上保留一份當前已經處于集成狀態的代碼的拷貝。我通過代碼管理系統在代碼庫的主線(mainline)上拉下(check out)一份工作代碼拷貝。

  上一段文字主要針對使用代碼控制系統的人,對于不使用代碼控制系統的人來說便是胡言亂語了。因此,我將向后者解釋一下。代碼控制系統用于將項目所有的代碼保存在一個代碼庫(repository)中,項目當前的狀態通常被稱為主線。任何時候開發人員都可以從主線上獲得一份拷貝到本地機器,這被稱為“checking out”。本地機器上的代碼拷貝稱為“working copy”。(多數時候,實際上你是在更新(update)本地代碼到主線狀態,實踐中它們是一樣的效果。)

  現在,為了完成軟件的功能添加,我對本地代碼進行修改,其中既包括修改產品代碼,也包括添加自動化測試。持續集成非常看重測試,并且在軟件代碼本身中達到了測試自動化——我將其稱為自測試代碼,通常使用流行的XUnit測試框架的一個版本。

  當我完成了功能開發(或者在我開發過程的不同階段),我將在本地開發機上完成自動化構建。構建過程將編譯并鏈接本地代碼,然后跑自動化測試。只有當構建和測試都沒有錯誤時,該次構建才能算是好的構建。

  有了本地的成功構建,我便可以考慮將我修改的代碼提交到代碼庫了。但是,在我提交之前,其他開發人員可能已經向主線提交了他們的修改,所以首先我需要將他們的修改更新到我本地并且重新構建。如果他人的修改與我的修改有沖突,那么在本地編譯或者測試階段將會發生錯誤,這種情況下,我需要負責修改本地代碼直到與主線代碼保持適當同步為止。

  當本地代碼與主線代碼同步之后,我便可以向主線提交自己的修改了,代碼庫也得以更新。

  然而,單是提交了修改并不表示我的工作就完成了。我需要再次構建,但這次是在一臺擁有主線代碼的集成機器上進行。只有這次構建成功了才表示我的任務完成。通常會出現這樣的情況:我忘了提交本地機器上的一些東西,因此代碼庫并沒有得到適當的更新。只有我提交的修改在集成機器上成功構建之后,我的工作才算完成。這樣的集成構建可以由我手動完成,也可以由Cruise自動完成。

  當兩個開發者的代碼有沖突時,通常會在第二個開發者更新本地代碼時捕獲到,否則,集成構建應該會失敗。在這兩種途徑中,錯誤都可以被快速地發現。在持續集成環境中,你決不應該使失敗的集成構建保留太長時間。一個好的團隊每天都應該有許多成功的構建。當然,失敗的構建也會時常發生,但需要盡快的修復。

  這樣做的結果是,我們總會得到一個穩定并且工作正常的軟件。每個人都圍繞著一個共享并穩定的基礎代碼庫工作,絕不離基礎代碼庫太遠以至于需要很長的時間將自己的修改集成到基礎代碼庫中。如此這般,我們花在找bug上的時間減少了,因為bug在頻繁的集成中經常出現。

  持續集成實踐

  上文只是關于持續集成的一個概要和它在日常開發中的工作原理。讓所有這些都能很好的運作顯然不止于此。現在,就讓我們來看看有效持續集成所需的關鍵實踐。 

  維護一個單一的代碼庫

  軟件項目需要大量的文件協同工作來構建出最終的產品。跟蹤所有的文件需要大量的工作,尤其是在多個開發者參與的項目中。因此,我們可以并不驚奇的看到,不同的軟件開發團隊都在開發用于管理這些文件的工具——源代碼管理工具,也叫配置管理,版本控制系統,代碼庫等。這些工具是多數軟件項目不可分的組成部分。然而,令人傷心并吃驚的是,并不是所有的項目都使用了這樣的工具。我的確見到(雖然很少)不使用這些工具的項目,它們使用本地和共享磁盤這種混亂的結合來共同工作。

  因此,做為最基本的持續集成實踐,請保證你使用一款體面的代碼管理系統。成本不是問題,有許多高質量的開源代碼管理工具存在。當前的選擇為Subversion(譯者注:現在有了更新的hg和git)。(更老的開源工具CVS如今仍然被大量使用,雖然比沒有強,但是Subversion是更現代的選擇。)有趣的是,當我和一些開發者聊天時,我發現相比起多數商業化的代碼管理系統,他們更喜歡Subversion。據我所知,唯一值得花錢買的只有Perforce

  當你有了代碼管理系統之后,確保每個開發者都能方便的獲得到源代碼。不應該有人還在問:“foo-whiffle 文件在哪兒?”所有東西都必須在代碼庫里。

  雖然許多團隊都在使用代碼庫,但是我經常發現,他們并不把所有東西都放在里面。如果大家需要使用一個文件,他們知道該文件放到代碼庫中,但是,構建所需的所有都應該包含在代碼庫里,包括測試腳本,屬性文件,數據庫模式文件,安裝腳本和第三方庫等。我所知道的有項目將編譯器加到代碼庫中的(對于早期脆弱的C++編譯器來說非常重要)。基本原則是:在一臺新機器上check out代碼后構建也能構建成功。新機器上的東西應該盡量的少,通常包括很大的,難于安裝的,并且穩定的軟件,比如操作系統,Java開發環境或者數據庫管理系統等。

  你需要將構建所需的所有東西都加到代碼管理系統中,同時也需要將大家經常操作的東西方進去,IDE配置便是一個很好的例子,這樣便于大家共享IDE配置。

  版本控制系統的一大功能是它允許你創建多個分支,以此來處理不同的“開發流”。這種功能很有用,但卻經常被過度使用以至給開發者帶來了不少麻煩。所以,你需要將分支的使用最小化,特別建議使用主線,即項目中只有單一的開發分支,并且每人在多數時間里都在“離線”工作。

  總之,你應該將構建所需的所有東西都放在代碼管理系統中,而不應該將構建的輸出放進去。有些朋友確實將構建輸出放在代碼管理系統中,但我認為這是一個壞味道,可能導致更深的問題——通常是你無法完成重新構建。

  使構建自動化

  將源代碼變成一個能運行的軟件系統通常是一個復雜的過程,包括編譯,文件搬移,加載數據庫模式等等。但其中大多數任務都是可以自動化的,并且也應該被自動化。讓人去輸入奇怪的命令或點擊對話框是非常耗時的,而且從根本上來說也是個錯誤的做法。

  構建所需的自動化環境對于軟件系統來說是一個通用功能。Unix的Make已經誕生好多年了,Java社區有Ant, .NET社區有Nant,現在又有了MSBuild。當你用這些工具構建和啟動系統時,請確保只使用一個命令完成任務。

  一個常見的錯誤是在自動化構建里并沒有完全包括構建所需的東西。構建過程中應該從代碼庫里取得數據庫模式文件并自動執行之。結合我上文所講的原則來看,任何人都應該能夠在一臺新機器上拉下代碼庫中的代碼,并只用一個命令將系統運行起來。

  構建腳本是多種多樣的,通常特定于某個平臺或社區,但情況并不必須如此。我們的多數Java項目都使用Ant,而另外有些用Ruby(Ruby世界的Rake是一個非常不錯的構建工具)。我們用Ant完成了早期的一個微軟COM工程的構建自動化,并從中大獲裨益。

  大型的構建通常需要很長的時間,而在你只做了很小的修改的情況下,你是不想運行所有的構建步驟的。因此,優秀的構建工具能夠分析出哪些地方需要做相應的修改,并將這個分析過程本身做為整個構建過程的一部分。通常的做法是檢查源代碼和目標文件的修改日期,只有當源代碼的修改日期晚于其對應的目標文件時才執行編譯。依賴關系因此變得微妙起來了:如果一個目標文件發生了修改,那些依賴于它的文件也需要重新構建。有些編譯器能夠處理這種依賴關系,而有些就不見得。

  根據自己的需要,你可以選擇不同的東西進行構建。構建中既可以包括測試,也可以不包括,甚至可以包括不同的測試板塊。有些組件可以進行單獨構建。構建腳本應該能夠允許你針對不同的情形進行不同的構建目標。

  我們大多數都使用IDE,而多數IDE都或多或少地集成了構建管理功能。但是這樣構建文件通常是特定于IDE的,而且非常脆弱。此外,它們需要依賴于IDE才能工作。雖然對于開發者個人來說,在IDE中做這樣的構建配置并無不妥,但對于持續集成服務器來說,一份能夠被其它腳本調用的主構建腳本卻是至關重要的。比如一個Java項目,各個開發者可以在自己的IDE中進行構建,但應該還有一個Ant主構建腳本來保證構建能在集成服務器上順利完成。

  使構建自測試

  傳統意義上的構建包括只編譯,鏈接等過程。此時程序也許能運行起來,但這并不意味著系統就能正確地運行。雖然現在的靜態語言已經能夠捕捉到許多bug,但是漏網之魚卻更多。

  一種快速并高效發現bug的方法是將自動化測試包含到構建過程中。當然,測試也不見得完美,但的確能發現很多bug——足夠多了。特別是隨著極限編程(XP)的升溫,測試驅動開發(TDD)也使自測試代碼流行起來,越來越多的人開始注意到這種技術的價值所在。

  經常讀我著作的讀者可能知道我是一個TDD和XP的大粉絲,然而我想強調的是這兩種方法和自測試并沒有必然聯系。TDD和XP都要求先寫測試代碼,再寫功能代碼使測試通過。在這種模式下,測試既用于發現bug,又用于完成系統設計。這是非常好的,但對于持續集成來說不必如此,因為此時我們自測試代碼的要求并不那么高。(然而TDD是我寫自測試代碼的首選。)

  對于自測試代碼而言,你需要一組自動化測試來檢測一大部分代碼庫中的bug。測試能通過一個簡單的命令來運行并且具備自檢功能。測試的結果應該能指出哪些測試是失敗的。對于自測試的構建來說,測試失敗應導致構建失敗。

  過去這些年里,TDD使開源XUnit家族流行起來,成為了理想的測試工具。在ThoughtWorks,XUnit已經是非常有用的測試工具,我也經常建議人們使用。這組工具起初由Kent Beck開發,它們使自測試環境的搭建變得非常簡單。

  XUnit當之無愧地是你進行代碼自測試的起點。當然,你也應當多看看那些更側向于端到端測試的工具,包括FITSeleniumSahiWatirFITnesse等等,我就不逐一列舉了。

  當然,別指望測試就是萬能的。常言道,測試并不代表就沒有bug。

  每人每天都向主線提交代碼

  集成首先在于交流,它使其他成員能夠看到你所做的修改。在這種頻繁的交流下,大家都能很快地知道開發過程中所做的修改。

  在向主線提交代碼之前,開發人員必須保證本地構建成功。這當然也包括使測試全部通過。另外,在提交之前需要更新本地代碼以匹配主線代碼,然后在本地解決主線代碼與本地代碼之間的沖突,再在本地進行構建。如果構建成功,便可以向主線提交代碼了。

  在這種頻繁提交下,開發者可以快速地發現自己代碼與他人代碼之間的沖突。快速解決問題的關鍵在于快速地發現問題。幾個小時的提交間隔使得代碼沖突也可以在幾個小時內發現,此時大家的修改都不多,沖突也不大,因此解決沖突也很簡單。對于好幾周都發現不了的沖突,通常是很難解決的。

  在更新本地代碼庫時就進行構建,這意味著我們既可以發現文本上的沖突,又可以發現編譯沖突。既然構建是自測試的,那么運行時的沖突也可以被檢測出來,而這樣的沖突往往是一些特別煩人的bug。由于提交間隔只有短短的幾個小時,bug便沒多少藏身之處了。再者,因為每次提交的修改都不多,你可以使用diff-debugging來幫你找出這些bug。

  我的基本原則是:每個開發者每天都應當向代碼庫進行提交。在實踐中,越是頻繁提交,可能導致沖突的地方就越少,因而也越容易發現。

  頻繁提交鼓勵開發人員以幾個小時為單位來分割他們的代碼,這樣便于跟蹤進度。通常,人們一開始認為在短短的幾個小時內做不了什么事情,但我們發現找個導師和多實踐可以幫助他們學習。

  每次提交都應在集成機上進行構建

  有了每日提交,也就又了每日測試,這應該表明主線處于健康狀態。但是在實踐中,的確有出錯的時候,原因之一在于紀律——有人并沒有在提交之前進行本地更新和構建。另外,不同開發機之間的環境不同也是一個原因。

  因此,你應該保證在集成機上進行構建,只有當集成機上構建成功后,才表明你的任務完成了。由于提交者需要對自己的提交負責,他就得盯著主線上的構建,如果失敗,馬上修改。如果下班之前你提交的修改失敗了,那么,對不起,請修改好了才回家。

  我見到過兩種方式來保證主線構建的成功:一是手動構建,二是使用持續集成服務器

  手動構建是最簡單的,基本上與開發者在本地做的構建差不多——先到集成機上拉下主線的最新代碼,然后運行構建命令,在構建過程中你得盯著構建過程,如果構建成功,表明你的任務完成。(另見Jim Shore的描述。)

  持續集成服務器則一直監視著代碼庫,一旦檢測到有提交,便自動拉下代碼到本機,然后開始構建,并將結果通知提交者。只有當提交者收到通知后——通常是以電子郵件的方式,才表明自己的任務完成。

  在ThoughtWorks,我們是持續集成服務器的忠實粉絲,我們領導了CruiseControlCruiseControl.NET的初期開發,此兩者均是廣為使用的CI服務器。從那時起,我們也開發了商業化的Cruise。在幾乎每個項目中,我們都使用了CI服務器,并且結果是令人愉悅的。

  不是所有人都傾向于使用CI服務器的,Jim Shore便給出了一個很好的論述,在此論述中,他解釋了為什么他更傾向于手動構建。我同意他的看法——CI不過是安裝一些軟件而已,所有的實踐都應當旨在有效地完成持續集成。但同樣,許多使用CI服務器的團隊的確發現CI服務器是很好的工具。

  有很多團隊定期的進行構建,比如每晚構建。這和持續構建并不是一回事,而且對于持續集成來說,也是不夠的。持續集成的關鍵在于盡快地發現問題。而每晚構建意味著整個白天都發現不了bug,如此,需要很長的時間發現并清楚這些bug。

  持續構建的重點在于,如果主線構建失敗,你應該馬上進行修改。在持續集成中,你一直是在一個穩定的代碼庫基礎上進行開發。主線構建失敗并不是一件壞事,但是,如果這樣的情況經常發生,那么就意味著開發人員對于本地更新并沒在意或者在提交之前并沒在本地構建。主線構建一旦失敗,必須馬上修正。為了避免主線構建失敗,也許你可以試試 pending head

  快速構建

  持續集成的關鍵在于快速反饋,需要長時間構建的CI是極其糟糕的。我的多數同事都認為一個小時的構建時間對于CI來說決無道理可言。我也記得曾經有團隊夢想著他們的構建能有多么多么的快,但有時我們不得不面對很難快速構建的情況。

  對于多數項目來說,將構建時間維持在10鐘之內是合理的,這也是XP的方針之一,我們多數項目也達到了這個目標。這種做法是值得的,因為這樣省下的時間是為開發者節約的。

  如果你的構建長到了一小時,那么想使其加速便不是那么容易了。對于企業級應用來說,我們發現構建時間的瓶頸通常發生在測試上,特別是那些需要于外部交互的測試——比如數據庫。

  可能最好的解決辦法是引入階段性構建(也叫構建管道或者部署管道),因為構建事實上是分階段性的。代碼提交后首先觸發的是構建稱為提交構建,提交構建應該快速完成,而棘手的是怎么保持速度與查找bug之間的平衡。

  提交構建成功后,其他人便可自信的工作了。但是,你可能還有其它跑得比較慢的測試需要寫,這時可以用額外的機器來專門跑這些耗時的測試。

  一個簡單的例子是將構建分為兩個階段,第一個階段完成編譯,并且跑那些不需要外部交互的單元測試,數據庫交互也通過stub的方式完全消除掉。這些測試可以很快跑完,原則是將其保持在10分鐘之內。但是,對于那些需要大量外部交互——特別是涉及到真實數據庫交互時才能發現的bug,這個階段便無能為力了。第二個階段跑的測試則需要操作真實的數據庫了,同時還應包括端到端測試。這個階段可能需要幾個小時。

  在這種情況下,通常將第一階段視為提交構建,并將此做為主要的CI周期。第二階段則可在有必要時才進行,如果這個階段構建失敗,它也不需要像第一階段那樣“停下全部手頭的工作”,但也應該得到盡快的修改。第二階段的構建不見得需要保持一直通過,對于已經發現的bug來說,可以在之后幾天修改。對于這個案例來說,第二階段全是測試,因為通常情況下最慢的即是測試。

  如果第二階段構建發現了bug,通常意味著應該在第一階段中引入新的測試來予以保證。

  當然,以上的兩階段構建只是一個例子,你完全可以加入多個構建階段。提交構建之后的其它構建是可以并行完成的,如果這些階段的構建需要好幾個小時,那么可以用幾臺機器來并行完成。通過這種并行化,你可以將提交構建之外的所有測試都引入到構建過程中來,比如性能測試。

  在與生產環境的拷貝環境中運行測試

  測試旨在發現可能在生產環境中出現的問題,因此如果你的測試環境與生產環境不同,那么測試很有可能發現不了生產環境中的bug。

  因此,你的測試環境應該盡量與生成環境相同。使用相同的數據庫,相同的操作系統,并且版本都應該一樣。另外,將生產環境中的庫文件也放到測試環境中,即使構建時用不到這些庫。IP地址和端口號也應當相同,當然還包括硬件。

  但事實上這是有限制的。如果你開發的是桌面軟件,很難預測你的客戶在使用哪些第三方庫。再者,生產環境可能非常昂貴。即便存在這么多限制,你依然應當盡量去復制生產環境,并熟知因測試環境和生產環境的不同而可能導致的風險。

  如果你搭建的環境足夠簡單并沒有多少煩人的外部交互,那么你的提交構建便可在仿真環境中進行。但是,由于系統反應慢等原因,你可能需要test doubles。因此,通常情況是在人工環境下跑提交構建以獲取速度,而用一個生產環境的拷貝環境來跑其它測試。

  我注意到,虛擬化技術越來越引起人們的興趣。由于虛擬機可以保存構建所需的所有東西,故在虛擬機中運行構建和測試相對比較容易。另外,虛擬機技術也允許你在一臺機器上運行多個測試,或者可以模擬多臺機器同時訪問網絡的情況。隨著虛擬機性能逐漸提升,它將引起更多的注意。

  使任何人都能輕易獲得可執行文件

  軟件開發最困能的事情之一便是你不能保證所開發的是正確的軟件。我們發現人們往往很難預知自己究竟想要什么,而相反,對已有的東西進行評判和修改卻容易的多。敏捷開發過程則恰恰是符合人類這種行為習慣的。

  為此,項目中的所有成員都應能夠獲得最新的可執行文件并能成功的運行,目的可以包括做演示,瀏覽測試或者僅僅看看項目本周有何修改。

  這是很容易達到的:確保一個通用的地方來存放最新可執行文件。在同一個地方存放多個可執行文件也是很有用的。對于最新的可執行文件,應當保證能夠通過提交測試。

  如果你的開發過程有一個很好的迭代計劃,將每次迭代最后一次構建生成的可執行文件存放起來也是明智的做法。

  人人都能看到正在發生什么

  持續集成主要在于交流,因此應當保證每人都能輕易看到當前系統的狀態和已做的修改。

  主線的構建狀態是非常重要的,Cruise服務器包含一個網站,你可以在該網站上看到當前的構建狀態和最后一次主線構建的結果,許多團隊喜歡用比較顯眼的標識來反應構建狀態,比如在屏幕上放一盞燈,燈綠表示構建成功,燈紅表示失敗。尤其常見的是lava lamps——不僅表明構建狀態,還可顯示構建時間。如果紅燈中有了氣泡,則表明構建已經失敗了很長一段時間了。每個團隊都有自己的選擇,當然,適合自己的才是最好的。

  對于手工完成的持續集成過程,這種可見性也是很重要的,構建機器的顯示器應該能顯示主線構建的狀態。通常,正在做集成的人會放一個token在桌上來表明他正在做集成。人們喜歡在構建成功后播放一些簡單的聲音,比如鬧鈴之類的。

  當然,CI服務器的網站可以展示更多的信息。Cruise不但能可以顯示是誰在構建,并且能顯示最新提交的修改。另外,Cruise還可以查看提交歷史,這樣,團隊成員便可以很清楚項目的進展情況。據我所知,有些團隊的頭便是通過這種方式來了解項目成員的工作情況和整個系統的修改情況。

  使用CI網站的另一個好處是,哪怕不在一起工作的人都可以看到當前項目的狀態。再者,你也可以將不同項目的構建信息放到一起。

  并不是只有CI網站才能展示顯示構建信息。由于構建的不穩定性是一直存在的,這時我們可以將全年的日歷畫在一張墻上,每天對應一個方塊,如果構建成功,QA則在該天的方塊貼上綠色標簽,否則貼上紅色標簽。時間一久,這份日歷便可顯示出項目的穩定性進展情況。

  自動化部署

  做持續集成需要多種環境,不同的構建階段需要不同的環境。每天,項目的可執行文件都會在這些環境之間搬來移去,于是你希望將這些過程自動化。因此,自動化部署腳本便很重要了,不僅包括測試環境的腳本,也包括針對生產環境的部署腳本。雖然我們不是每天都向生產環境部署,但自動化部署不僅可以加速部署過程,并且能夠減少部署錯誤。

  如果你已經有了生產環境的自動化部署,那么也應該考慮一下相應的自動化回滾。由于失敗是時而會發生的事情,在這種情況下,我們希望能快速回滾到失敗之前的狀態。這樣一來,我們在部署是也不用那么畏首畏尾了,于是我們可以頻繁的發布軟件,用戶亦能盡快的享受到新的功能。(Ruby on Rails社區有一款名為Capistrano的工具即是一個典型的例子。)

  在集群環境中,我看到有每次只向一個節點部署的情況,由此在幾個小時之內逐漸完成所有節點的部署。

  對于一些面向大眾的web應用,我所了解的另外一種很有趣的部署方式是,先試驗性針對一部分用戶進行部署,再通過這些用戶的試用情況來決定是否向所有用戶部署。自動化部署,做為CI的一項原則,能夠很好的勝任這些工作。

  持續集成的好處

  總的來說,我認為持續集成的最大好處在于降低風險。我又想起了我在本文一開始提到的那個項目——已經處于項目的末期,但是仍然不知到何時才能結束。

  延期集成的缺點在于,很難預測集成到底要花多少時間,更糟的是,你很難了解集成的進展情況。

  持續集成正好解決了這些問題。每次集成的時間都不長,任何時候你都知道自己所處的情況,軟件的哪些地方在工作,哪些沒有。

  Bug——惡心的玩意兒,傷害我們的自信,攪亂我們的日程,還破壞我們的名聲。如果在生產環境中遇到了bug,那么用戶將會把氣往你身上撒。而在開發環境中,bug攔著你的路,迫使你無法完成余下的工作。

  持續集成并不能消除bug,卻能幫你快速的發現bug并予以清除。這種情況下,持續集成更像是自測試的代碼。當遇到bug時,由于你只做了很小的修改,這樣便大大縮小的bug的查找范圍。另外,由于是你剛寫的代碼,你還記得很清楚,因此也使查找bug更加容易。你還可以使用diff debugging,將當前的代碼版本和先前沒有bug的版本進行比較。

  Bug也存在積累性,bug越多,越難清除。部分原因在于bug之間存在牽連。另外也存在心理因素,bug一多,人便沒那么多精力去修了——這就是所謂的“Broken Windows 綜合征”。

  因此,對于采用持續集成的團隊,bug將大大減少,不管是在生產環境,還是在開發環境。但是,我想強調的是,你的獲益程度取決于測試的好壞程度。你或許已發現,寫出好多測試并不難。然而,要達到低bug率的程度依然是需要時間的,你還得不斷地引入并改進自己的測試。

  有了持續集成,頻繁部署也不是什么難事了。頻繁部署的價值在于,你的客戶可以快速的享用軟件的新功能,并能快速的提出反饋。這將有利于清除客戶和開發之間的障礙——我認為這是軟件開發最大的障礙。

  引入持續集成

  然后你開始試著玩持續集成了,但該從何入手呢?上文中我所羅列持續集成實踐可以給你帶來太多的好處,但是你并不必在一開始就完全采用這些實踐的。

  做持續集成沒有套路,主要取決于你團隊自身的情況,但是我們發現以下幾點對于持續集成來說是比較通用的。

  (1)第一步需要將構建自動化,并將你所需的所有東西都放在代碼管理系統中,以至于可以通過一個命令來構建整個系統。對很多項目來說,這并非易事。一開始,你可以按照需要進行構建,或者可以只做自動化的夜晚構建。雖然,這些做法都不能稱為持續集成,但夜晚構建確是一個好的起點。

  (2)在構建中引入一些自動化測試,試著確定出現問題的主要范圍,并用自動化測試去發現這些問題。對于已有的項目來說,很難建立起一組好的快速測試,這時你就得另尋它路了。

  (3)使提交構建快速完成。雖然好幾個小時的持續集成比沒有要好,但是如果你能將構建時間縮短到幾十分鐘,或者就短短的10分鐘,這就再好不過了。

  (4)對于新項目,從項目開始就采用持續集成。注意構建時間,如果構建時間違背了“10分鐘原則”,那么請盡快采取行動。

  (5)尋找幫助,找有經驗的人幫助你。和其它的新技術一樣,當不知到結果會是什么樣時,很難開頭。找一個導師可能要花錢,但是不找的話,你所付出的代價是時間的浪費和低下的生產力。(ThoughtWorks提供這樣的咨詢服務,畢竟你可能遇到的問題我們之前都遇到過。)  

  總結

  自Matt和我發布了本文的第一版之后,持續集成逐漸變成了軟件開發的主流技術,在ThoughtWorks,幾乎所有的項目都使用到持續集成,同時我們也看到世界上其他組織也在使用持續集成技術。相比起充滿爭議的極限編程來說,持續集成很少得到負面的評論。

  如果你還沒有采用持續集成,我強烈建議你試一試。如果你已經采用了持續集成,本文可能會幫助你進一步提高效率。這些年來,我們已經學到了許多關于持續集成的知識,我們也希望有更多可以學習和改進的地方。  

  延伸閱讀

  像本文這樣的文章通常只能涵蓋一些基本,但它卻是一種重要的話題,所以我在自己網站上放了一個guide page,那里你可以獲得更多的信息。

  如果想了解持續集成更多的細節,我建議Paul Duvall(Jolt獎得主)的Continuous Integration: Improving Software Quality and Reducing Risk。對于更寬泛的持續交付,可以看看Humble 和 Dave Farley的Continuous Delivery: Reliable Software Releases through Build, Test, and Deployment Automation

it知識庫重溫大師經典:Martin Fowler 的持續集成,轉載需保留來源!

鄭重聲明:本文版權歸原作者所有,轉載文章僅為傳播更多信息之目的,如作者信息標記有誤,請第一時間聯系我們修改或刪除,多謝。

主站蜘蛛池模板: 91网页| 美女黄视频在线 | 黄色美女网站免费 | 日韩 国产 欧美视频一区二区三区 | 99久久久久国产 | 欧美在线精品永久免费播放 | 久久se精品一区二区国产 | 38pao强力打造永久免费高清视频 | 在线激情网址 | 国产毛片在线看 | 亚洲国产图片 | 天天色天天干天天 | 91视频国产精品 | 激情五月婷婷开心 | 最新色视频 | 成人国产精品视频 | 国产精品欧美激情第一页 | 久久精品国产乱子伦多人 | 91不卡视频 | 国产精品福利资源在线 | 精品久久天干天天天按摩 | 亚洲欧美综合图片 | 国产成人+综合亚洲+天堂 | 好吊操视频在线 | 亚洲视频在线观看一区 | 91精品国产91热久久p | 欧美丝袜xxxxx在线播放 | 亚洲综合插插 | 国产在线干 | 精品成人 | 狠狠色狠狠色综合伊人 | 在线观看欧美视频 | 白嫩美女一级毛片免费看 | 亚洲一区二区观看 | 免费一区二区三区 | 国产亚洲欧美另类久久久 | 亚洲精品在线播放 | 日本加勒比在线视频 | 欧美午夜a级精美理论片 | 久久精品夜色国产 | 亚洲激情婷婷 |