Brad Fitzpatrick#

LiveJournal 創辦人、memcached 發明者、網路世代的代表性程式設計師。 生於 1980 年,是書中最年輕的受訪者,也是唯一一位從未生活在沒有網路和個人電腦的世界中的人。

Fitzpatrick 五歲就開始學程式設計,在高中時期建立了第一個商業網站,大學入學前的那個暑假開始開發 LiveJournal。他與 Danga Interactive 的團隊打造了 memcachedPerlbalMogileFS 等開源基礎設施軟體,現在被全球許多大型網站使用。受訪時任職於 Google。


學習程式設計的歷程#

家庭與啟蒙#

  • 父親在 Mostek(記憶體製造商)工作,用零件自製了一台 Apple II clone
  • 母親和父親圍著電視焊接零件,花了好幾個月
  • 父親後來轉到 Intel,負責設計 386 和 486 晶片,家裡總是有最新的電腦
  • 父親是電子工程師,會寫些程式,在 Fitzpatrick 五歲時教他程式設計
  • 五到七歲時就在讀 Apple II 程式設計手冊,同時也在讀 Clifford the Big Red Dog

早期程式設計經驗#

  • 最早學的是 BASIC——第一個程式是 10 PRINT HELLO, 20 GOTO 10
  • 六歲時的重大頓悟:把 40 行逐字母列印的程式替換成一行 Print the variable!
    • 「對一個六歲的小孩來說,那是一次重大的抽象化突破」
  • 大約八到十歲時,一位家族友人介紹了 Turbo C
  • 在計算器上做過一點 Z80 組合語言(TI 計算器)

中學時期#

  • 製作遊戲並賣給同學(五美元一份),還要做 EGA vs VGA 的偵測
  • 遊戲有時候在同學的電腦上無法運行,母親會開車送他去現場除錯
  • 撰寫圖形編輯器和關卡編輯器,後來同學們的老師至今仍在使用他寫的圖形函式庫

高中時期#

  • 沒有正式的程式設計課程,主要靠圖書館的一兩本書和自己摸索
  • 教同學進階程式設計課的內容
  • 學了 Pascal 來考 AP C.S. 考試——跑到鄰近高中上夜間課程,得了五分
  • Tektronix 做實習,第一次接觸到 Unix 和 CGI 程式設計
    • 第一天就在 SPARC 工作站上寫出了 hello-world CGI,興奮到隔天六點就到公司

網路創業萌芽#

  • AOL 封鎖帳號(因為寫 bot 洗聊天室和灌爆 AOL 免費光碟申請表)
  • 在 ISP 上獲得 shell account,開始學 Unix 和 Perl
  • 創建了 FreeVote(投票網站),靠 banner 廣告一個月賺到 25,000-27,000 美元
  • 大學前就賣掉了 FreeVote(約 11,000 美元),因為不想繼續承擔法律責任

Fitzpatrick 的程式設計動力始終來自純粹的樂趣。他母親必須給他「電腦使用券」才能讓他出門跟朋友玩。他形容朋友會來家裡說:「Brad 又在玩電腦了,他好無聊。」


LiveJournal 的誕生與成長#

起源#

  • 大學前最後一個暑假開始開發 LiveJournal
  • 最初只是一個 Perl 腳本,讓朋友們可以發布「我要去吃午餐」之類的訊息
  • 純粹是和朋友開玩笑——在課堂間加入回覆功能,因為想吐槽朋友的貼文
  • 隱私功能(friends-only posts)的起因:一個朋友寫了去派對喝醉的文章,被他父母看到了

從玩具到事業#

  • 原本只開放給朋友,意外有了公開的註冊頁面
  • 在 LiveJournal 新聞頁面上寫「Help. We need to buy servers.」——募了六七千美元
  • 最初運行在一台共享的 Unix 主機上(ISP,月付 $10)
  • 逐步擴展:買了兩台 Dell 伺服器 → 三台 web server + 一台 database → 更多 1U 伺服器

