八卦 Google 的前端開發方式及流程

jopen 10年前發布 | 23K 次閱讀 Google

    原文出處: 百度FEX(@吳多益

他山之石,可以攻玉。

</blockquote>

  話說本人從畢業到現在一直在某 B 公司工作,前些年折騰過不少開發方式和工具,但總覺得或許有更好的方案,所以很好奇其它公司內部是如何工作的,我曾經瀏覽過某 Y 公司內部無所不包的 TWiki,也拜訪過某 F 總部了解他們的開發流程,但對某 G 公司卻了解不多,只零零碎碎知道一些,這兩天抽空梳理了之前收集到的各種資料,希望能給 FEX 后續改進提供參考。

  注意:以下內容主要信息來自網上收集、『In The Plex』這本書及閑聊,純粹為了技術交流和討論,僅代表個人觀點,本人從未在某 G 工作過,不受 NDA 限制,但大部分信息無法確認真偽,加上某 G 很大,每個部門都有可能不一樣,所以這里的信息也是比較片面的,歡迎大家提供更多參考信息。

  分工協作

  首先,某 G 大部分產品線都不區分前端工程師和后端工程師,一個人需要用從前到后都負責開發,盡管這幾年似乎有變化,能看到專門的 Front End 職位了,但應該是很少數產品線的做法。

  N 年前有人去 G 面試過,和他閑聊后了解到某 G 要求應聘者必須至少要會 C++ 和 Java 中的一種,只會 Python/PHP 是不夠的,要是只懂 JS 就更不行了。這個信息很關鍵,能用來解釋一些內部現象,后面我會提到。

  我個人認為前端工程師確實應該了解基本的后端知識,某 B 公司以前很多前端工程師都只負責模板(比如 Smarty)開發,這導致一個很嚴重的問題,那就是前端工程師往往不知道如何搭建環境,開發時需要依賴后端工程師提供環境和數據,嚴重影響了開發效率, 這也是為什么 FIS 還內嵌了本地服務功能。

  另外國內有公司還對前端工程師做進一步細分,按照職能分為寫 HTML/CSS 和 JS 的,對于我所屬的團隊,我個人并不贊同這種做法,因為 HTML 和 JS 是密切相關的,這樣分工將不利于代碼管理與優化,尤其是交互復雜的頁面,因為 JS 很依賴 HTML,拆分反而增加溝通成本,但或許在重運營的網站這么做會更好。

  代碼管理方法

  以下是一些零碎了解到的幾點:

  • 內部所有人都能看到代碼
    • 據說在 09 年時某國家的 office 有例外(來自『In The Plex』第 6 章,內容比較不和諧,這里就不展開了)
    • 提交代碼需要相關人員的 review
    • 這使得某 G 內部工程師可以很方便地切換項目,很少一個人只負責一個項目
  • 代碼只有最新版(trunk),沒有 release 版本,沒有版本號
    • 一般大家喜歡新增接口
    • 如果要修改原有的接口,就必須通知所有使用方,不過因為所有人都能看到所有代碼,所以很容易找到有誰使用
    • 據了解某 F 也是這樣的
  • 有個代碼的搜索引擎
    • 估計和下線的 Code Search 比較像(好像還是某高管寫的,不過我忘記在哪看到的了)
    • 如果想使用某個基礎庫,最好的方法是搜索使用到這個庫的相關代碼,抄過來
      • 我認為這種方式比讓工程師寫文檔靠譜多了,因為絕大部分調用這個庫的代碼都是相似的,所以直接給出例子能讓別人更容易上手
  • 代碼依賴是通過全局的方式統一管理的
    • 我猜應該很類似 Chromium 中的 GYP,熟悉 node 的同學可以理解為 npm,不過是支持多語言的
    • 之前在某 G 工作過的 iOS 工程師也在某篇后來刪除的文章中透露代碼中不放 Xcode 項目文件,而是由工具生成出來(話說這篇文章挺有價值的,可惜老外不喜歡轉帖,導致現在找不到了)
    • 這種依賴管理方式讓人想起某 A 公司(賣書那個,不是賣水果的)內部完善的 SOA 機制,不過某 A 喜歡基于 service 來重用,而某 G 看起來喜歡代碼級別的重用
  • 很少使用第三方庫
    • 只能選用內部維護的版本,比如類似這個 MySQL
    • 會將第三方庫的編譯工具改成內部的,比如 Chromium 中都改成 GYP 方便管理
    • 據說想申請用某個新第三方庫需要審核,周期比較長
  • 代碼管理軟件用的 Perforce
    • 某 G 直接將這個公司買下了(未確認,但下面那篇論文是在某 G 網站上的,所以我感覺消息可靠),Perforce 的員工為某 G 內部定制了一套代碼管理工具
    • 另外我找到一篇 Perforce 的性能優化的論文,這里面透露了很多 G 公司內部的代碼情況(發表時間是 2011 年 5 月),以下信息取自這篇論文:
      • 這個程序用了 17 年,有 2 千萬次 changelist(可以理解就是 ci 數量)
      • 最大的 client 有 6 百萬個文件(應該絕大部分是數據吧,要知道 chromium 項目也就不到 30 萬個文件)
      • 文檔及相關數據文件也放上面
      • Reivew 工具叫 Mondrian(確認就是 Rietveld 的前身)

  整體來說某 G 的代碼管理方式有很多可取之處,尤其是代碼開放,能最大程度地調動開發人員的主動性與協作意識,從而創造出更大的價值。不過沒有版本管理這點是個雙刃劍,我也沒想好是否這樣會更好。

  feature flag

  因為沒有分支,代碼只有一份,所以要實驗新功能就得通過 flag 來控制的,這個 flag 由線上 Borg 系統來管理,能做到針對某一部分的 Cookie 開啟不同的 feature,方便進行對比抽樣。

  如果某個功能最終不上線,后續需要手工刪除相關代碼。

  這個 flag 開關功能在某 F 也有,我認為這是大型網站是必備功能,但需要注意,這個系統本身會成為關鍵節點,之前某 F 的類似系統掛過,直接導致整個網站大部分功能都關閉了,所以一旦出問題后果很嚴重。

  嚴格的代碼檢查

  據說某 G 工程師大部分時間在寫單元測試,單元測試可以保證 UI 無關代碼的質量,但對于頁面測試就很難了,雖然可以使用 selenium,但某 G 內部大家都不愿意寫,我個人認為這個問題確實無解,頁面隨便一改就導致大量測試失效,我還沒見任何一家公司解決(某 F 說他們用的是 Watir,但主要用于保證登錄等基本功能可用),目前看來唯一可行的就是自動頁面截圖 diff,某 G 在 Consumer Surveys 這個產品中也在嘗試

  據說某 G 的項目大多沒有嚴格的上線時間點,所以不能以項目緊急為借口來不寫單元測試,這點和天朝不太一樣,大家更傾向犧牲質量來追求速度。

  另外國外公司一般對瀏覽器兼容性問題都不怎么關注,因為現代瀏覽器中的兼容性問題比以前好得多,這點某 G 和某 F 公司一樣,只支持高版本的 IE。

  因為只有主干,所以提交代碼很謹慎,需要經過 3 個主要階段:

  1. 代碼風格檢查
    1. 應該主要參考這個文檔
    2. 非常嚴格,據說還會檢查命名什么的
    3. 有段子說 Python 作者 Guido van Rossum 寫的 Python 代碼無法通過檢查,所以一直沒提交。。。我認為這是假的,因為他老人家寫的 rietveld 還是挺符合某 G 規范的
  2. 單元測試檢查
  3. 代碼 owner 的 Review

  提交一旦出錯可能會導致影響其它人的工作(因為每個人都依賴主干啊),甚至遭到其它國家 office 工程師的指責,所以大家對于代碼提交都非常謹慎,再三確認,壓力不小。

  在單元測試、代碼風格和 review 的執行上,某 G 做得很徹底,這點值得學習,國內大家似乎更喜歡開發效率而不是質量。

  前端如何開發

  除了 Gmail、Maps、Plus 這樣的特例,基本上都是由后端模板生成頁面,很少項目使用 JS 來寫界面,更少使用 MVC 框架,這點其實在很多公司都差不多,比如某 B 也是一樣的,除了地圖及廣告管家等產品,其它產品基本上都是通過模板生成的。

  某 G 的頁面是通常是由 Java 或 C++ 語言所寫的模版引擎生成的,而且開源出來了,分別是 Closure TemplatesCTemplate,話說某 B 在幾年前也自己寫了個 C++ 的模板引擎,但目前基本被淘汰了。

  對某 G 來說,「前端」工程師要寫 Java 和 JavaScript,而「后端」服務主要是 C++(某些地方開始使用 Go 了,比如這個)。

  前面說到招人時都要會 Java,這帶來的結果是大多數團隊成員更了解 Java 而不是 JavaScript,于是在這種背景下很自然地誕生了 GWT 這個神奇的東西,它在內部很多地方使用,按照內部人士的說法,主要的考慮是:

  • 能自動生成跨瀏覽器瀏覽器代碼
  • 結構規范,通過編譯器就能提前發現很多問題
  • 能使用強大的 IDE 來提高效率(重構、自動完成、方便跳轉到定義等)

  對于專業做前端的同學,看到 GWT 多半不喜歡,感覺就是多此一舉,但如果是 Java 出身的工程師其實是很容易接受的,尤其是對于習慣了 Java 的代碼組織方式及強類型語言的人,反而會很不習慣 JavaScript 這種弱類型的語言,覺得太難控制太容易出錯了,比如拿到一個變量,在 Java 代碼中通過它的類型就能知道它的數據結構,但 JavaScript 就不行了,只能在運行時 console.dir 出來或找相關實現的代碼,從我個人體會來看,對于陌生代碼,JavaScript 版本的理解難度要明顯高于 Java 版本。

  話說某 G 曾經弄過一個叫 Wave 的產品,后來產品失敗后就將代碼開源出來了,我認為這個代碼能反應出 G 內部在使用 GWT 時的開發風格,我用 cloc 統計了一下它的代碼情況,結果如下:

----------------------------------------------------------

Language        files       blank      comment        code

----------------------------------------------------------

Java              2329       50121       139226      245856

Python             34        1308         2537        4451

CSS                 57         617         1670        2791

XML               148        1009         2627        2487

Ant                 15         131           335          987

HTML               8          124           155          831

Bourne Shell     9          61            190          185

Javascript          1         12             26           56

  神奇吧,這么復雜的前端交互應用,只有 1 個 56 行的 JS 文件,而且其實這個 JS 還是無關緊要的,所以你可以理解為什么某 G 只招懂 Java 或 C++ 的工程師了吧。

  后來某 G 的 Lars Bak 大神推出了 Dart,在我看來就是用來取代 GWT 的,前面說到的 GWT 優點在 Dart 都有,而且在 I/O 2012 有一個演講題目是 Migrating Code from GWT to Dart,赤裸裸啊。

  另外其實某 G 內部也不是所有人都喜歡 GWT,比如 Plus 就沒使用,而是直接基于 Closure 開發,并使用 Closure template。

  說到 Closure,就不得不提它的起源:Gmail,在 WebApps 2010 會議上,有篇 PPT 介紹了 Gmail 代碼的情況,以下摘抄其中幾個信息:

  • 2004 年就有 9400 行代碼了,還有個 JS 編譯器(Closure compiler 的前身)來壓縮代碼、檢查錯誤等
  • 2005 年有 22000 行代碼,10000 行注釋
  • 2006 年有 52000 行代碼,23000 行注釋,開始使用面向對象,并初步形成 Closure library
  • 2007 年重寫,代碼達到 90000 行,注釋居然有 97000 行(太厲害了。。。),開始出現模塊化機制,而且出現了 Closure Templates
  • 隨后開始內部使用,并最終對外推出了 Closure 系列工具
  • 演講人認為 Type-checking is important and possible
  • 有報道說在這個會議中演講人還透露 Gmail service 也是用 JS 寫的,代碼有 443000 行
    • 對于這個消息,我不確定是否真實,但確實是有可能,08 年時 Stevey Yegge 也說過某 G 的規范有漏洞,沒說 JS 只能用在前端,而且他還真這么做過。

  最后插一句我的觀點:對于我所處的團隊及用戶類產品來說,GWT 沒有意義,而 Dart 雖然比起 GWT 要好得多,但和 JS 交互實在太麻煩,導致它的使用場景很有限,語法有明顯變化,使得難以讓大部分前端工程師接受(Lars Bak 就在 I/O 2013 上吐槽工程師太糾結語法,看起來大神在內部推廣時肯定遇到不少阻力)。對于類型檢查的好處,我個人是比較贊同的,因此我更喜歡 TypeScript 這種增強形方案,因為它可以逐步適應,既有類型支持的優勢,又能直接使用現有代碼。

  內部工作流程

  以下是打聽到的某個產品項目開發流程:

  • PM 或工程師提出某個想法,UX 做原型 mock
  • PM 申請項目審核(通過率不高)、工程師開發 UX 無關部分
  • 工程師完成開發
  • 線上小流量實驗
  • PM/工程師分析實驗結果,完成報告,申請全量上線(通過率不高)
    • 通過數據來證明這個功能是有價值的
    • 需要解釋這些數據的變化原因
  • 分批逐步上線,這個過程中還會有很多審核
  • 最終確定是否要上線(通過率不高)

  一般整個項目周期很長(至少一季度),項目最終上線時間點無法確定,大部分的項目最終都無法正式上線。

  最大的特點是完全靠數據說話,而不是由某個 PM 決定一切,以前有個視覺設計師在離開 G 后就在博客上吐槽這點,他認為這會導致無法進行大膽的界面改版。

  這個流程和我們搜索產品幾年前的開發流程很類似,對于成熟的搜索引擎來說這么做確實有它的道理,畢竟隨便改個什么都很可能影響收入,當然要十分謹慎了,但這種開發方式并不適合面向用戶類的產品,如社區、游戲等,因為開發周期太長了,很容易錯過時機。

  某人一天的工作

  這里拿 Matt Welsh 來舉例介紹一個工程師在某 G 一天的工作,雖然他不是做前端開發的,但他目前在 Chrome 團隊負責移動 Web 性能優化,所以還是比較相關,而且最重要的是他比較喜歡寫博客,有意無意地透露了很多信息,所以我比較好公開談。

  另外話說他之前還是哈佛的計算機終身教授(!!!),八卦很多,比如差點說服小扎同學不要搞什么社交網絡了,還是好好學習拿畢業證書。。。

  這這篇文章里,Matt Welsh 介紹他的一天是如何度過的(另外還提到了在哈佛當教授是如何度過的,也很有意思),我摘抄如下:

  • 9:00,到公司,查郵件
  • 9:30-10:15,寫代碼,增加功能,編寫單元測試,發起 changelist 代碼 review,喝無糖可樂
  • 10:15-11:00,切換 git 分支到其它項目,查看同事 review 代碼的結果,回復評論并發新版本 changelist
  • 10:00-11:30,再次切換 git 分支,提交一個要運行 3 小時的 MapReduce 任務分析網絡延遲日志
  • 11:30-12:00,和山景城的團隊成員開視頻會議
  • 12:00-12:35,午餐
  • 12:35-14:00,檢查郵件,檢查 MapReduce 任務運行狀態,回復代碼 review 的評論,再次提交代碼,然后查看任務列表確定接下來的工作
  • 14:00-15:00,和在劍橋(有評論指出這里是波士頓的劍橋,不是英國那個)、山景城等多個地區的團隊成員開項目會議
  • 15:00-16:00,喝紅牛,這時 MapReduce 任務已經跑完了,生成圖表,分析數據中不符合預期的部分,整理代碼,準備下一次 MapReduce
  • 16:00-17:00,喝蘇格蘭威士忌(scotch)并玩吉他英雄(Guitar Hero)
  • 17:00,收拾筆記本回家

  看完后我的幾點體會是:

  • 前面提到的代碼只有 trunk 并不準確,當然每個部門確實可能不一樣
  • 代碼 review 做得很認真
  • 看起來任務很明確,所以雖然工作時間是 9-5,但效率挺高,這點我最為好奇的,怎么做到將工作安排這么具體?
  • 除了寫代碼,分析數據也是每天的重要工作,具體分析什么可以通過他的論文了解,看得出來是很細致的

  內部工具

  2008 年前的內部工具情況可以通過這篇文章這個 PPT 了解,不過之后就不清楚了,看起來很多外部工具都有內部版本(Docs、Mail、Talk、Calendar 等)。

  這里說一下 Chromium 項目中我看到的工具使用情況:

  • 網站是基于 Sites 搭建的
  • 設計文檔喜歡使用 Docs,因為可以在線編輯和評論功能,所以多人協作會很方便
  • https://codereview.chromium.org/
  • Groups 中進行討論
  • 使用 code 來管理 issues
  • Buildbots 來進行編譯和集成測試
  • 搭建了各種檢測工具來保證質量,具體細節推薦讀這本書,看完這本書我最大的體會是沒什么神奇的東西,完全靠細心的工作

  可用的石頭

  以下是我認為可以借鑒的地方:

  • 源碼不分版本,對內部所有人公開
    • 在 FEX 內部已經是這樣了,但我們應該推動更廣泛的開放與共享
  • 嚴格的代碼規范及單元測試機制
    • FEX 所有項目將接入 Travis CI
    • 代碼規范及單元測試的強制檢查
    • 代碼 owner 的 review 機制
  • 通過實際例子來使用,甚至不用看文檔
    • 加強對 demo 及 example 的要求,不能是簡單的 hello,而最好是從產品線實際使用案例中抽取出來
  • 文檔及相關資料和代碼放一起
    • 這能保證找起來很方便
    • 如果由于種種原因不能放一起,至少也要放鏈接
  • 外部產品有內網版,比如 Docs
    • 典型的 Eating your own dog food
    • 在內網提前測試外部產品的新功能,而且一般內部人員都會很積極地吐槽,對產品改進很有幫助
  • GWT 的靜態檢查機制
    • 整理這篇文章時我發現 TypeScript 也已經接近 1.0 版本了,看起來時機快成熟了,后續計劃嘗試 TypeScript
 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!