![](http://img3m5.ddimg.cn/26/25/29384315-1_u_3.jpg)
開本:16開 紙張:膠版紙 包裝:平裝-膠訂 是否套裝:否 國際標準書號ISBN:9787519864705 作者:[美]提圖斯·溫特斯,[美]湯姆·曼什雷克,[美]海勒姆·賴特 出版社:中國電力出版社 出版時間:2022年03月 
" 編輯推薦 這本書解釋了谷歌做軟件工程的方式,講述了需要考慮的各種權衡。 如今,軟件工程師不僅需要知道如何有效地編程,還需要知道如何發展適當的工程實踐,以使代碼庫可持續且健康。這本書強調了編程和軟件工程之間的區別。 軟件工程師如何管理一個活躍的代碼庫,這個代碼庫在其生命周期裡不斷響應變化的需求,不斷地發展?軟件工程師Titus Winters和Hyrum Wright,攜手技術作家Tom Manshreck,基於他們在谷歌的經驗,坦率而有見地的為大家介紹了的從業者是如何構建和維護軟件的。 “這本書解釋了谷歌做軟件工程的方式,這種方式讓我有很高的生產力,並且很快樂,同時本書也直言不諱的講述了需要考慮的各種權衡。” ——Eric Haugh 谷歌軟件工程師 內容簡介 你將學習到軟件組織在設計、架構、編寫和維護代碼時應牢記的三個基本原則:時間如何影響軟件的可持續性,以及如何使代碼隨著時間的推移而具有韌性。模如何影響工程組織內軟件實踐的可行性。在評估設計和開發決策時,一位典型的工程師需要做出哪些權衡。 作者簡介 作者介紹 Titus Winters,谷歌高級軟件工程師,他是谷歌C 代碼庫的領導者:2億5000萬行代碼,每月成千上萬名不同的工程師在這些代碼上工作。 Tom Manshreck,在谷歌軟件工程部擔任技術作家。他是C Library Team的成員,負責開發文檔,開展培訓課程以及為Abseil,谷歌的開源C 代碼,編寫文檔。 Hyrum Wright是谷歌的一名軟件工程師,他領導著谷歌自動化變更工具團隊。Hyrum對谷歌代碼庫的編輯比公司歷史上任何其他工程師都要多。 譯者介紹 陳軍,江湖稱號“軍少”,深圳敏捷社區發起人,騰訊T12工程效能專家,現主要從事研發效能提升工作,多年軟件工程方法和技術實踐經驗。作者介紹
Titus Winters,谷歌高級軟件工程師,他是谷歌C 代碼庫的領導者:2億5000萬行代碼,每月成千上萬名不同的工程師在這些代碼上工作。
Tom Manshreck,在谷歌軟件工程部擔任技術作家。他是C Library Team的成員,負責開發文檔,開展培訓課程以及為Abseil,谷歌的開源C 代碼,編寫文檔。
Hyrum Wright是谷歌的一名軟件工程師,他領導著谷歌自動化變更工具團隊。Hyrum對谷歌代碼庫的編輯比公司歷史上任何其他工程師都要多。
譯者介紹
陳軍,江湖稱號“軍少”,深圳敏捷社區發起人,騰訊T12工程效能專家,現主要從事研發效能提升工作,多年軟件工程方法和技術實踐經驗。
周代兵,華為軟件工程專家,有多年輔導團隊應用軟件工程方法和技術提升研發能力實踐經驗。
邱棟,東南大學軟件工程博士,華為軟件工程技術專家,有多年軟件工程技術研究和實踐經驗,研究方向包括軟件架構分析與評估,智能化軟件工程等。 目錄 目錄 序 1 前言 3 部分 理論 第1 章 什麼是軟件工程 13 時間與變化 15 海勒姆定律18 案例:哈希排序 18 為什麼目標不是“沒有變化”呢 20 規模與效率 21 阻礙規模化的政策 22 促進規模化的政策 24 案例:編譯器升級 24 左移思想 26目錄 序 1 前言 3 部分 理論 第1 章 什麼是軟件工程 13 時間與變化 15 海勒姆定律18 案例:哈希排序 18 為什麼目標不是“沒有變化”呢 20 規模與效率 21 阻礙規模化的政策 22 促進規模化的政策 24 案例:編譯器升級 24 左移思想 26 權衡與成本 28 案例:白板筆 29 決策投入 30 案例:分布式構建 30 案例:時間與規模的博弈 32 數據驅動的決策 32 軟件工程VS 編程 33 小結 34 本章要點 34 第二部分 文化 第2 章 如何更好地參與團隊合作 37 隱藏代碼 37 天纔神話 38 隱藏有害 40 及早檢測 41 巴士繫數 41 小步快跑 42 拒絕隱藏 44 一切為了團隊 44 社交的三大支柱 45 三大支柱的重要性 46 謙虛、尊重和信任 46 無指責的回顧文化 50 谷歌範兒(Googley) 52 小結 53 本章要點 53 第3 章 知識共享 55 學習的挑戰 55 知識共享的哲學 57 設定基調:心理安全 58 導師制 58 大型群體的心理安全 59 不斷充實知識 60 提問 60 理解上下文61 擴大提問渠道:向社區提問 62 群聊 62 郵件列表 63 YAQS:問答平臺 63 分享你的知識:你總有可以教別人的地方 64 Office Hours 64 技術講座與課程 64 文檔 65 代碼 67 組織知識發展 68 培養知識分享的文化 68 建立規範的信息源 70 讓信息流動73 可讀性:通過代碼評審規範化指導 74 什麼是可讀性流程 74 為什麼需要可讀性流程 75 小結 78 本章要點 78 第4 章 平等工程 79 人類的偏見 80 理解多樣性的必要性 82 文化能力 82 使多樣性具有可操作性 84 拒絕單一的方式 85 挑戰既定流程 86 價值觀與成果 87 保持好奇心,向前推進 88 小結 88 本章要點 89 第5 章 團隊領導的藝術 91 經理和技術主管(或兩者兼任) 91 工程經理 92 技術主管 92 技術主管經理 92 從個人貢獻者到領導者 93 需要擔心的是……嗯,一切 94 僕人式領導95 工程經理 96 “經理”是一個令人厭惡的詞 96 如今的工程經理 96 反模式 98 反模式:雇用平庸的人 98 反模式:忽視低績效員工 99 反模式:忽視“人”的問題 100 反模式:做老好人 101 反模式:打破招聘門檻 102 反模式:像對待孩子一樣對待你的團隊 102 積極的模式 103 拋棄“自我”意識 103 成為一名禪師 104 成為催化劑106 移除障礙 106 成為老師和導師 107 設定清晰的目標 107 坦誠 108 追蹤幸福感109 出乎意料的問題 110 其他提示和技巧 111 對待人像植物一樣 113 內在激勵和外在激勵 114 小結 115 本章要點 115 第6 章 大規模團隊領導力 117 總是在做決策 118 飛機的故事 118 識別盲點 119 識別關鍵的權衡 120 決策,然後迭代 120 總是不在場 122 你的使命:建立一個“自驅”的團隊123 劃分問題空間 123 總是在擴展 126 成功的循環127 重要VS 緊急 128 學會放棄 130 保護你的精力 131 小結 133 本章要點 133 第7 章 度量工程生產力 135 為什麼要度量工程生產力 135 鋻別:它值得度量嗎 137 根據目標和信號來選擇有意義的指標 141 目標 142 信號 144 指標 145 使用數據驗證指標 145 采取行動並跟蹤結果 150 小結 150 本章要點 150 第三部分 流程 第8 章 風格指南與規則 155 為什麼要有規則 156 創建規則 157 指導原則 157 風格指南 165 修改規則 168 流程 169 風格仲裁者170 例外情況 170 指南 171 應用規則 173 錯誤檢查工具 174 代碼格式化工具 175 小結 177 本章要點 177 第9 章 代碼評審 179 代碼評審流程 180 谷歌如何進行代碼評審 181 代碼評審的好處 184 代碼正確性185 代碼理解 187 代碼一致性187 心理和文化方面的好處 188 知識共享 189 代碼評審實踐 190 禮貌而專業190 小的變更 191 清晰的變更描述 193 評審者數量少化 193 盡可能的自動化 194 代碼評審類型 194 綠地代碼評審 194 行為變更、改進和優化 195 缺陷修復和回滾 195 重構和大規模變更 196 小結 197 本章要點 197 第10 章 文檔 199 什麼是文檔 200 為什麼需要文檔 200 像代碼一樣對待文檔 202 了解文檔的讀者 204 讀者的類型205 文檔類型 206 參考文檔 207 設計文檔 210 新手教程 210 概念文檔 212 著陸頁面 213 文檔評審 214 文檔的哲學 216 WHO,WHAT,WHEN,WHERE 和WHY 216 開頭,中間和結尾 217 優秀文檔的要素 217 丟棄文檔 218 什麼時候需要技術文檔工程師 219 小結 219 本章要點 220 第11 章 測試概述 221 為什麼要寫測試 222 “Google Web Server”的故事 223 當今開發速度下的測試 224 編寫,運行,響應 224 測試代碼的好處 227 設計測試套件 228 測試粒度 229 測試範圍 233 碧昂絲規則235 代碼覆蓋率236 谷歌規模下的測試 237 大型測試套件的陷阱 238 谷歌測試的歷史 239 入職培訓課240 測試認證 241 “馬桶測試” 241 如今的測試文化 242 自動化測試的局限性 243 小結 244 本章要點 244 第12 測試 245 可維護性的重要性 246 防止脆弱的測試 247 努力做到不更改測試 247 通過公共API 進行測試 248 測試狀態,而不是交互 252 編寫清晰的測試 253 使測試完整簡潔 254 測試行為,而不是方法 255 不要把邏輯放進測試 260 編寫清晰的失敗信息 261 測試與代碼共享:DAMP,而不是DRY 263 共享值 265 共享設置 267 共享helper 和驗證 269 定義測試基礎設施 270 小結 270 本章要點 270 第13 章 測試替身 273 測試替身對軟件開發的影響 274 谷歌的測試替身 274 基本概念 275 測試替身的示例 275 縫(Seams) 276 模擬(Mocking)框架 277 使用測試替身的技術 279 偽造(Faking) 279 打樁(Stubbing) 279 交互測試 280 實際實現 281 實際實現比隔離更好 281 如何決定何時使用實際實現 283 偽造(Faking) 285 為什麼偽實現(Fakes)如此重要286 什麼時候寫偽實現 286 偽實現的保真度 287 偽實現應該被測試 288 如果沒有偽實現怎麼辦 288 打樁 289 過度使用打樁的危險性 289 何時使用打樁合適 291 交互測試 292 狀態測試優於交互測試 292 何時使用交互測試合適 293 交互測試的實踐 294 小結 296 本章要點 296 第14 章 較大型的測試 299 什麼是較大型的測試 299 保真度 300 為什麼不要有較大型的測試 303 谷歌的較大型的測試 304 較大型的測試和時間 305 谷歌規模下的較大型的測試 306 大型測試的結構 308 被測繫統(SUT) 309 測試數據 314 驗證 315 較大型的測試的類型 316 一個或多個交互二進制文件的功能測試 316 瀏覽器和設備測試 317 性能、負載和壓力測試 317 部署配置測試 318 探索性測試318 A/B 差異回歸測試 319 用戶驗收測試(UAT) 321 探針和金絲雀分析 321 災難恢復與混沌工程 322 用戶評估 324 大型測試和開發者工作流 325 編寫大型測試 325 運行大型測試 326 大型測試的所有權 329 小結 330 本章要點 330 第15 章 棄用 331 為什麼棄用 332 為什麼棄用很難 333 將棄用融入設計 335 棄用的類型 336 建議性棄用336 強制性棄用337 棄用警告 338 棄用流程的管理 339 流程負責人340 裡程碑 340 棄用的工具341 小結 342 本章要點 343 第四部分 工具 第16 章 版本控制與分支管理 347 什麼是版本控制 348 為什麼版本控制很重要 349 集中式版本控制繫統VS 分布式版本控制繫統 351 真實來源 354 版本控制VS 依賴管理 356 分支管理 356 分支等同於在制品 357 開發分支 358 發布分支 359 谷歌的版本控制 360 單一版本 361 場景:多個可用版本 362 “單一版本”規則 363 (幾乎)沒有長周期的分支 363 發布分支呢365 單一代碼倉(Monorepos) 365 版本控制的未來 367 小結 369 本章要點 370 第17 章 代碼搜索 371 Code Search 的用戶界面 372 如何使用Code Search 373 在哪裡 373 做什麼 374 如何用 374 為什麼 375 誰以及何時375 為什麼需要一個單獨的Web 工具 375 規模 375 無需設置即可瀏覽全局代碼 376 專業化 377 與其他開發工具集成 377 開放API 379 規模對設計的影響 379 搜索查詢延遲 380 索引延遲 381 谷歌的實現 382 搜索索引 382 排序 383 權衡 387 完整性:代碼庫的Head 387 完整性:所有結果VS 相關的結果 387 完整性:Head VS 分支 VS 所有歷史 VS 工作空間 388 表達性:Token VS 子串 VS 正則表達式 389 小結 390 本章要點 391 第18 章 構建工具與構建哲學 393 構建繫統的目的 393 沒有構建繫統會發生什麼 395 但是我隻需要一個編譯器 395 用shell 腳本來拯救 396 現代構建繫統 397 一切都是為了依賴 397 基於任務的構建繫統 398 基於制品的構建繫統 402 分布式構建408 時間,規模,權衡 412 處理模塊和依賴 413 使用細粒度依賴與1:1:1 規則 413 小化模塊可見性 414 管理依賴 414 小結 419 本章要點 420 第19 章 Critique:谷歌的代碼評審工具 421 代碼評審工具的原則 421 代碼評審流程 423 通知 424 步:創建一個變更 425 差異比較 425 分析結果 426 緊密的工具集成 428 第二步:請求評審 429 第三步和第四步:理解和評論變更 430 評論 430 了解變更狀態 432 第五步:批準變更(評價變更) 434 第六步:提交變更 435 提交後:跟蹤歷史 436 小結 437 本章要點 438 第20 章 靜態分析 439 有效靜態分析的特點 440 可擴展性 440 易用性 440 讓靜態分析發揮作用的關鍵經驗 441 關注開發者的體驗 441 讓靜態分析成為核心開發者工作流的一部分 442 賦予用戶貢獻的權力 442 Tricorder: 谷歌的靜態分析平臺 443 集成的工具444 集成反饋渠道 445 建議的修復446 按項目定制447 預提交 448 編譯器集成448 編輯和瀏覽代碼時的分析 449 小結 450 本章要點 450 第21 章 依賴管理 451 為什麼依賴管理這麼難 453 衝突的需求和菱形依賴 453 引入依賴 455 兼容性承諾455 引入時的注意事項 457 谷歌如何處理引入的依賴 459 從理論上講,依賴管理 460 沒有變化(又名靜態依賴模型) 461 語義化版本號 462 綁定分發模式 463 Live at Head 464 SemVer 的局限性465 SemVer 可能過度約束 466 SemVer 可能過度承諾 467 動機 468 小版本選擇 469 那麼,SemVer 有效嗎 470 資源無限的依賴管理 471 導出依賴 473 小結 477 本章要點 477 第22 章 大規模變更 479 什麼是大規模變更 480 誰來處理LSC 481 原子變更的障礙 483 技術限制 483 合並衝突 483 “沒有鬧鬼的墓地” 484 異構性 484 測試 485 代碼評審 487 LSC 的基礎設施 489 政策與文化489 代碼庫分析490 變更管理 491 測試 491 語言支持 491 LSC 流程 493 授權 493 變更創建 494 切片與提交494 清理 498 小結 498 本章要點 498 第23 章 持續集成 499 CI 的概念 501 快速反饋循環 501 自動化 503 持續測試 505 CI 的挑戰 511 封閉測試 512 谷歌的CI 515 CI 案例研究:Google Takeout 518 但是我無力做CI 524 小結 525 本章要點 525 第24 章 持續交付 527 持續交付在谷歌的習語 528 速度是一項團隊運動:如何將部署分解為可管 529 隔離評估變更:特性開關 530 力求敏捷:建立發布火車 531 沒有一個二進制是完美的 531 趕上你的發布期限 532 質量與聚焦用戶:隻發布有用的功能 533 左移:更早地做出數據驅動的決策 534 改變團隊文化:建立發布規則 535 小結 536 本章要點 537 第25 章 計算即服務 539 馴服計算環境 540 將瑣事自動化 540 容器化與多租戶 542 總結 545 為托管計算編寫軟件 545 為失效設計架構 545 批處理VS 服務 547 管理狀態 549 連接到服務550 一次性代碼551 CaaS 隨時間和規模的演化 552 抽像容器 552 一個服務統御餘眾 555 提交的配置557 選擇計算服務 558 集中化與定制化 559 抽像層次:Serverless 561 公有雲VS 私有雲 565 小結 566 本章要點 567 後記 569 前言 前言 本書的書名是“Google 軟件工程”。軟件工程到底是什麼意思?“軟件工程”與“編程”或“計算機科學”有什麼區別?為什麼谷歌會把自己對軟件工程獨特的觀點編寫成一本書,在50 年軟件工程的歷史中留下這一筆? 術語“編程”和“軟件工程”在我們的行業中已經交替使用了相當長的一段時間,盡管它們都有不同的重點和含義。大學生們傾向於學習計算機科學,並獲得以“程序員”的身份編寫代碼的工作。 然而,“軟件工程”聽起來更為嚴肅,似乎它意味著應用一些理論知識來構建真實而精確的東西。機械工程師、土木工程師、航空工程師和其他工程領域的工程師都從事工程實踐。他們都在現實世界中工作,運用自己的理論知識創造出真實的東西。軟件工程師也創造“真實的東西”,盡管它相比其他工程師創造的東西來說並沒那麼實實在在。前言 本書的書名是“Google 軟件工程”。軟件工程到底是什麼意思?“軟件工程”與“編程”或“計算機科學”有什麼區別?為什麼谷歌會把自己對軟件工程獨特的觀點編寫成一本書,在50 年軟件工程的歷史中留下這一筆? 術語“編程”和“軟件工程”在我們的行業中已經交替使用了相當長的一段時間,盡管它們都有不同的重點和含義。大學生們傾向於學習計算機科學,並獲得以“程序員”的身份編寫代碼的工作。 然而,“軟件工程”聽起來更為嚴肅,似乎它意味著應用一些理論知識來構建真實而精確的東西。機械工程師、土木工程師、航空工程師和其他工程領域的工程師都從事工程實踐。他們都在現實世界中工作,運用自己的理論知識創造出真實的東西。軟件工程師也創造“真實的東西”,盡管它相比其他工程師創造的東西來說並沒那麼實實在在。 與那些更成熟的工程專業不同,當前的軟件工程理論或實踐並沒有那麼嚴格。航空工程師必須遵循嚴格的指導方針和實踐,因為他們計算中的錯誤會造成真實的損害。總體而言,編程在傳統上沒有遵循這樣嚴格的實踐。但是,隨著軟件越來越融入我們的生活,我們必須采用和依賴更嚴格的工程方法。我們希望本書能幫助其他人看到一條通向更可靠的軟件實踐的道路。 編程的時間性 我們認為“軟件工程”不僅包括編寫代碼的行為,還包括組織在一段時間內用來構建和維護代碼的所有工具和流程。一個軟件組織可以引入哪些實踐來限度地保持其代碼的長期價值?工程師如何使代碼庫更具可持續性以及軟件工程學科本身更為嚴格?對於這些問題,我們沒有基本的答案,但我們希望谷歌過去20 年的經驗能夠為我們找到這些答案指明可能的道路。 我們在這本書中分享的一個關鍵見解是,軟件工程可以被認為是“隨著時間而不斷集成的編程”。我們可以為我們的代碼引入哪些實踐,使其在整個生命周期內,從概念到上市、到維護、再到棄用,具有可持續性(能夠對必要的變更做出反應)?這本書強調了我們認為的軟件組織在設計、架構和編寫代碼時應該牢記的三個基本原則: 時間與變化 代碼在其生命周期內需要如何適應。 規模與增長 組織在發展過程中要如何適應。 權衡與成本 組織如何從時間、變化、規模和增長中所學到的經驗來做出決策。 貫穿所有章節,我們試圖圍繞這些主題,並指出這些原則是如何影響工程實踐的,並讓它們可持續的發展(完整討論見第1 章)。 谷歌的視角 鋻於我們的規模和歷史,谷歌對可持續軟件生態繫統的增長和演變有著獨特的視角。我們希望我們所吸取的經驗教訓能對貴組織的發展和擁抱更多可持續性實踐有所幫助。 我們將本書的主題分為谷歌軟件工程領域的三個主要方面: • 文化。 • 流程。 • 工具。 谷歌的文化是獨特的,但我們在發展我們的工程文化中所吸取的教訓是廣泛適用的。我們關於文化的章節(第二部分)強調了軟件開發企業的集體性,軟件開發是一種團隊工作,恰當的文化原則對於一個組織的成長和持續健康至關重要。 我們的流程章節(第三部分)中概述的技術對大多數軟件工程師來說都很熟悉,但是谷歌龐大規模和多年積累的大型代碼庫為開發實踐提供了一個更完整的“壓力測試”。在這些章節中,著重講述了我們發現隨著時間的推移以及規模的增長而起作用的東西,並且也還有我們仍然沒有得到滿意答案的領域。 後,我們的工具章節(第四部分)說明了我們如何利用對工具基礎設施的投資,來為日益增長和老化的代碼庫帶來收益。在某些情況下,這些工具是谷歌特有的,盡管我們指出了開源或第三方的替代方案(如果適用的話)。我們期望這些基本見解適用於大多數工程組織。 本書中概述的文化、流程和工具描述了典型的軟件工程師希望在工作中學到的經驗教訓。當然並不是隻有谷歌纔能提供好的建議,我們在這裡介紹的經驗不是要指示你的組織應該做什麼。本書是我們的觀點,我們希望你會發現它是有用的,不管直接采用這些經驗,還是在考慮自己的實踐時將它們作為出發點,專門針對自己的問題領域進行優化。 這本書也不打算說教。谷歌本身仍然沒有完美地應用書中的許多概念。我們從失敗中吸取的教訓是:我們仍然會犯錯誤,執行不完美的解決方案,並且需要不斷改進。然而,谷歌工程組織的龐大規模使得每個問題都有多種解決方案。我們希望本書包含了其中的精華。 本書不包含的內容 本書並不涵蓋軟件設計,這是一門需要獨立出書(並且已經有很多內容)的學科。盡管本書中有一些代碼用於說明,但這些原則與編程語言無關,在這些章節中幾乎沒有實際的“編程”建議。因此,本文沒有涉及軟件開發中的許多重要問題:項目管理、API 設計、安全強化、國際化、用戶界面框架或其他特定編程語言的關注點。它們在這本書中被遺漏並不意味著它們不重要。相反,我們選擇不在這裡講述它們,是因為我們無法提供它們應得的待遇。我們試圖使本書中的討論更多的是聚焦於工程,而不是編程。 臨別贈言 這本書代表了所有貢獻者付出的努力和汗水,我們希望你能收到它:把它當做一個了解大型軟件工程組織如何構建其產品的窗口。我們也希望,這是眾多的聲音之一,有助於推動我們的行業采取更具前瞻性的思維和可持續的實踐。重要的是,我們希望你喜歡這本書,並能從這本書中獲得你關心的觀點。 —— Tom Manshreck 內容約定 本書采用以下排版約定: 斜體(Italic) 表示新術語、URL、電子郵件地址、文件名和擴展名。 等寬字體(Constant width) 用於程序示例,以及段落中引素,如變量或函數名、數據庫、數據類型、環境變量、語句和關鍵字。 等寬黑體(Constant width bold) 顯示用戶應鍵入的命令或其他文本。 等寬斜體(Constant width italic) 顯示應替換為用戶提供的或由上下文確定的值的文本。 O’Reilly 在線學習平臺(O’Reilly Online Learning) 近40 年來,O’Reilly Media 致力於提供技術和商業培訓、知識和卓越見解,來幫助眾多公司取得成功。 我們有一群獨家專家和創新者,他們通過圖書、文章、會議和在線學習平臺分享知識和技術。O’Reilly 的在線學習平臺提供按需訪問的直播培訓課程、詳細的學習路徑、交互式編程環境,以及由O’Reilly 和其他200 多家出版社出版的書籍和視頻。 詳情請訪問http://oreilly.com。 聯繫我們 任何有關本書的意見或疑問,請按照以下地址聯繫出版社。 美國: O’Reilly Media, Inc. 1005 Gravenstein Highway North Sebastopol, CA 95472 中國: 北京市西城區西直門南大街2 號成銘大廈C 座807 室(100035) 奧萊利技術咨詢(北京)有限公司 我們有本書的專屬網頁,你可以在那兒找到本書的勘誤、示例和其他信息。網頁地址:https://oreil.ly/software-engineering-at-google。 如果你對本書有一些評論或技術上的建議,請發送電子郵件到 bookquestions@oreilly.com。 有關其他圖書、講座、會議、新聞的信息,請訪問我們的網站:http://www.oreilly.com。 Facebook:http://facebook.com/oreilly。 Twitter:http://twitter.com/oreillymedia。 YouTube:http://www.youtube.com/oreillymedia。 致謝 沒有無數其他人的努力是不可能有這本書的。這本書中的知識都來自我們在谷歌的職業生涯中許多其他人的經驗。我們是使者,他們來到我們面前,在谷歌和其他地方,教導我們現在呈現給你們的東西。我們不能在這裡一一列舉,但衷心地向你們致謝。 我們還要感謝Melody Meckfessel 在項目初期的支持,以及Daniel Jasper 和Danny Berlin 在項目完成過程中的支持。 如果沒有策劃人、作者和編輯的大量合作是不可能有這本書的。盡管作者和編輯在每一章或標注中都得到了明確的認可,但我們還是希望再次感謝那些對每一章做出貢獻的人,他們為本書提供了深思熟慮的意見、討論和評審。 Tom Manshreck:感謝我的父母讓我相信自己,和我一起在餐桌旁完成工作。 Titus Winters:感謝父親,為我指明道路。感謝母親,傾聽我的聲音。感謝Victoria 對我的支持。感謝Raf,做我的後盾。此外,還要感謝Snyder,Ranwa,Z,Mike,Zach,Tom ( 以及Payne 一家), mec,Toby,cgd 和Melody,感謝他們的教誨、指導和信任。 Hyrum Wright:感謝父親和母親的鼓勵。感謝Bryan 和Bakerland 公司,給了我次嘗試軟件的機會。感謝Dewayne,與我並肩作戰。感謝Hannah,Jonathan,Charlotte,Spencer 和Ben,感謝他們的愛和關注。感謝Heather 一路的陪伴。 ![](http://img3m5.ddimg.cn/26/25/29384315-2_u_3.jpg) ![](http://img3m5.ddimg.cn/26/25/29384315-3_u_3.jpg) |