擴展之路(Scaling Journey)#

  1. 單機時代:一台共享 Unix 主機,運行 CGI
  2. FastCGI + Apache 調優:關閉反向 DNS 查詢等優化
  3. 專用伺服器:一台機器、一個 MySQL + 一個 Apache process
  4. Web/DB 分離:用交叉線連接兩台伺服器
  5. HTTP 負載平衡:嘗試 mod_backhand、mod_proxy、Squid(都不喜歡)
  6. 資料庫分片(Database Sharding)
    • 寫了設計文件,將 per-user 和 per-blog 的資料分散到不同的資料庫叢集
    • 每個使用者有一個 flag 標記所在的叢集
    • 線上遷移耗時數月,但避免了停機
  7. memcached 的誕生
    • 洗澡時想到的點子——利用 web server 上閒置的記憶體做分散式快取
    • 當晚用 Perl 寫了 prototype,但 CPU 負擔太重,改用 C 重寫
  8. MogileFS(分散式檔案系統)
    • 因為 NetApp 太貴且有單點故障問題而自建
    • 設計理念:files 是永久的,configuration 會隨時間改變
    • 使用 HTTP 作為儲存協定

Fitzpatrick 事後最大的遺憾是沒有從一開始就設計為分散式系統:「第一次就把事情做對,總比在線上服務上做遷移容易太多了。」所有他描述的擴展步驟,都可以在單機上模擬——關鍵是一開始就不要假設可以 JOIN 不同使用者的資料。


對程式語言的看法#

Perl#

  • 深愛的語言——儘管語法醜陋,但「它從不管你用什麼風格」
  • 可以寫 OO、函數式,或混合風格——語言不強制你
  • 主要缺點:缺乏 optional static typing
  • 在 Google 之前主要使用 Perl;到 Google 後寫得少了

C 和 C++#

  • C++ 語法糟糕,GCC 的錯誤訊息很荒謬——但「你很快就會記住那些模式」
  • 新版 C++ 標準(auto variables、lambdas、for loops)讓它感覺更像 Python
  • 在 Google 主要用 C++ 寫效能關鍵的程式(memcached 在 Google 內部用 C++ 重寫)
  • 使用 scoped pointers 管理記憶體——可以寫好幾天 C++ 而不需要 new 或 delete

Java#

  • 在 Google 寫了大量 Java,但有點膩了
  • Java 社群對 JNI 的排斥讓他困擾——Python 社群反而很樂意用 SWIG 包裝 C++ 函式庫
  • JVM 已經變得很快,很多寫在 C++ 的程式其實不需要

理想中的語言#

  • 想要 optional static typing——在需要時給 runtime hints 和 compile-time checks
  • 想要編譯器能在 compile time 告訴你「你在做蠢事」,但也允許你不在乎時 coerce
  • Perl 最接近他的理想,但仍不夠好

底層知識的重要性#

  • 認為只懂 Java 的優秀程式設計師缺乏全棧思維——他們不會想到 kernel 層面的問題
  • 在 LiveJournal 時期會讀 Linux kernel code 來優化 epoll 和網路效能
  • 「理論上什麼都不用管。實際上,什麼都會壞。那些漂亮的抽象層,底層實作都是垃圾。」

Fitzpatrick 提到一個讓他崩潰的 Perl bug:$_ 不是 lexically scoped,所以在 sort 中修改 $_ 可能破壞遠處其他程式碼的狀態。這個 bug 花了很久才找到,之後他們審計了所有程式碼並建立了「永遠不要這樣做」的規則。


軟體設計方法#

設計流程#

  • 介面開始——common methods、RPCs、queries 是什麼?
  • 如果是儲存系統:資料如何在磁碟上排列?需要哪些 indexes?
  • 先寫 dummy mocks,然後逐步充實實作
  • 越來越多地使用 test-first 的方式——先設計介面和 storage,再逐步加上實際實作
  • 設計文件通常是在編輯器中寫 pseudocode,然後寫成真正的 schema

設計形式#

  • 先寫一個 spec.txt
  • 然後用 pseudocode 描述 schema
  • 驗證「create table」可以運作後,才開始實作
  • 「我總是先困難的部分開始——我喜歡先做困難的事。那些沒完成的專案,通常是因為困難的部分做完了,剩下的無聊部分我懶得做。」

