2014年2月1日 星期六

筆記:Introducing Branch By Abstraction


接下來就看看Branch By Abstraction有多厲害,實際看下來,的確是一套很有用的方法,簡單來說,就是把整合的工分散到每日的開發中。但是要實行有一些現實的問題需要克服
  • 當我要新加一個Feature,會改動3個Class,這3個Class可能所有Module都要參考,而且與其它Module的Code綁很緊,要抽成Abstraction要改動的地方也是會很多,根本就是翻了。
  • 就算我做好抽象層,把所有Module參考到這三個Class的地方改為呼叫抽象層,這樣還是對Code有變動,也是有可能對產品造成衝擊。
  • 如果這3個Class的修改連介面都換掉,整個Class改頭換面,煥然一新,原來的使用流程已經不在,就算有抽象層當緩衝,還是免不了對產品造成衝擊。
這些現實的問題,我想是可以克服的,第一就是要有完整的Test,Unit Test,Integration Test,UI Test,但是如果Test不夠完整,可以使用這招嗎?我想答案是肯定的,但是要邊做邊補Test。而沒有任何Feature Branch,大家都只看Trunk,也就是mainline,這件事對目前的我而言,簡直就是美麗的夢境!我自己參與的產品就有遇到這種狀況,目前是分支一個Branch來做,如果用Branch By Abstraction,新的東西就可以不用等好幾個版本之後才進mainline,也不用擔心如果合併回mainline,到底會是怎麼樣的地獄。如果我有機會參與決策,我一定直接就這麼搞。
另一點作者提到除了Release之外,完全沒有其它Branch,這點我還是有點存疑,除非有一套機制讓Developer拿著Commit去取得認證,保證不會Break掉任何東西。不然Developer自己一個人做測試還是有限,如何保證不Break mainline?如果一個產品的開發編制如下:
  • 100個Developer
  • 分成15個Team,有的Team人多,有的Team人少
  • 25個Component,從Web UI,Mobile UI,Database,Domain,Infranstructure.....
  • 有跨Component,跨Team修改的需求,也就是一個需求需要改UI,Domian,Infranstructure一路改到底。
所有人都進mainline,哇塞,這太硬了,如果有個超級CI Server Cluster,Developer把Commit送上去,5分內跑完所有Test,取得Commit Token,然後Commit,那我覺得OK。但是有這麼超級的CI Server嗎???如果沒有,感覺還是以Team為單位,有各自的Private Branch,一周或三天與mainline同步,然後各自有自己的CI,一周整合回mainline一次,把測試的負載分散到各個Team會比較好。Mainline當然也有自己的CI。不過這個方式對於跨Compoent與跨Team的需求,分出Private Branch也是可以,但是Branch要維護就麻煩...感覺跟在某一個Team的Branch會好些....

果然,分Branch就是麻煩的開始...

概要:Developer應該用Branch By Abstraction,而不是在版本控制工具裡面分支(至少對某些"我應該創建一個分支"的情況)。
  • "Branch by Abstraction"是很少人知道的Best practice
  • 避免使用需要合併回mainline的Short lived feature branches
  • 因為這些Branches的狀態隨著不斷開發,可能會無法正常運作,導致developer需要花很久的時間去整合,最後可能就是整合不完,不斷的再整合,這個short lived變成long lived...
但書
架構要滿足以下條件才能用Branch by Abstraction,這些條件與Agile Development相符合:
  • 你已經將Application分成不同的Component
  • 每一個Component在trunk裡面是一個目錄(有可能是階層式)
  • 每一個目錄有它自己的Source,而且可以自己被build出來(有可能是階層式)
  • 你有一組良好的unit tests而且這些tests可以展現components怎麼用
  • CI可以管理大量的Component的建置,Maven-like Repository可以存放Build好的Compoent,只需透過下不同的Command就可以做好Branch相關Component的管理
  • 你的管理方式對Release Planning有良好規畫
  • 每個Developer有絕不能Break Build的Sense
你的Trunk可能會長的像這樣:
<root>
  trunk/
    foo-components/
      foo-api/
      foo-beans/
      foo-impl/
        build.xml
        src/
          java/
          test/
        cruisecontrol-config-snippet.xml
      remote-foo/
    bar-services/
      bar/
        build.xml
        src/
          java/
          test/
        cruisecontrol-config-snippet.xml
      bar-web-service/

