🎯 什麼情境該想到我
當你「同一個函式庫在公司裡有七、八個版本,沒有人知道升級它會炸到誰」的時候。
⚙️ 怎麼用(步驟 / 公式)
意圖:全公司共用的原始碼儲存庫,是把區域性發現整合到整個組織最強大的機制之一——更新任何東西(例如一個共用函式庫)都會快速且自動地傳播到每一個使用它的服務,並透過每個團隊的部署管線整合進去。
規模參照(Google,2015):單一共用儲存庫超過十億個檔案、超過二十億行程式碼,被他們的兩萬五千名工程師全部使用,橫跨每一個 Google 產品(Search、Maps、Docs、Google+、Calendar、Gmail、YouTube)。Randy Shoup:「Google 防止失效最強大的機制就是單一程式碼儲存庫。任何人 check in 任何東西進 repo 都會產生一次新的 build,而它永遠用最新版本的一切。」
除了原始碼,還要放進去的東西
- 函式庫、基礎設施與環境的組態標準(Chef recipes、Puppet manifests 等)
- 部署工具
- 測試標準與工具,包含資安
- 部署管線工具
- 監控與分析工具
- 教學與標準(Tutorials and standards)
配套的擁有者制度(這是這條的核心,不是附加品)
- 在 Google,每一個函式庫(libc、OpenSSL,以及內部自行開發的如 Java threading libraries)都有一位 owner。
- 這位 owner 負責確保該函式庫不只是能編譯,還要成功通過所有相依專案的測試——就像現實世界的圖書館員一樣。
- 這位 owner 也負責把每一個專案從一個版本遷移到下一個版本。
- 理想上只允許一個版本存在於生產環境,確保生產環境跑的東西承載了組織最好的集體知識。
- 反例:一個組織在生產環境跑著八十一個不同版本的 Java Struts 框架函式庫——除了其中一個之外,其餘全部都有嚴重的安全漏洞。維護所有這些版本(每個都有自己的怪癖)造成巨大的維運負擔與壓力;而這種歧異性又讓升級變得有風險且不安全,於是進一步打消開發者升級的念頭,惡性循環繼續下去。
- 若無法從單一原始碼樹建置一切,就必須用別的方式維護已知良好的函式庫與相依版本,例如全組織的 Nexus、Artifactory、Debian 或 RPM repository,並在有已知漏洞時更新這些 repository 與生產系統。
以自動化測試當文件
- 確保每個共用函式庫都包含大量的自動化測試,這些函式庫就會變成自我文件化(self-documenting),直接示範給其他工程師看怎麼用。
- 若已經有 TDD 實踐(測試先於程式碼),這個好處幾乎是自動獲得的:這個紀律把測試套件變成系統的、活的、最新的規格。任何想理解怎麼用這個系統的工程師,都可以去看測試套件找到可運作的 API 使用範例。
- 再搭配每個函式庫或服務各自的討論群組/聊天室,讓提問者能從其他使用者(通常比開發者回得更快)拿到答案。
編纂非功能需求(Codified NFRs)——八項全列
把可維運性寫成清單,套用到所有生產服務。書中的例子是確保我們具備:
- 應用程式與環境中足夠的生產遙測
- 精確追蹤相依關係的能力
- 有韌性且能優雅降級的服務
- 版本之間的前向與後向相容性
- 封存資料以管理生產資料集大小的能力
- 跨服務輕鬆搜尋與理解 log 訊息的能力
- 追蹤使用者請求穿越多個服務的能力
- 簡單、集中化的執行期組態(使用 feature flags 等)
書中對這份清單有一句明確的歸屬宣告:這些全都是建構該服務之團隊的責任。
原文(擁有者制度):「every library (e.g., libc, OpenSSL, as well internally developed libraries such as Java threading libraries) has an owner who is responsible for ensuring that the library not only compiles, but also successfully passes the tests for all projects that depend upon it, much like a real-world librarian. That owner is also responsible for migrating each project from one version to the next.」(L10822–10826)
原文(八十一個版本的反例):「Consider the real-life example of an organization that runs eighty-one different versions of the Java Struts framework library in production—all but one of those versions have critical security vulnerabilities」(L10828–10830)
原文(NFR 的責任歸屬):「These are all responsibilities of the team building the service.」(L10916–10917)
原文(測試即活文件):「This discipline turns our test suites into a living, up-to-date specification of the system.」(L10858–10859)
🧪 我實際套用的紀錄
- (待填)
⚠️ 注意 / 什麼時候不適用
- 沒有 owner 的單一儲存庫只是把混亂集中在一起。 這條真正在運作的部分是「每個函式庫有一位負責通過所有下游測試、並負責推動遷移的人」,不是 repo 的物理形狀。
- 「生產環境只允許一個版本」需要下游有全面的自動化測試與持續整合來快速偵測回歸,否則遷移會變成無法承受的風險。
- Google 也不是全部塞在一起:Chrome 與 Android 專案在另一個獨立的儲存庫,某些保密演算法(如 PageRank)只有特定團隊能存取。
- 若你的組織無法建立單一樹,書中給的替代方案是全組織的 artifact repository(Nexus、Artifactory、Debian/RPM),但你仍必須負責在有已知漏洞時去更新它們。
🔗 相關工具
- 版本控管一切(這條的上游前提:組態、環境、工具全都得先進版控)
- 技術選型收斂(先收斂技術種類,共用函式庫的維護才可能)
- 測試金字塔(自動化測試要多到能當文件,才撐得起 owner 制度)
- 主幹開發(單一儲存庫加上每次 check in 觸發全量建置的搭配)
- 預先核可的資安函式庫(資安的預先核可元件就放在這個儲存庫裡)
- 保留20%產能給非功能需求(NFR 清單要有產能才做得完)
- DevOps手冊