微軟開發部門 DevOps 經驗談 (二) - 從經驗中學習

本文接續 微軟開發部⾨ DevOps 經驗談 (一) - 從 Agile 邁向 DevOps,今天要來談的是從經驗中我們學習到什麼。

適度控管分支讓開發更快速

在 2008 年,我們開發團隊剛開始使用 Agile 時,我們認為可以透過程式碼品質控管,以及版本控制系統所提供的分支 (branch) 功能等方式,讓程式碼維持高品質。剛開始的時候,我們版本控制系統中的分支都是經過精心規劃設計的,工程師開發完成後,必須要從主幹 (trunk) 取得最新的程式碼,將自己所開發的程式碼與主幹的程式碼合併,透過系統建置並且通過所有程式碼品質的檢查,確保開發的程式碼符合我們的規範之後,才能算是開發完成,可以把程式碼簽入 (check in) 到版本控制系統中。

但我們沒有預料到的是,過度的使用分支可能會造成開發流程上無謂的浪費。我們進行新功能的開發時,可能會因為在開發上遇到阻礙開發的事情,所花費的時間超過原本預期,導致開發中程式碼與主幹 (trunk) 太久沒有進行合併 (merge),讓程式碼落差越來越大。這個現象也產生了相當嚴重的合併 (merge) 債務,我們在不同分支的工作好不容易完成之後,卻發現原本主幹中的程式碼與建立分支時有相當大的落差,這是由於其他人在我們的工作進行時,也不斷的把所開發的程式碼加入到主幹之中,所以當我們開發完成要合併程式碼回主幹的時候,就會有大量的合併衝突 (merge conflics) 必須要解決。隨著我們的組織越龐大,分支越繁雜,這樣的情況也會越來越嚴重。

因此在 2010 年時,我們開始針對程式碼分支的規劃進行了改變,我們大量刪減了原本過於繁瑣的程式碼分支架構,只留下了少數幾個分支,而這些分支通常也只是暫時存在。我們同時明確的針對程式碼開發流程進行了改善,減少程式碼從主幹切出分支進行開發到合併回主幹讓其他人可以使用的時間。接著我們嘗試轉換目前所使用的版本控制系統,雖然我們大部分的客戶和合作伙伴都是使用中央化的版本控制系統,但我們仍然決定改為使用分散式的版本控制系統 (例如 Git),當然,Visual Studio Online 和 TFS 都有支援這兩種版本控制系統。使用 Git 的好處是它相當的輕量,並且由於分散式系統的特性,可以很輕鬆的在本地端建立暫時性的分支結構,不會影響原本遠端的分支,所以我們可以在任何需要的時候開啟新的分支,當完成工作並將程式碼合併回主幹後就把這個分支刪除,讓分支不會過多,管理起來更容易。

同時再搭配發送 pull-request 的工作流程,讓 Code Review 和程式碼品質控管可以同時完成,當 pull-request 中的程式碼內容被審核人員確認無誤之後,就會立即的合併回主要分支 (Master Branch),也就是原本的主幹之中,這讓我們程式碼開發流程是順暢且嚴謹的,而且由於每一個分支相當輕量,就比較不容易發生因為在分支上開發過久,開發人員必須花費相當大的精力保持與主幹的程式碼同步。

搭配這套流程可以把開發人員的工作週期相對的縮短,由原本冗長的開發時程,轉變為一個一個短週期的工作項目,也讓完成工作項目變得更加容易,並且隨時可以合併回主要分支中,達到一個更容易持續整合的循環,分支也不會因為離開主要分支過久,而有許多合併衝突要解決,一旦我們完成工作合併回主要分支後,所建立出來的分支隨時都可以刪除,讓分支的管理工作更容易進行。

保持敏捷

我們雖然決定要使用 DevOps 作為新的流程,但我們一樣會繼續遵循著 Scrum 的精神,Scrum 有著讓我們能夠方便進行溝通的優點。舉例來說,我們的主要工作團隊單位是以開發某項特定功能來視為一個小組,約莫等於 Scrum 的一個 Team,Product Owner 會坐在我們團隊的中間,與我們一同工作,Product Owner 和工程師的主管共同代表著我們工作團隊的意見。