測試哲學#

  • 在開始和其他人合作後才認真對待測試
  • 一旦意識到自己寫的程式碼將永遠需要維護,測試就變得不可或缺
  • 「我會寫測試來防範我自己的程式碼被破壞——然後一旦別人寫了程式碼,我會要求:你確定這能用嗎?寫個測試證明給我看。」
  • 基本規則:來自 end user 的輸入出錯不應該是 runtime crash;內部程式碼出錯則要盡早且大聲地失敗(fail as hard as possible, as early as possible

閱讀程式碼的方法#

突破恐懼#

  • 最初害怕閱讀別人的程式碼——因為「如果不是我寫的,整個設計不在我腦子裡,我就無法理解」
  • 突破點是在向 Gaim(即時通訊軟體)提交 patch 時——「我突然看到了整個設計。不是因為我記住了所有程式碼,而是我開始看到 patterns。」
  • 此後享受閱讀程式碼的過程——遇到不理解的 pattern 時會深入研究

閱讀步驟#

  1. 從 svn 或 tarball 取得乾淨的原始碼
  2. 先讓它成功 build——這本身就是最大的障礙
  3. 做一個小修改(例如在 title bar 加上 “Brad says Hello world”)
  4. 提交 patch 並開始對話——這是進入開源專案最好的方式

純粹出於興趣的閱讀#

  • 會下載 AndroidChromeFirefoxOpen Office 等的原始碼純粹瀏覽
  • 通常用 findless 隨意瀏覽目錄結構
  • 邊 build 邊讀——這兩件事是很好的平行任務

程式碼品質的判斷#

  • 第一個警訊:不遵循 style guide
  • 在 Google 工作後對 coding style 變得特別挑剔——前六七種語言都有嚴格的 style guide
  • 「在一個檔案裡保持一致比用你喜歡的風格更重要」

除錯方法與工具#

工具偏好#

  • Println / printf 是首選——如果環境允許的話
  • 如果有好的 debugger(如 GDB 在 Google 維護得很好),也會使用
  • 最愛的工具:strace——「如果只能選一個工具,就是它。」
    • 不知道程式在做什麼?用 strace 跑一次就能看到所有系統呼叫
  • ValgrindCallgrind 也很好用

除錯策略#

  • 越來越多地使用 refactoring 來除錯——把大函式拆小,分別寫 unit test
  • 「在重構的過程中,你被迫思考程式碼,然後問題就變得明顯了」
  • 重構到一半時,通常會順便把程式碼改得更好,為下一個維護者簡化

最糟的 Bug#

  • 花了 90 分鐘在 GDB 中追蹤一個問題,不斷重跑 MapReduce——最後發現是讀寫了不同的檔案(路徑差了一個 component)
  • 教訓:「我太執著了,沒有退一步檢查:我的 command line 正確嗎?」

團隊管理與人才觀#

管理經驗#

  • 在 LiveJournal 時期學到「不是所有人都像我一樣 self-driven」
  • 有些人只做被要求的事——「Done. Next assignment.」
  • 有些人是純粹的抽象主義者——做大量的 abstraction on abstraction,但程式碼跑不動
  • 關鍵發現:瞭解每個人的動機和工作方式,然後安排適合他們的角色

識別優秀的程式設計師#

  • 看重主動做額外事情的人——不只是學校專案或公司要求的,而是自己有熱情的 side projects
  • 面試題目:大整數乘法(AP 考試等級的問題)——不要求最優解,只要求能做出來
  • Google 面試中被問過的好題目:設計一個 rack 上的機器存在偵測演算法(使用 Ethernet broadcast/unicast,最小化頻寬和延遲)

程式碼所有權#

  • 不認為程式碼應該被個人擁有
  • Google 的做法:一棵巨大的 source tree、統一的 build system、任何人都可以修改任何東西
  • 但有 code review 機制、readability certification(證明你懂某語言的 style)、和 directory owners
  • Check-in 需要三個條件:reviewer 批准、有該語言的 readability、directory owner 批准

結對程式設計#

  • 認為 pair programming 很有趣但不一定適合所有時候
  • 主要好處:強迫你專注在一件事上,避免分心
  • 「如果我遇到無聊的地方,partner 會說『Come on, 我們得做完。』」

Fitzpatrick 的工作時間觀:他偏好深夜工作——「晚上感覺這是我的時間,我在偷別人睡覺的時間。沒有噪音,沒有干擾。」在大學時期,LiveJournal 的伺服器維護只能在晚上做,白天要上課。


對電腦科學教育的看法#

大學經歷#

  • 跳過了很多早期的 CS 課程,因為覺得太無聊
  • 到了 300-400 level 的課程才覺得有趣——但剛好那時候畢業了
  • 資料庫課程的教授似乎沒有實際資料庫經驗——他有一堆 MySQL 和 Oracle 的實戰問題,但只得到教科書的回答
  • 回顧來看:一半的課程學到了全新的東西或正確的術語;另一半純粹是浪費時間
  • 正式的 CS 教育幫助他獲得正確的詞彙來描述他已經知道的東西

對大學的建議#

  • 慶幸自己一邊上學一邊經營 LiveJournal——如果只做其中一件,要麼會無聊,要麼會壓力太大
  • 大學對社交很重要——「如果我只做 LiveJournal,我會被壓力逼瘋」
  • 想讀更多語言學

推薦書籍#

  • Higher-Order Perl by MJD — 強烈推薦
    • 「開始時看似簡單,結果一路越來越瘋狂。就算我已經知道所有那些理論,看它做到極致還是改變了我的思維方式。」
    • 推薦給朋友後也「blow their minds」
    • 認為「任何能讓你用不同方式思考的書」都值得一讀
  • The Art of Computer Programming — 有但沒有深入讀完
    • 如果更早拿到會更有價值
    • 拿到時已經在 CS 課程中學了大部分內容

對數學的看法#

  • 「大多數程式設計師不需要太多數學。對日常工作而言,統計學更重要。」
  • 如果做圖形相關的工作,數學當然很重要
  • 但大多數人做的是 Java enterprise 或 web stuff——這些不需要數學
  • 邏輯統計學比較常用到

關於軟體的現狀與未來#

對桌面軟體的失望#

  • 「我一直都討厭電腦。電腦似乎越來越慢、越來越容易當機。」
  • 十年前的電腦使用體驗反而比現在好——「硬體變快了,但軟體變慢、bug 變多」
  • 原因可能是:電腦太快了,所以不需要寫高效的程式碼;太多的抽象層讓人搞不清楚底下在做什麼

App Engine 與入門#

  • 認為 Google App Engine 是「這一代的 BASIC」——一個按鈕就能把東西放到網路上
  • 現在的小孩不想在自己的電腦上跑「彈球」程式——他們想要網站
  • 對於降低程式設計入門門檻非常樂觀

選擇函式庫的方法#

  • Google search 看評價、看維護者是誰
  • 在開源社群中認識人很重要——選擇你信任的維護者的函式庫
  • 「我選 maintainer 而不是選函式庫」——友善、有熱情的維護者會認真修 bug

程式設計師對新事物的追求#

  • 「我不確定這是絕望——希望新的東西不會爛——還是人類本性」
  • 使用者總是想要更新的版本號,即使它更爛
  • 程式設計師在這方面和一般人沒有統計上的差異

經典語錄#

“Always try to do something a little harder, that’s outside your reach. Read code.”

“Not knowing something doesn’t mean you’re dumb – it just means you don’t know it yet.”

“In practice, nothing works. There are all these beautiful abstractions that are backed by shit.”

“The first time I did anything hard enough was when I do it at LiveJournal, and once I realized that code I write never fucking goes away and I’m going to be a maintainer for life… that’s when testing became important.”

“Strace. I don’t think I could live without it. If I could only have one tool, it would probably be that.”

“It’s always easier to do something right the first time than to do a migration with a live service. That’s the biggest pain in the ass ever.”