單一儲存庫:請,必須

單一儲存庫:請,必須

為課程學生準備的文章翻譯 “DevOps 實踐和工具” 在 OTUS 教育計畫中。

您應該選擇單一儲存庫,因為它在您的團隊中促進的行為是透明度和共同責任,尤其是隨著團隊的成長。 無論哪種方式,您都必須投資於工具,但當預設行為是您在命令中想要的行為時,它總是更好。

我們為什麼要談這個?

馬特·克萊因撰寫了這篇文章 “Monorepos:請不要!”  (譯者註:哈布雷翻譯 “單一儲存庫:請不要”)。 我喜歡馬特,我認為他非常聰明,你應該閱讀他的觀點。 他最初在 Twitter 上發布了這項民意調查:

單一儲存庫:請,必須

翻譯:
今年元旦,我將討論單一儲存庫是多麼荒謬。 2019年悄悄開始。 本著這一精神,我向您提供一項調查。 誰是大狂熱分子? 支持者:
- 莫諾雷波
-
- 民調不正確/兩者皆有

我的回答是:“我確實是這兩個人。” 我們不討論 Rust 如何成為一種藥物,而是看看為什麼我認為他對單一儲存庫的看法是錯誤的。 簡單介紹一下自己。 我是 Chef Software 的 CTO。 我們擁有大約 100 名工程師、大約 11-12 年的程式碼庫和 4 個主要產品。 其中一些程式碼位於多重儲存庫(我的起始位置)中,有些位於單一儲存庫(我目前的位置)中。

在開始之前:我在這裡提出的每個論點都適用於這兩種儲存庫。 在我看來,沒有任何技術原因說明您應該選擇一種類型的儲存庫而不是另一種類型。 您可以使任何方法發揮作用。 我很高興談論這個問題,但我對人為的技術原因不感興趣,為什麼一個人比另一個人優越。

我同意馬特觀點的第一部分:

因為在規模上,單一儲存庫將解決多儲存庫解決的所有相同問題,但同時迫使您緊密耦合程式碼,並需要付出難以置信的努力來提高版本控制系統的可擴展性。

無論您選擇單一儲存庫還是多儲存庫,您都必須解決相同的問題。 您如何發布版本? 您的更新方法是什麼? 向後相容? 跨專案依賴? 什麼樣的建築風格是可以接受的? 您如何管理建置和測試基礎架構? 這個清單是無窮無盡的。 隨著你的成長,你會解決所有這些問題。 沒有免費的起司。

我認為馬特的觀點與我尊敬的許多工程師(和經理)的觀點相似。 這是從處理該組件的工程師或處理該組件的團隊的角度來看的。 你會聽到這樣的話:

  • 程式碼庫很大——我不需要這些垃圾。
  • 測試更困難,因為我必須測試所有這些我不需要的垃圾。
  • 處理外部相依性更加困難。
  • 我需要我自己的虛擬版本控制系統。

當然,所有這些觀點都有道理。 這兩種情況都會發生 - 在多存儲庫中,除了構建所需的垃圾之外,我還有自己的垃圾......我可能還需要其他垃圾。 所以我「簡單地」創建了檢查整個專案的工具。 或者我創建一個帶有子模組的假單一存儲庫。 我們可以在這周圍走一整天。 但我認為馬特的論點忽略了主要原因,我非常支持單一儲存庫:

它引發溝通並顯示問題

當我們分離儲存庫時,我們實際上造成了協調和透明度問題。 這對應到我們對團隊的思考方式(尤其是個別成員對團隊的思考方式):我們對某個組成部分負責。 我們的工作相對孤立。 我的團隊和我們正在開發的組件的邊界是固定的。

隨著架構變得越來越複雜,一個團隊不再能夠單獨管理它。 很少有工程師腦子裡有整個系統。 假設您管理一個由團隊 B、C 和 D 使用的共享元件 A。團隊 A 正在重構、改進 API,並更改內部實作。 因此,這些變更不向後相容。 您有什麼建議?

  • 尋找所有使用舊 API 的地方。
  • 新API有哪些地方不能使用?
  • 您可以修復並測試其他組件以確保它們不會損壞嗎?
  • 這些團隊現在可以測試您的變更嗎?

請注意,這些問題與儲存庫類型無關。 您需要找到 B、C 和 D 團隊。您需要與他們交談,找出時間,以了解他們的優先事項。 至少我們希望你會。

沒有人真正願意這樣做。 這比修復該死的 API 沒那麼有趣。 這都是人性的,而且很混亂。 在多重儲存庫中,您可以簡單地進行更改,將其交給處理該元件(可能不是 B、C 或 D)的人員進行審查,然後繼續進行。 B、C 和 D 隊暫時可以保留目前版本。 當他們認識到你的天才時,他們就會煥然一新!