我們遵循著讓團隊獨立自主,並努力增進團隊之間的認同感,這也會讓一些化學效應開始發生在團隊之中,我們團隊的成員都是多才多藝的,我們也不會特別區分開發人員或是測試人員,而是只有一種共同的工程師角色。(這點對於提升士氣十分有幫助)

我們盡可能的讓團隊成員互相熟悉,在每個功能開發團隊中約有 8~12 個工程師,我們讓團隊成員至少一起工作 12~18 個月,甚至更久。當工作量超出團隊負荷時,我們也不會對團隊成員施壓,希望他們能夠自己消化滿出來部分的工作,而是尋求其他團隊的幫助,幫我們分擔這些工作內容。

同時,我們讓每一個功能開發團隊坐在同一個團隊工作區 (參考圖一),每個團隊擁有一個專屬的房間,而並不只是開放空間的一部份。團隊成員除了坐在一起工作之外,也能夠隨時進行溝通,不用擔心打擾到其他功能開發團隊。除此之外,團隊工作區附近還有許多小房間提供成員進行需要專注的工作,或是暫時性離開團隊進行思考或放鬆,基本上每個團隊成員在工作區中都是非常自在的,甚至當需要進行每日站立會議時,只要在自己的座位上站起來就可以開會了!


圖一、功能開發團隊的成員們一起坐在團隊專屬的房間中

我們通常會根據經驗來規劃三週的 Sprint,對我們來說,要能夠在這麼短的週期中,替一個在全球都提供服務的網站,開發出具有足夠價值的功能是相當困難的。但是如果開發週期過長,可能會讓功能開發充滿各種不安因素,也無法確保自己所開發功能的方向是對的。在微軟的某些團隊甚至使用兩週的 Sprint,讓他們可以快速根據線上功能使用情況的反饋,不斷修正自己所進行開發的項目的方向是否正確,而不是讓 Sprint 淪落為計算時間的單位。

透過這種開發模式,要驗收功能開發的完成也非常簡單,當開發人員完成自己新功能的開發之後,這些新功能會在 Sprint 結束後發佈到上百萬的使用者面前讓他們使用,而當新功能在線上發生的異常時,開發人員也會馬上知道,並且很快的找出發生異常的原因,並且修正它。

我們的 Scrum Master 是由團隊成員輪流擔任的,這也讓每個人都有機會學習怎麼作為一個好的 Scrum 領導者,我們同時盡可能的讓 Sprint 的進行更加輕量化,只保留了 Sprint 透明好溝通的優點。在 Sprint 開始時,每個功能開發小隊會從產品的 backlog 中認領想要進行的工作項目,並且撰寫一頁 Email 說明他們的開發計畫,信中會附上 backlog 在 Visual Studio Online 上的連結供大家瀏覽 backlog 內容,而 Sprint 開發結果的檢驗也是透過更新這個 mail,如果需要的話還會再額外附上三分鐘的簡短說明影片,影片中將會以客戶的角度來說明如何使用團隊開發的新功能,以及這個新功能有什麼優點。

我們讓團隊規劃盡可能的精簡,通常我們會定下未來十八個月的目標,做為我們開發的主要方向,而這些目標通常是透過一些操作上的需求、想像功能使用的情境、概念影片或是簡短的構思文件來決定的。每隔六個月,我們團隊與團隊間也會根據需求互相交換開發項目或是合作夥伴,每隔三個 Sprints,功能開發團隊的隊長也會一起進行新功能的跨團隊溝通會議,分享交流團隊工作內容的優先順序,確認自己團隊進行的方向沒有偏離目標,同時交換新資訊和同步不同小隊間的訊息。舉例來說,我們可能會透過功能會議來重新決定我們開發新功能的順序以及開放哪些新功能給使用者使用。

根據使用者經驗調整方向

在傳統的 Agile 開發流程中,Product Owner 會決定產品 Backlog (PBIs) 的優先順序,PBIs 也通常被視為開發時的需求。PBIs 會使用使用者故事 (User Story) 的方式來撰寫,雖然 PBIs 的概念是有彈性的,但決定之後不太會去改變它,我們以前也是使用這種方式進行開發。

但為了轉換到 DevOps 的開發流程,我們並沒有使用這樣的模式太久,我們嘗試著把原本的 PBIs 轉變為假設性質的項目,假設使用者的使用情境以及需要的功能,再根據這些項目來進行功能開發,完成後就部署到線上環境提供使用者使用,然後收集使用者的反饋以及使用情況的數據,利用這些數據來證明或否定我們的假設方向是否正確,透過這種驗證學習循環 (Validated learning) 的方式來確保假設的方向是正確的。

