01 / 導讀
導讀
引用
Winters, T., Manshreck, T., & Wright, H. (Eds.). (2020). Software Engineering at Google: Lessons Learned from Programming Over Time. O'Reilly Media. Free official edition: https://abseil.io/resources/swe-book
章節概要
第1章:什麼是軟體工程?
第一部分"論點"只有 Titus Winters 撰寫的這一章,它確立了全書的論點:軟體工程是"在時間維度上積分的程式設計"。本章圍繞前言提出的三個主題展開:時間與變化、規模與增長、取捨與成本。它提出海勒姆定律(Hyrum's Law:當 API 的使用者足夠多時,系統的每一種可觀察行為都會被某人依賴),並以依賴雜湊表遍歷順序的程式碼為例加以說明,進而論證預期存活多年的程式碼必須能夠承受變化。另外幾個例子(編譯器升級、"左移"以更早發現問題、分散式構建)展示了哪些政策能隨組織擴充、哪些不能;本章最後討論如何依據資料、先例和論證作出決策。
第2章:如何在團隊中良好合作
第二部分"文化"以 Brian Fitzpatrick 關於工程中人的因素的一章開篇。它批評"天才神話"和隱藏未完成工作的習慣,運用早期發現、巴士因子等概念,提出社互動動的三大支柱(謙遜、尊重和信任),並就如何給予和接受批評、如何開展不追究責任的事後復盤給出實用建議。
第3章:知識共享
本章把學習視為組織層面的問題。它認為心理安全是第一位的,然後介紹擴充知識的各種途徑:提問、導師制、群聊、郵件列表、內部問答平臺、答疑時間、技術講座、文件以及程式碼本身。本章以 Google 的 readability(可讀性認證)流程結尾,這是一種通過程式碼評審實現的標準化導師制。
第4章:為公平而工程
本章認為偏見是產品開發中的預設狀態,團隊必須在工作中融入多元視角和多元文化能力。它以一起公開報道的影像標註失誤作為案例,建議挑戰既有流程,寧可放慢交付,也不要釋出會傷害部分使用者的產品。
第5–6章:如何領導團隊;規模化領導
第5章區分工程經理、技術負責人和兼任兩者的技術負責經理,討論從個人貢獻者轉向領導者的過程,並列出反模式(招聘唯命是從的人、忽視表現差的人、把團隊當孩子對待)和正面模式(僕人式領導、清除障礙、設定明確目標、關注團隊成員的幸福感)。第6章把討論推廣到領導多個團隊的人,提出三條準則:始終在決策(識別盲點和取捨,作出決定並迭代)、始終在準備離開(建立能"自動駕駛"的團隊)、始終在擴充(保護時間、注意力和精力)。
第7章:衡量工程生產力
文化部分的最後一章介紹 Google 的生產力研究團隊如何先判斷一個問題是否值得衡量,再用"目標/訊號/指標"(GSM)框架選擇指標,並檢查指標是否覆蓋程式碼品質、工程師注意力、智力複雜度、節奏與速度以及滿意度(QUANTS)。一個關於 readability 流程的貫穿範例展示瞭如何把定性與定量資料結合使用。
第8章:風格指南與規則
第三部分"流程"從 Google 如何編寫和維護各語言的風格指南講起。規則應當物有所值、為讀者最佳化、保持一致並避免容易出錯的寫法;規則通過由風格仲裁者把關的既定流程修改,並儘可能由錯誤檢查工具和自動格式化工具來執行。
第9章:程式碼評審
本章介紹 Google 的程式碼評審流程:每項變更都需要評審者的批准("LGTM"),還需要程式碼所有者的批准,以及具備該語言 readability 資格者的批准(後兩者可以由同一人或作者本人隱含滿足)。它列出程式碼評審的好處(正確性、可理解性、一致性、知識共享、歷史記錄),以及小變更、好的描述、少量評審者等最佳實踐,並區分從全新程式碼到大規模重構的不同評審型別。
第10章:文件
文件被當作程式碼來對待:有所有者、要評審、要測試,並納入同一工作流。本章討論瞭解讀者、主要文件型別(參考文件、設計文件、教程、概念性文件、入口頁面)、文件評審,以及回答"誰、什麼、何時、何地、為何"和淘汰過時文件等原則。
第11–14章:測試概述;單元測試;測試替身;大型測試
這四章構成全書最大的一塊內容。第11章解釋為什麼自動化測試使變更成為可能,按規模(小型、中型、大型)和範圍對測試分類,介紹"碧昂絲規則"("如果你喜歡它,就該給它加個測試"),討論程式碼覆蓋率,並講述 Google 如何通過"廁所裡的測試"(Testing on the Toilet)等專案建立測試文化。第12章給出編寫可維護單元測試的規則:通過公共 API 測試,測試狀態而非互動,測試行為而非方法,測試中不寫邏輯,測試程式碼寧取"DAMP"而非"DRY"。第13章比較真實實現、偽實現(fake)、樁(stub)和互動測試,建議優先使用真實實現,並警告不要濫用 mock。第14章討論大型測試(其結構由被測系統、資料、操作和驗證組成,型別從效能測試到災難恢復),以及如何避免它們拖慢開發者。
第15章:棄用
流程部分的最後一章認為,移除舊系統往往比構建它們更難;它區分建議性棄用和強制性棄用,並說明如何管理棄用過程:負責人、里程碑、工具,以及維持舊系統執行的真實成本。
第16–17章:版本控制與分支管理;程式碼搜尋
第四部分"工具"從版本控制開始:集中式與分散式系統、長期分支為何有害、基於主幹的開發、Google 的單一程式碼倉庫以及"單一版本規則"。第17章介紹程式碼搜尋(Code Search)——Google 用於瀏覽和搜尋整個程式碼庫的網頁工具,工程師如何使用它,以及規模帶來的設計取捨。
第18章:構建系統與構建理念
本章說明沒有構建系統時會出什麼問題,對比基於任務和基於製品的構建系統,並介紹 Google 的 Blaze(開源版本為 Bazel),包括封閉式與分散式構建、細粒度模組,以及顯式指定版本的外部依賴。
第19–20章:Critique:Google 的程式碼評審工具;靜態分析
第19章逐一介紹一項變更在 Google 評審工具 Critique 中的各個階段,從建立變更、請求評審到評論、批准和提交,並重點介紹"關注集"(attention set)等功能。第20章說明靜態分析怎樣才能有效(誤報少、修復建議可直接採用、融入程式碼評審),並介紹 Tricorder 平臺。
第21–22章:依賴管理;大規模變更
第21章認為依賴管理比原始碼控制更難,考察語義化版本及其侷限,並思考廉價的計算資源和測試可能如何改變這個問題。第22章介紹涉及成千上萬個檔案的大規模變更:為什麼原子化變更變得不可能,用於拆分和測試這些變更的基礎設施(包括 Rosie 工具),以及把它們合入程式碼庫的流程。
第23–25章:持續整合;持續交付;計算即服務
第23章介紹持續整合的概念和 Google 的 TAP 系統,區分快速的提交前檢查和較慢的提交後測試。第24章給出持續交付的慣用做法(功能開關、釋出列車、分階段釋出、只發布真正被使用的功能)。第25章解釋 Google 的 Borg 叢集管理系統如何把工作負載的執行標準化,以及為託管計算環境編寫軟體需要滿足哪些要求。
後記
一篇由 Google 工程副總裁撰寫的簡短後記,重申了全書關於可持續性以及對使用者負責的主題。
核心概念
第1章:論點
- 在時間維度上積分的程式設計:軟體工程不僅包括編寫程式碼,還包括在程式碼整個生命週期內維護和修改它。
- 海勒姆定律:只要使用者足夠多,系統的每一種可觀察行為都會成為某人依賴的東西。
- 左移:在開發流程中更早地發現問題,此時修復成本更低。
第2–7章:文化
- 謙遜、尊重和信任:本書提出的有效團隊協作的三大支柱。
- 心理安全:人們可以提問、承認錯誤的環境,是知識共享的基礎。
- Readability:Google 通過程式碼評審認證工程師掌握某種語言風格的導師制流程。
- 目標/訊號/指標(GSM):一種選擇指標的框架,使指標可以追溯到團隊真正想了解的問題。
第8–10章:風格、評審與文件
- 為讀者最佳化:規則和評審偏向日後易讀的程式碼,而不是寫起來快的程式碼。
- LGTM 與所有權:一項變更需要評審者的批准,也需要受影響程式碼所有者的批准。
- 文件即程式碼:把文件放在原始碼控制中,配有所有者並經過評審,使其保持最新。
第11–15章:測試與棄用
- 測試規模與範圍:按所用資源(小型、中型、大型)和所覆蓋程式碼的多少對測試分類。
- DAMP 而非 DRY:測試程式碼應當描述清楚、含義明確,即使因此有些重複。
- 真實優先於隔離:先考慮真實實現或偽實現,再考慮樁和 mock。
- 強制性棄用與建議性棄用:使用者是被要求還是僅被鼓勵遷離舊系統。
第16–25章:工具
- 單一版本規則:開發者在程式碼庫內永遠不必在同一依賴的多個版本之間作選擇。
- 基於製品的構建系統:宣告輸出和依賴的構建工具,因而能夠封閉、增量、並行地構建。
- 大規模變更(LSC):涉及程式碼庫範圍過大、無法原子化提交的變更,被拆分為可獨立評審和測試的部分。
- 提交前與提交後測試:在變更合入之前執行快速、可靠的測試,之後再執行較慢的測試。
評析
優點
- 清晰的統一思想。 "工程是隨時間推移的程式設計"這一論點以及時間、規模和取捨三個主題在前言和第1章中提出,並在各章反覆出現;因此,關於風格、測試和依賴的政策都是從它們對長期存續程式碼的影響來解釋的,而不是作為規則直接給出。
- 立足於一個組織的實際經驗。 每一章都由負責相應實踐的 Google 工程師撰寫,配有具體故事(雜湊順序引發的錯誤、測試文化的發展史、棄用行動)以及一些內部資料,例如關於工具滿意度的調查結果。
- 兼顧文化、流程與工具。 作為一本工程類書籍,它少見地用整整一個部分討論團隊合作、知識共享、公平、領導力和度量,與程式碼評審、測試和構建系統並列。
- TL;DR 總結。 每章都以一份簡短的要點清單結尾,便於日後回顧,也便於用於討論。
局限
- Google 特有的規模和工具。 許多工具(Critique、TAP、Borg、Rosie、Code Search)是內部工具,單一程式碼倉庫或單一版本規則等做法依賴大多陣列織所不具備的基礎設施;前言本身也說明本書並不是讓人照搬的方案。
- 很少涉及設計和程式設計。 按前言的說法,本書不涉及軟體設計、API 設計、專案管理、安全加固或使用者介面,因此不能充當通用的軟體工程教材。
- 各章風格不一,偏隨筆體。 由於作者眾多,各章深度和語氣差別較大,而且沒有練習、案例思考題或形式化模型。
- 2020 年的快照。 本書描述的是 2019–2020 年前後的實踐和工具,某些細節(如具體工具和組織結構)此後可能已有變化。
在課程中的定位
在本軟體工程書單中,Sommerville 的 Software Engineering 是覆蓋需求、設計、過程和驗證的綜合教材,適合作系統性的概覽;Software Engineering at Google 適合與它配合使用,作為一家大型組織如何處理維護、測試和工具問題的詳細記述。Ousterhout 的 A Philosophy of Software Design 和 Thomas 與 Hunt 的 The Pragmatic Programmer 討論個人層面的設計與技藝,正是本書明確略去的主題,因此與本書搭配良好。
Bass、Clements 和 Kazman 的 Software Architecture in Practice 以及 Jackson 的 Software Abstractions 分別在架構和形式化建模方面更加深入。有一定業界或實習經驗的學生最能從 Winters 等人的書中獲益;沒有這類經驗的學生,先讀 Sommerville 或一本入門書可以提供背景。
如何使用本書
本書面向在職工程師、團隊負責人以及在團隊中寫過程式碼、用過版本控制、測試和程式碼評審的高年級學生。不要求掌握特定語言,書中的程式碼只是示意。
各章相對獨立,可以有選擇地閱讀。第1章必讀,因為它定義了全書使用的術語。如果是測試方面的課程單元,請按順序讀第11–14章;關注程式碼品質,讀第8、9、19、20章;關注釋出工程,讀第16、18 章和第21–24章。對領導力或團隊實踐感興趣的學生應讀第二部分(第2–7章)。第25章要求讀者對分散式系統有一定了解。
可以把每章的 TL;DR 清單當作討論題,並針對每一種實踐提出本書自己提出的問題:在讀者自己專案的規模和程式碼生命週期下,這種取捨是否合理?免費的 HTML 版本在 abseil.io 上以知識共享"署名-非商業性使用-禁止演繹"許可釋出。
版本與來源
本導讀依據 https://abseil.io/resources/swe-book 上釋出的 Software Engineering at Google 免費 HTML 版(第一版,O'Reilly,2020)。內容取材於推薦序、前言全文、目錄中的各部分劃分、全部 25 章(每個小節標題、章節開頭、結論和 TL;DR 清單,其中第1章為細讀)以及後記。
