團隊研發的本質

我們曾經接觸到一家企業,它一開始只有8個人,那個時候每個月都可以發一兩個版本出去,客戶都可以用到,因為他們是做醫院的資訊管理HIS系統,他們覺得做得還不錯,后來團隊發展比較快,規模到了80人左右,卻半年沒發一個版本,這導致實施團隊沒臉見客戶,因為客戶說半年前提的需求怎么還發不出來,
這個時候悖論就來了:我們以為團隊規模越大,研發效率就會越高,可以做越多的東西,但是我們發現團隊規模大到一定程度,整個研發效率是會下降的,甚至降得非常快,

站在團隊的角度來說,因為人多,協作越來越慢,協作的成本也越來越高,我們發現團隊的研發模式,人越多越會有問題,因為沖突更多,等待更多,這里沖突是指代碼集成發布程序中的沖突,而等待也是集成和開發程序中代碼彼此的等待,
以下是兩個具體的場景:

假設有兩個程式員A和B一起作業,A一開始每次提交都把作業逐漸成功提交到線上去,然后B提交了一個版本,導致編譯失敗了,這時,A就無法提交,因為提交就會掛,要等待B修復問題才能提交,這時A的提交和B的作業就產生了沖突,
第二種情況,多個分支往同一個分支合并,FeatureA先合進主干,FeatureB晚了一點結果發現無法合并,因為基線不一樣了,這時候必須先解決掉代碼沖突才能合進去,

如上圖,假設現在有3個人,A、B和測驗C,每個人的點代表它做的任務,比如A一直在做自己的事情,每完成一個事情就開始做下一個事情,做完第三個事情的時候他覺得需要去找B聯調一下,就給B發了一個ping,但是B有自己的節奏,在忙他自己的任務,所以并未馬上回應A的請求,他發現有一個任務可以提測了,他就告訴了C,C發現有問題就馬上Pong了回去,但是這時B在忙另外一個任務,沒有回應,C發現B無回應,又發了一次Pong,這時B看到了A和C的訊息,他先處理了A的事情,給A回復了一個Pong的訊息,
我們發現,程式員和程式員,測驗人員和開發人員之間,在整個的開發協作中其實是異步的、延遲協作的程序,每個人并不是收到一個請求就馬上回復,馬上協作,往往都是有自己的步調和自己的動作,可能會產生延遲,所以當產品更復雜,協作更多,團隊更復雜,團隊的人多了以后,協作成本就會快速上升,
在這樣一個異步的、延遲協作的程序中,程式員面對日常開發的作業,需要有一套相應的研發模式,來保證在協作程序中能夠持續地把資訊同步掉,并快速地回應掉,
軟體交付程序,本質是開發者圍繞代碼庫的協作程序,無論是產品代碼、配置、環境和發布流程,都可以通過代碼來描述,并保存到代碼庫里,
因此,研發模式的目的就是約束我們在圍繞代碼庫作業時的行為,本質是一種圍繞代碼庫的行為約束,
研發模式我們狹義地理解為分支模式,包含一系列的行為約束,比如分支型別及其標識、分支的生命周期、Commit在分支間的流轉方式,以及流轉的約束條件,還有分支和代碼之間的對應關系等,接下來我們會一一探討,
研發模式是一系列研發行為的約束,目標是避免沖突、減少等待,在協作的程序中,人多了之后帶來的最大的問題就是沖突變多、等待變多,所以好的研發模式應該盡可能的避免沖突,盡可能的減少等待,
首先看一下研發模式和研發行為之間的對應關系:

這些研發行為和代碼庫行為有一個Mapping(映射)關系,開始新的特性開發時,我們會創建一個新的特性分支,做一次代碼的提交集成,其實就是一次Commit和Push,完成之后進入集成驗證,就做了一次分支的Merge,
同樣地,集成完進入待發布也是在做Merge,而完成發布意味著打一個Tag,代碼庫里的操作記錄了我們的研發行為,所以研發行為和代碼庫的操作可以做到一一映射,