當你的團隊想要從Hibernate轉到iBatis,因為底層架構改變,所以架構師可能會建議要建立一個分支,否則trunk可能會Break數周,這時候Branch by Abstraction登場代替Branch by Source Control。

Hibernate:一套很有名的ORM
iBatis:也是一套ORM

Branch By Abstraction步驟
  1. 在要修改的地方導入一個抽象層,底層實作還是原來的實作,然後Commit
  2. 修改所有相關Class,使其呼叫這個抽象層,然後Commit
  3. 打造另一個抽象層的實作,撰寫對應的unit test,確定功能OK後Commit
  4. 步驟2相關Class參考的實作換成新的實作,抽象層不變,然後Commit
  5. 把原來的實作標為廢棄,或是直接砍掉(如果不想要轉移期)
  6. 刪除原來的實作,到這裡已經沒有需要原來的實作了
  7. 移除抽象層(如果抽象層寫的不漂亮)
簡單來說,就是這幾張圖:

一開始長這樣

抽出Abstraction Layer


其它Client呼叫Abstraction Layer


開始做新的Supplier

把舊的Supplier換掉,大功告成


好處
  • 只有一個小團隊會被影響
  • 在修改中,trunk不會被Break,因為整個產品都是可以編譯可以跑的狀態
  • 由於不會被Break,所以管理面可以滿足Schedule
  • 避免Merge Hell
  • 導入抽象層可以增加對架構的了解與優化Model,這件事本身就有好處
當然Branch By Abstraction不是萬靈丹,它只是一種Developer/架構師可以套用的實務作法,它用來取代架構師建議的Long Running Feature Branch,架構師應該爭取使用BBA而不是另開Branch。

什麼時候該Branch
真正的Branch應該只有在Release的時候,應該長的像這樣
<root>
  trunk/
  releases/
    rel-1.0/
    rel-1.1/
    rel-1.2.x/
  • 在Release前幾天才Branch
  • 這個Branch當然是從trunk分支出來
  • 然後作"Production harden"(為了產品化把bug修掉,集中測試,禁止別人亂改),Developer不能Commit到Release
  • 只有被指派的人(在這裡是Release Engineer)才能Commit
  • 讓CI證明trunk一直都保持良好的狀態

24-2009/5/2更新
  • Mercurial,Git取代SVN變成主流
  • 採用TBD,配合"Branch by Abstraction",與"little and often commits",與Agile Development搭配得很好。

Multi Branch VS trunk圖解
使用Multi Branch的示意圖


戰況報導:
  • 紅色是無法正常執行產品所有功能的狀態
  • 在任何分支之間都有可能有合併動作
  • 某些Branch很短命,某些Branch很長命
  • 某些Branch在開發時注意的是使用者介面下去的功能是否正常(應用程式開發Team)
  • 某些Branch在開發時注重底層架構效能(引擎開發Team)
  • 這就是混亂的代表
  • 每個Branch都有可能Release
會遇到的問題:
  • 一個獨立的Branch在經過幾周之後,有可能變成無法發布
  • 研發團隊回報,他們整天在合併,解決合併相關的問題,沒辦法做正事
  • 常會有Regressions,合併的時候總是會漏掉某些東西,然後就被業務部門X爆
  • 標記Branch與處理標記讓人想換工作
如果用Trunk model就會長的像這樣

戰況報導:
  • 所有人的開發都在Trunk上(這張有隱含一些細節,接下來的圖會說明)
  • Release都在Release Branch上做
  • 只有Bug fix會進Release,然後合併回Trunk(能先進Trunk再進Release更好)
  • 幾乎每一天產品都是可以執行的,而且可以Deploy
  • 可以滿足這句: "be ready to go live within a day's notice, and have a high level of confidence",隨時要出都可以
細節部分:

灰色部分可以是Developer本機下載的Code,或是小型的Private Repository,其他團隊看不到,沒有機會也禁止修改。



DevOps Lessons Learned at Microsoft Engineering 筆記

原文: https://www.infoq.com/articles/devops-lessons-microsoft 筆記 組織 講Microsoft裡面的DevOps 故事描述的是Cloud & Enterprise and the Bing ...