在單一儲存庫中,預設會轉移責任。 A 團隊更改了組件,如果不小心,就會立即破壞 B、C 和 D。這導致 B、C 和 D 出現在 A 的門口,想知道 A 團隊為何破壞組件。 這告訴 A 他們不能跳過我上面的清單。 他們必須談論他們要做什麼。 B、C、D 可以移動嗎? 如果 B 和 C 可以,但 D 與舊演算法行為的副作用密切相關怎麼辦?

然後我們必須談談如何擺脫這種情況:

  1. 支援多個內部 API,並將舊演算法標記為已棄用,直到 D 可以停止使用它。
  2. 支援多個發布版本,一種使用舊介面,一種使用新介面。
  3. 延遲發布 A 的更改,直到 B、C 和 D 可以同時接受它。

假設我們選擇了 1 個 API。 在本例中,我們有兩段程式碼。 舊的和新的。 在某些情況下相當方便。 我們重新檢查舊程式碼,將其標記為已棄用,並與 D 團隊就刪除時間表達成協議。多晶和單晶儲存庫本質上是相同的。

要發布多個版本,我們需要一個分支。 現在我們有兩個組件 - A1 和 A2。 B 隊和 C 隊使用 A2,D 隊使用 A1。 我們需要每個元件都做好發布準備,因為在 D 繼續前進之前可能需要安全更新和其他錯誤修復。 在多重儲存庫中,我們可以將其隱藏在感覺良好的長期分支中。 在單一儲存庫中,我們強制在新模組中建立程式碼。 D 隊仍需對「舊」組件進行更改。 每個人都可以看到我們在這裡付出的成本 - 我們現在的代碼數量是原來的兩倍,適用於 A1 和 A2 的任何錯誤修復都必須適用於它們兩者。 透過多儲存庫中的分支方法,這隱藏在cherry-pick後面。 我們認為成本較低,因為沒有重複。 從實際角度來看,成本是相同的:您將建立、發布和維護兩個基本上相同的程式碼庫,直到您可以刪除其中一個。 不同之處在於,對於單一儲存庫,這種痛苦是直接且可見的。 這更糟,但那很好。

最後,我們到了第三點。 釋放延遲。 A 所做的改變可能會改善 A 團隊的生活。重要,但並不緊急。 我們可以延後一下嗎? 在多儲存庫中,我們推動它來固定工件。 當然,我們會將這一情況告訴 Team D。請繼續使用舊版本,直到趕上! 這會讓你扮演膽小鬼的角色。 A 團隊繼續開發他們的元件,忽略了 D 團隊正在使用越來越過時的版本(這是 D 團隊的問題,他們很愚蠢)。 同時,D 團隊對 A 團隊對程式碼穩定性的粗心態度(如果他們真的談論過的話)評價不佳。 幾個月過去了。 最後,D 隊決定考慮更新的可能性,但 A 隊只有更多的改變。 A隊幾乎不記得他們何時或如何打破了D。升級更加痛苦並且需要更長的時間。 這會將其進一步傳送至優先權堆疊。 直到有一天,我們在 A 遇到安全問題,迫使我們建立一個分支。 A 團隊必須回到過去,找到 D 穩定的點,修復那裡的問題,並做好發布的準備。 這是人們事實上做出的選擇,也是迄今為止最糟糕的選擇。 只要我們能夠互相忽略,對 A 隊和 D 隊來說似乎都是好事。

在單一儲存庫中,第三種確實不是一個選項。 您被迫以兩種方式之一處理這種情況。 您需要了解擁有兩個發布分支的成本。 了解如何保護自己免受破壞向後相容性的更新的影響。 但最重要的是: 你無法避免進行一場艱難的談話。

根據我的經驗,當團隊規模變大時,就不再可能記住整個系統,而這是最重要的部分。 您必須提高系統中不和諧的可見度。 您必須積極努力,讓團隊將目光從他們的組件上移開,專注於其他團隊和消費者的工作。

是的,您可以建立嘗試解決多儲存庫問題的工具。 但我在大型企業中教授持續交付和自動化的經驗告訴我:不使用其他工具的預設行為就是您期望看到的行為。 多存儲庫的預設行為是隔離,這就是重點。 單一儲存庫的預設行為是共同責任和透明度,這就是重點。 在這兩種情況下,我將創建一個工具來平滑粗糙的邊緣。 身為領導者,我每次都會選擇單一儲存庫,因為工具需要強化我想要的文化,而文化來自微小的決策和團隊的日常工作。

只有註冊用戶才能參與調查。 登入, 請。

誰是最大的狂熱分子? 支持者:

  • 莫諾雷波

  • 民調不正確/兩者皆有

33 位用戶投票。 13 名用戶棄權。

來源: www.habr.com

添加評論