要避免沖突,唯一的方法是大家彼此隔離,分開就沒有沖突,在代碼庫里面,很多時候通過分支的方式,來做作業之間的隔離,避免沖突,
要減少等待,而等待是資訊不同步造成的,盡可能地做到資訊同步,就不用等待,在代碼里面的等待,是代碼之間基線的同步,比如說頻繁地提交,所以其實分支是用來避免沖突和做作業隔離,而頻繁地提交合并是為了做資訊同步,減少等待,
Q:如果是一個人做軟體開發,用什么樣的分支模式?一個人會不會有沖突?
一個人做軟體開發的時候是不會有沖突的,一個人作業的時候不需要很多分支,一個分支就足夠,一個人做開發,也不用等待資訊,因此可以一條主干走到底,但是如果人數擴張到10人、100人,彼此之間就會有作業的隔離,彼此之間也會存在著沖突,也存在著等待,所以在這個程序中,隨著協作的人數越來越多,分支的模式會不斷地發生變化,
4種常見分支模式決議
主干開發

團隊人很少(比如1~2個人)的時候,最常見的研發模式是Trunk—BasedDevelopment,也叫主干開發方式,
主干開發方式一條主干分支走到底,開發的程序中不會有太多的沖突,要求代碼持續集成到主干上去,所以在開發程序中不需要做相應作業的隔離,開發的程序中,所有的開發者在主干上面頻繁地提交,頻繁地集成,這種分支模式下,唯一的分叉出現在發布的時候,為了能夠把發布版本隔離出來,有了發布分支,
這種模式下,不需要做分支隔離,資訊同步通過持續頻繁地提交來保證,在人數比較少,并且整個工程能力比較強的時候,這是我們推薦的研發模式,
但是當參與開發的人數越來越多時,主干開發的沖突幾率就大大增加了,對工程能力的要求也越來越高,
所以說主干開發不是萬能藥,主干上的人越多,代碼提交的沖突機率就越大,而且解決沖突的風險也越大,如果兩個人的時候,即便有沖突我知道只是和另外一個人有沖突,如果是10個人,這中間就會產生很多的問題,
另外在主干開發里面,要保持資訊地同步,需要做頻繁持續地提交,而且每次提交的力度要很小,這針對有一些特性來說,可能只做了一半,這時需要將它提交上去,需要通過特性開關等方式來進行隔離,比如說這個是還未完成的特性,提前把它的開關制成Off,再做相應的提交,但是特性開關本質上也是一個分支,
特性開關只是用代碼的形式拉了一個分支,但是這個分支只有打開的時候才能跑到,本質上還是一個分支,如果特性開關比較多,它在一定程度上會把代碼變得很脆弱,維護起來比較麻煩,
主干開發當很多人同時參與時,代碼沖突的機率很大,而且特性開發的時候也有很多的風險,大家彼此之間需要隔離,
Git-Flow

Git—Flow的基本原則是需要什么分支就給什么分支,任何事都有很明確的分支,比如說要集成,就有develop分支,要開發就有feature分支,要發布有release分支,每個都是不同的分支,每種型別的分支都有確定的用途,
比如說feature分支,是很多個feature并行開發的時候用來去做作業隔離,避免彼此之間有沖突,而release分支是用來做發布的隔離,使得發布之間不會有沖突,
我們發現這種模式很好地做了隔離,但是在資訊同步的程序中,它需要基于develop頻繁地集成去做同步,并且在各個分支中間做相應的cherry-pick或者是rebase這樣的方式來做的,
這個時候,我們就會發現分支太多,而且一個commit從feature開發到最終發布要經歷好幾個分支,其中分支的流轉和merge規則非常麻煩,
所以Git—Flow也不是仙丹,過多的分支增加了分支管理的復雜度,還有如果Feature分支的生命周期特別長,它的合并耗時也會變得很長,而且Develop分支和Master分支同時存在,好像Develop分支的意義不是特別大,另外區分Feature分支和hotfix好像意義也不是特別大,
所以Git—Flow雖然增加了很多的分支,讓各種作業盡可能地隔離開來,但是它資訊同步是很麻煩的,而且它管理這些分支的難度也特別大,
GitHub-Flow

