特性分支是邪惡的?!

作者: jez  發布時間: 2012-08-31 15:32  閱讀: 3556 次  推薦: 0   原文鏈接   [收藏]  

  英文原文:On DVCS, continuous integration, and feature branches

  翻譯:喬梁

  為了吸引大家的注意力,我想說:“特性分支是邪惡的化身”。

  自2008年起,Mercurial (最近是Git)就成了我日常工作的工具,而且我喜歡使用分布式版本控制系統。正如《持續交付》一書中討論的那樣(英文版第393頁和394頁),有很多理由說明,與之前已存在的同類工具相比,DVCS代表了一種巨大的轉變。但正如所有強大的工具一樣,你會有很多種方法來使用它們,但并不是所有的方法都是好的。這里所有的討論不是想說DVCS不好:使用特性分支和使用DVCS完全是正交的。而且,我認為,DVCS的支持者用這種工具的功能分支來推銷DVCS,是對DVCS的一種傷害。

  首先看幾個定義。請注意,一些人以不同的方式使用這些術語,所以你需要暫時從你的大腦中把先把其它的定義擦去,否則我的討論就沒有什么意義了。

  持續集成是一種實踐,用于確保你的軟件一直是可以工作的,并且在幾分鐘內你就能夠得到關于 “你的修改是否破壞了系統”的反饋。

  特性分支是一種實踐, 使用它的人直到他所開發的特性“完成”后才合并回主干(這里的“完成“不是“done done”原則中的那個“完成”)。

  主干是指開發主線 —— 通常是指版本控制庫中的。你的某次構建就是從這個主干中的一個版本創建的,并會被放到你的部署流水線中。 注意,這些定義對DVCS和其它開源項目,甚至是GitHub,也完全適用。

  先讓我們解決一個象稻草人一樣的爭論。當使用版本控制工具時,你就使用一個分支來工作:即本地工作目錄。使用DVCS,只是多了一個層次而已,因為你的本地庫就是一個有效分支。我并不反對創建分支。我所不贊同的是:讓你最終要發布的代碼在分支上堆積起來

  下面是我所看到的狀況。當你將最終要發布的代碼大量地堆積在分支上,會有幾個糟糕的事情發生:

  • 這種狀態持續時間越長,就越難合并。因為隨著其他人向主干提交,主干的代碼與你的分支上的代碼之間的差異會越來越大。強大的合并工具的確會在一定程度上幫助你,但是任何一個做過很多開發工作的人都會有過這樣的經歷,即:代碼的確成功合并了,但是應用程序運行不起來。隨著需要合并的那些代碼數量的增加,以及初始分支與最終合并時間的增長,發生這種事情的可能性是遞增的,而且不僅僅是線性遞增。
  • 在分支上的工作越多,在合并到主干時越有可能破壞系統。每個人都有這樣的經歷:有個問題出現了,你似乎找到了一個非常聰明的解決方案。可是,幾個小時(或者幾天)后,你才發現需要廢棄所有的東西,或者(更常見地)那些引起未預期后果的代碼提交。
  • 當多個開發人員同時在這個代碼庫上工作,并使用特性分支開發時,使代碼重構變得很難。如果我重構并且提交到主干了,而其他人在其分支上已經修改了很多東西的話,當他們向主干合并時就更難了。這就會驅使我不做重構。而不充分的重構就等于劣質代碼。

  當大家頻繁將其代碼合并到主干時,就沒有這些問題了。如果不這么做的話,隨著團隊人數的增加,這些問題的痛苦會成指數級增加。而且,還有一個惡性循環: 這種痛苦的自然反應是:更少做合并。正如我喜歡說的,當某些事情令你很痛苦時,解決方案是更頻繁地做,并將痛苦提前。在這里,解決方案是每個人都更頻繁地合并到主干。

  然而,如果你正在做的一個功能中需要做很多工作,或者你對系統進行大面積修改時,這么做就比較困難了。下面是一些解決方案:

  1. 將Story分解成一些更小塊的工作(有時被叫做Task)。我還沒有遇到過一大塊工作無法分解成更小塊的工作 —— 通常少于1小時,并且肯定用不了一天時間 —— 這樣讓我既能達到目標,又能保證系統可工作且可發布。這需要細心的分析、討論、思考和嚴格的紀律。當我無法找到在增量開發方式下幾小時內可以完成的工作時,我就會先對某些想法做一些試驗(敏捷中叫做Spike)。至關重要的點在于:我能盡早地對我的方案進行快速驗證:是可以解決問題,還是會對系統造成不良后果,影響了其他人的工作,或者引出了回歸缺陷(這也是持續集成的動機所在)。
  2. 在實現Story時,最后再做面向用戶那部分接口。先從業務邏輯及以下部分下手。使用TDD完善你的代碼。頻繁提交,與主干合并。最后再完成界面部分。
  3. 使用抽象分支方法來對復雜或大范圍變更進行增量開發,同時保證系統一直處于可工作狀態

  你怎么知道什么時候沒有合并的東西太多了呢?想像一下,假如你是一個開源項目的維護者,有一個你不認識的剛剛提交了一個補丁。你會馬上合并它嗎?你能記住它與主干之間的所有diff嗎?你能保證在不需要問你的前提下,團隊其他人員能在一分鐘之內就能清楚地理解這些diff嗎?如果你對上述所有問題的回答不是“Yes”, 那么你就要停止工作,將其分成更小的工作單元。

  很明顯,只要 “特性”足夠小,我并不真正反對特性分支。然而,通常使用特性分支的人大多無法通過上一段中的問題測試。真正有經驗的開發人員能理解使用特性分支與為了高效使用它而建立的紀律之間的平衡,但仍舊有一定的危險 —— GitHub就被Forks搞得很亂,這些Forks很多是不可合并的,因為它們與主干的差異太大了。

  我更想強調的是下面這個觀點,即:讓“盡早地持續地交付有價值的軟件” 中最重要的實踐之一就是確保你的系統一直是可工作的。

  對于開發人員來說,達到這一目標最好的方法是:確保他們可以將“提交可能對系統造成破壞”的風險最小化。我們可以通過“保持小步提交、在主干持續集成,并且有全面的自動化測試套件來驗收本次修改的預期行為,且不會引發回歸缺陷”,從而達到這一目標。

0
0
 
 
 

文章列表

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()