是不是寫(xiě)完代碼反症,工作就算完成了呢? 你或許會(huì)疑惑畔派,難道不是這樣嗎铅碍?那我再問(wèn)你,代碼是技術(shù)團(tuán)隊(duì)的交付物嗎线椰?
你是不是發(fā)現(xiàn)什么不對(duì)勁了胞谈。沒(méi)有人需要這堆文本,人們真正需要的是一個(gè)可運(yùn)行的軟件。寫(xiě)代碼是程序員的職責(zé)烦绳,但我們更有義務(wù)交付一個(gè)可運(yùn)行的軟件卿捎。
交付一個(gè)可運(yùn)行的軟件,通常不是靠程序員個(gè)體奮戰(zhàn)就能完成的径密,它是開(kāi)發(fā)團(tuán)隊(duì)協(xié)作的結(jié)果午阵。我們大多數(shù)人都工作在一個(gè)團(tuán)隊(duì)中,那我們寫(xiě)的代碼是不是能夠自然而然地就和其他人的代碼配合到一起呢享扔?顯然沒(méi)那么簡(jiǎn)單底桂。
如果想將每個(gè)程序員編寫(xiě)的代碼很好地組合在一起,我們就必須做一件事:集成惧眠。
但是集成這件事情籽懦,該誰(shuí)做,該怎么做呢锉试?我不知道你有沒(méi)有思考過(guò)這個(gè)問(wèn)題猫十。在開(kāi)始這個(gè)話(huà)題之前,我先給你講個(gè)故事呆盖。
集成之“災(zāi)”
之前做的一個(gè)項(xiàng)目, 部門(mén)有很多個(gè)小組拖云,正在共同研發(fā)一個(gè)項(xiàng)目。他們工作流程是应又,先開(kāi)發(fā)一個(gè)月宙项,等到開(kāi)發(fā)階段告一段落,大項(xiàng)經(jīng)理再把各個(gè)小組最精銳成員調(diào)到一起開(kāi)始集成株扛。對(duì)他們來(lái)說(shuō)尤筐,集成是一件大事,難度很大洞就,所以要聚集精英來(lái)做。
這個(gè)項(xiàng)目是用 C 語(yǔ)言編寫(xiě)的旬蟋,所以油昂,集成的第1步就是編譯鏈接。大家把各個(gè)小組寫(xiě)好的程序模塊編譯到一起倾贰,哪個(gè)模塊有問(wèn)題冕碟,哪個(gè)小組的精英就出面解決它。
如果第一天匆浙,所有模塊能夠編譯鏈接到一起安寺,大家就要謝天謝地了。之后才進(jìn)入到一個(gè)正式“聯(lián)調(diào)”的過(guò)程首尼。
“聯(lián)調(diào)”的目標(biāo)挑庶,是把一個(gè)最基本的流程跑通言秸,這樣,集成才算完成。而對(duì)他們這個(gè)項(xiàng)目來(lái)說(shuō),“聯(lián)調(diào)”階段更像是場(chǎng)“災(zāi)難”磁奖。
為什么?你想想俱恶,一個(gè)大部門(mén)有若干個(gè)團(tuán)隊(duì),每個(gè)團(tuán)隊(duì)都在為同一個(gè)項(xiàng)上進(jìn)行代碼開(kāi)發(fā)范舀,周期為一個(gè)月合是。這一個(gè)月期間,所有團(tuán)隊(duì)的程序模塊匯總在一起锭环,體量會(huì)非常龐大聪全。那么這些內(nèi)容中,出現(xiàn)錯(cuò)誤需要改動(dòng)的可能性也就非常大辅辩,需要改動(dòng)的量也就非常大难礼。因此他們集成“聯(lián)調(diào)”所需要的時(shí)間也會(huì)非常大。
即便他們調(diào)動(dòng)各組精英玫锋,完成一次項(xiàng)目集成的時(shí)間至少也需要2~3天蛾茉,改動(dòng)量稍大,可能就要一周了撩鹿。雖然我不知道你所處公司的現(xiàn)狀是什么樣的谦炬,但大概率地說(shuō),你在職業(yè)生涯中节沦,會(huì)遇到過(guò)類(lèi)似的場(chǎng)景键思。那怎么去解決這個(gè)問(wèn)題呢?
邁向持續(xù)集成
聰明的你作為旁觀者一定會(huì)想甫贯,在這個(gè)故事中吼鳞,為什么他們要在開(kāi)發(fā)一個(gè)月后才做集成呢?為什么不能在開(kāi)發(fā)一周后叫搁,甚至是更短的時(shí)間內(nèi)就集成一次赔桌?
這是一個(gè)行業(yè)中常見(jiàn)的痛點(diǎn),所以常熙,就會(huì)有人不斷地嘗試改進(jìn)纬乍,最先取得的突破是“每日構(gòu)建”碱茁。
1996年裸卫,Steve McConnel出版了一本著作《Rapid Development》,國(guó)內(nèi)譯作《快速軟件開(kāi)發(fā)》纽竣。在這本書(shū)中墓贿,作者首次提出了解決集成問(wèn)題的優(yōu)秀實(shí)踐:Daily Build茧泪,每日構(gòu)建。通過(guò)這個(gè)名字聋袋,我們便不難看出它的集成策略队伟,即每天集成1次。
這在當(dāng)時(shí)的人看來(lái)幽勒,已經(jīng)是“驚為天人”了嗜侮。就像上面提到的例子一樣,當(dāng)時(shí)的人普遍存在一種錯(cuò)誤認(rèn)知:集成不是一件容易的事啥容,需要精英參與锈颗,需要很長(zhǎng)時(shí)間,如果每天都進(jìn)行集成咪惠,這是想都不敢想的事情击吱。
實(shí)際上,每日構(gòu)建背后的邏輯很簡(jiǎn)單:既然一段時(shí)間累積下來(lái)的改動(dòng)量太過(guò)巨大遥昧,那一天的時(shí)間覆醇,累積的改動(dòng)量就小多了,集成的難度也會(huì)隨之降低炭臭。
你會(huì)看到永脓,對(duì)比最后做集成和每日構(gòu)建,這兩種不同的做法都是在處理改動(dòng)量和集成時(shí)間的關(guān)系鞋仍。只不過(guò)憨奸,一個(gè)是朝著“長(zhǎng)”的方向在努力,一個(gè)則瞄準(zhǔn)“短”的方向凿试。最后的事實(shí)證明排宰,“長(zhǎng)”的成了惡性循環(huán),“短”的成了最佳實(shí)踐那婉。
既然板甘,我們認(rèn)同了只要增加集成的頻率,就可以保證在每次集成時(shí)有較少的改動(dòng)量详炬,從而降低集成難度盐类。
那問(wèn)題來(lái)了?究竟要在開(kāi)發(fā)后多久才進(jìn)行一次集成呢呛谜?是半天在跳、兩個(gè)小時(shí)、還是一個(gè)小時(shí)呢隐岛?倘若這個(gè)想法推演到極致猫妙,是否就變成了只要有代碼提交,就去做集成聚凹?
沒(méi)錯(cuò)割坠,正是基于這樣的想法齐帚,有人嘗試著讓開(kāi)發(fā)和集成同時(shí)進(jìn)行,誕生了一個(gè)關(guān)于集成的全新實(shí)踐:持續(xù)集成彼哼。
持續(xù)集成一個(gè)關(guān)鍵的思維破局是对妄,將原來(lái)分成兩個(gè)階段的開(kāi)發(fā)與集成合二為一了,也就是一邊開(kāi)發(fā)一邊集成敢朱。
持續(xù)集成這個(gè)想法固然好剪菱,但是不是需要有專(zhuān)門(mén)負(fù)責(zé)盯著大家的工作,只要有人提交了代碼拴签,這個(gè)負(fù)責(zé)人就要去集成呢琅豆?顯然,這在真實(shí)工作中是行不通的篓吁。
既然是程序員的想法茫因,程序員解決問(wèn)題的方案自然就是自動(dòng)化這個(gè)過(guò)程。于是杖剪,有人編寫(xiě)了一個(gè)腳本冻押,定期去源碼服務(wù)器上拉代碼,出現(xiàn)程序更新時(shí)盛嘿,就自動(dòng)完成構(gòu)建洛巢。
后來(lái),人們發(fā)現(xiàn)這段腳本與任何具體項(xiàng)目都是無(wú)關(guān)的次兆。于是稿茉,把它進(jìn)一步整理并發(fā)布出來(lái),逐步迭代發(fā)展成為今天廣為人知的持續(xù)集成服務(wù)器芥炭。
在2000年時(shí)漓库,“軟件行業(yè)最會(huì)總結(jié)的人” Martin Fowler 發(fā)布了一篇重量級(jí)文章“Continuous Integration”。
之后一年园蝠,由 Martin Fowler 所在的 ThoughtWorks 公司發(fā)布了市面上第1款持續(xù)集成服務(wù)器 CruiseControl渺蒿。CruiseControl可謂是持續(xù)集成服務(wù)器的鼻祖,后來(lái)市面上的服務(wù)器基本都是在它的基礎(chǔ)上改良而來(lái)的彪薛。
Martin Fowler 的重磅文章和首款持續(xù)集成服務(wù)器的問(wèn)世茂装,讓軟件行業(yè)對(duì)持續(xù)集成進(jìn)行了更為深入的探討,人們對(duì)于持續(xù)集成的認(rèn)知程度一路走高善延,持續(xù)集成服務(wù)器成為了開(kāi)發(fā)團(tuán)隊(duì)在集成階段最得心應(yīng)手的工具少态。圍繞著持續(xù)集成的一系列行為準(zhǔn)則逐漸成型。
以至于發(fā)展到2006年易遣,Martin Fowler 不得不重寫(xiě)了“Continuous Integration”這篇文章彼妻。之后人們更是以持續(xù)集成為基礎(chǔ),進(jìn) 一步拓展出持續(xù)交付的概念训挡。
人類(lèi)對(duì)工具是有偏愛(ài)的澳骤,持續(xù)集成服務(wù)器的發(fā)布,將持續(xù)集成從一項(xiàng)大眾實(shí)踐逐步發(fā)展成為今天行行業(yè)的“事實(shí)”標(biāo)準(zhǔn)澜薄。
“地面上”的持續(xù)集成
然而为肮,即便持續(xù)集成已經(jīng)發(fā)展多年,入今整個(gè)行業(yè)在對(duì)它的應(yīng)用上肤京,卻并未達(dá)到同步的狀態(tài)颊艳。有趣的是,有一部分公司雖然還 無(wú)法實(shí)現(xiàn)持續(xù)集成忘分,但是因?yàn)槌掷m(xù)集成服務(wù)器的出現(xiàn)棋枕,反而可以做到每日構(gòu)建。
這不難理解妒峦,每日構(gòu)建的概念雖然早早就提出來(lái)了重斑,但在那個(gè)時(shí)期,行業(yè)里真正踐行每日構(gòu)建的公司并不多肯骇,其根本原因就在于窥浪,每日構(gòu)建最初都是一些指導(dǎo)原則,缺乏具體的支持笛丙。而每日構(gòu)建和持續(xù)集成最根本的區(qū)別在于構(gòu)建時(shí)機(jī)漾脂,而這只是持續(xù)集成服務(wù)器的一個(gè)配置選項(xiàng)而已。
當(dāng)然胚鸯,行業(yè)內(nèi)有一部分公司已經(jīng)可以將持續(xù)集成運(yùn)用的得心應(yīng)收骨稿,而也有相當(dāng)大的一部分人還在為集成而痛苦不堪,比如我前面舉得例子
雖然我們?cè)谕粋€(gè)時(shí)代寫(xiě)代碼做開(kāi)發(fā)姜钳,但在技術(shù)實(shí)踐層面坦冠,不同的團(tuán)隊(duì)卻仿佛生活在不同的年代。這也是我們要學(xué)習(xí)的原因哥桥。 也許蓝牲,目前國(guó)內(nèi)對(duì)于持續(xù)集成的實(shí)踐水平還處于較為原始的狀態(tài),這是個(gè)壞消息泰讽。但好消息是例衍,我們可以通過(guò)更多的學(xué)習(xí),對(duì)集成有足夠的了解已卸,從而一步到位地進(jìn)入到最先進(jìn)的狀態(tài)中佛玄。
無(wú)需停留在以精英為核心的集成時(shí)代,也可以完全不理會(huì)每日構(gòu)建累澡,我希望你擁有這個(gè)時(shí)代的集成觀梦抢,直接開(kāi)始持續(xù)集成。
如果有了持續(xù)集成的集成觀愧哟,我們?cè)撛趺纯创_(kāi)發(fā)這件事呢奥吩?開(kāi)發(fā)和集成就不再是兩個(gè)獨(dú)立的過(guò)程哼蛆,而是合二為一成為一體。
基于這樣的理解霞赫,我們就不能再說(shuō)代碼寫(xiě)完了腮介,就差集成了,因?yàn)檫@不叫開(kāi)發(fā)的完成端衰。一個(gè)好的做法是盡早把代碼和已有代碼集成到一起叠洗,而不應(yīng)該等著所有代碼都開(kāi)發(fā)完了,再去做提交旅东。