GitHub引入了一個分支模式叫GitHub—Flow,明顯比Git—Flow簡單很多,沒有Develop,沒有hotfix,也沒有Release,當需要開發的時候拉一個Feature分支,開發完就合并Master做發布,
這個程序中,它的隔離只發生在開發程序中,它的資訊同步通過持續地往Master去做集成,和頻繁從Master里面Pull代碼來實作,它的發布程序是基于主干Master分支做的,因此沒有在發布的程序中做相應地隔離,
這時候又會帶來一個問題,就是Master分支需要做持續集成,這個分支既是集成的地方也是發布的地方,一旦集成后出現問題,它會把所有的作業堵塞掉,無法發布也無法合并,
所以GitHub—Flow很簡單,可以做相應地隔離,但是如果說本身基礎設施或工程能力比較弱,它會限制你集成和發布的頻率,
GitLab-Flow

GitLab—Flow和GitHub—Flow區別是在發布程序中有了Pre-production分支和Production分支,基于開發、集成和發布程序中不同的環境分配了相應的分支,
完成集成以后是在Master分支上,下面一步將會切換到預發分支上,對應Commit的版本已經達到了預發的條件,在預發上做完驗證以后再將其同步到Production分支,說明它已經達到了發布的條件,所以它是逐級Promotion(晉級)的程序,逐步從集成的環境Promotion到預發環境,再Promotion到生產環境,
我們簡單地介紹了一些常見的分支模式,下面我們再來比較一下他們之間的優劣,

TBD分支少,實施簡單,做起來不需要太多的理解成本,但是它對團隊協作的成熟度和紀律都有很高的要求,一旦有人不遵守紀律,那主干就會成為你的夢魘,這時就很難很好地去做持續地集成和發布了,一旦它出現問題,所有人都被Block,這是主干方式的優缺點,
Git—Flow特性之間可以并行開發,規則很完善,每個分支的職責特別明確,再大的團隊協作基本上也不會有太多的問題,但是它分支太多,規則太復雜,而且分支生命周期長,合并沖突會比較頻繁,尤其是Develop,Master是長期存在的,
對于GitHub—Flow,Git—Flow能支持的基本上它也能支持,但是這里面有一個問題,它的集成只有在Master分支去做,因此對集成紀律有很高的要求,而且集成和發布在一個分支上,一旦集成分支中斷,無論是集成還是發布都會被中斷,
Gitlab—Flow也是并行開發,但是開發分支還是會有生命周期長的問題,有合并沖突的風險,另外,發布分支之間是有耦合的,比如說Prodution和Pre—Prodution之間,是基于Promotion來耦合,所以彼此之間也是一種中斷阻塞的方式,而且很多的開發分支,Prodution和Pre—Prodution,也增加了分支管理的復雜性,
因此,我們發現沒有哪個分支模式是絕對好的,也沒有哪個是絕對差的,
對于分支有一個簡單的原則,即控制分支數目,小批量頻繁集成,控制分支的數目也就是做到作業隔離,但是又增加太多管理成本,而小批量頻繁集成可以加速資訊同步,
所以一個簡單的原則就是,從最大化生產力和最小化風險的角度,盡可能地控制分支的數目和小批量頻繁集成,
最大化生產力:所有人作業在公共區域內,除了一條長期的,不被中斷的開發主干外,沒有任何分支,也并無其他規則,代碼的提交程序相當簡單,但是,每一次的代碼提交,都有可能破壞整個專案的集成,進而導致專案進度的中斷,
最小化風險:所有人都作業自己的分支上,每個人的作業是相互獨立的,沒人可以打斷其他人的作業,這樣,減少了開發被打斷的風險,但是,這種做法卻增加了額外的流程負擔,同時,協作變得非常困難,所有人都不得不謹小慎微地合并自己的代碼,即便是整個系統中非常小的一部分,也是如此,
那么怎么設計或選擇適合自己的分支模式?
請參考:3個案例,詳解如何選擇合適的研發模式
作者 | 張燎原、張裕
本文來自博客園,作者:古道輕風,轉載請注明原文鏈接:https://www.cnblogs.com/88223100/p/Analysis-and-comparison-of-advantages-and-disadvantages-of-4-common-branch-modes.html
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/502603.html
標籤:其他
上一篇:DTSE Tech Talk丨第3期:解密資料隔離方案,讓SaaS應用開發更輕松
下一篇:4種常見分支模式決議及優劣對比