而要能夠執行有效的循環必須要具備有意義的統計樣本資料,以及對照組資料來互相比較數據,判斷所收集的資料是否合理,當然你也必須要了解影響這些數據的因素是什麼,才能夠針對這些數據進行評估。你可以參考圖 7~11 的範例,我們發現使用者在開始使用 Visual Studio Online 時,通常不會馬上建立團隊專案 (Team Project),但是如果沒有團隊專案的話,使用者就沒辦法實際操作或體驗 Visual Studio Online 的好處以及帶來的便利性,下圖二中呈現了以前進入 Visual Studio Online 頁面的樣子。


圖二、由於使用者必須要輸入很多資料,以及進行許多步驟才能開始使用 Visual Studio Online,導致使用者對於試用興趣缺缺

由於以上的原因,我們修改了 Visual Studio Online 在網頁和 IDE 中的操作體驗。圖三中呈現了我們讓使用者能夠 Visual Studio 中,透過兩個步驟,就能建立 Visual Studio Online 帳號,以及建立團隊專案,修改完成後,我們開放這項功能到其中兩個 Scale Units 進行實驗 (總共六個 Scale Unit)。


圖三、我們在兩個 Scale Unit 中,開放改善 IDE 建立團隊專案流程的功能

我們在 IDE 中改善建立專案流程的實驗結果可以在圖四中看到。這個改善增加了新使用者建立團隊專案的數據,從 3% 提升到 20%,足足有 7 倍的提升。


圖四、IDE 建立專案流程的改善,讓新使用者建立團隊專案的機率從 3% 提升到 20%

同時,我們也改善了 Web 版本的註冊流程,從畫面上可以看到是完全不同的註冊畫面,在圖五中可以看到我們對 Web 版本登入畫面的改變。


圖五、可以看到我們簡化了 Web 版本的註冊流程,並把團隊專案的建立移到第二屏

我們計算了在註冊同一天也建立團隊專案的使用者人數,人數從接近 18% 提升到 30% (1.7 倍),可以看到圖表中從深藍色變為紫色的部分,相對於 IDE 改變後的數據成長,在 Web 版的改善率這麼低讓我們感到十分訝異。


圖六、由於另外兩個新功能的結果不如預期,導致 Web 版本建立帳號流程改善的效果不好,在我們關閉其中一個結果之後,主要的結果就更清楚了。

根據追查之後發現,這次的新功能發佈除了 Web 登入流程改善之外,同時間還有另外一個實驗也在進行,導致許多不被預期的使用者也被引導來進行帳號註冊,然後沒有繼續進行更進一步的使用,也因此登入流程改善的數據被影響了,增長的數據就沒有那麼的明顯。這其實也是一個不正確對照組數據的好例子,兩個實驗的結果互相干擾,當我們停止另外一個實驗的干擾之後,團隊專案被建立的數據就上升了,可以參考上表中的淺藍色部分,數據上升到了 50% (2.8 倍的成長,也是 IDE 數據的 2.5 倍)

上面的例子告訴我們,實驗的結果可能有好有壞,而對的實驗不一定會在一開始就有好的成長,就算這個方向是對的,我們還是必須繼續進行反覆的實驗,根據實驗結果調整並再次驗證,才能證明實驗的方向是否正確。

參考資料

1. Branch 是分散式版本控制系統中,我們可以除了透過切割不同的 Branch,讓不同功能的開發可以同時進行並且不會互相干擾,而在 Branch 開發完成之後,我們可以透過 Merge 將 Branch 的內容合併回主要分支之中,讓程式碼同步,而當 Branch由主要分支中切出來的時間過長時,由於其他人同時還是會不斷對主要分支簽入新的程式碼,因為可能會因為改到同一分程式而在 Merge 時遇到 Conflict,工程師必須要解決 Conflict 才能讓 Merge 的工作繼續進行。
2. Validated Learning - 這個名詞出現在 *The Lean Startup.* 一書中,代表有系統將新功能開放給顧客使用,並根據我們所希望收集的資料,針對客戶的使用情況與反應收集數據,觀察數據來評估我們的方向是否正確,然後再次進行同樣的循環,讓自己的功能往對的方向前進。