前言
人們為電子計算機編寫程式已有 80 多年,但令人驚訝的是,對於如何設計程式、好的程式應該是什麼樣,討論卻一直很少。相比之下,軟體開發過程(如敏捷開發)和開發工具(如偵錯程式、版本控制系統、測試覆蓋工具)已經得到了廣泛討論。物件導向程式設計、函數語言程式設計等程式設計技術,以及設計模式和演算法,也已有大量分析。這些討論都很有價值,但軟體設計的核心問題仍很少被觸及。David Parnas 的經典論文“關於將系統分解成模組的標準”發表於 1971 年,此後 45 年間,軟體設計的水平並未在這篇論文的基礎上取得多少進展。
電腦科學中最基本的問題是 問題分解:如何將一個複雜的問題分解為可以獨立解決的部分。問題分解是程式設計師每天都要面對的首要設計任務,但是,除了這本書裡描述的工作之外,我還沒有在任何一所大學裡找到一門以問題分解為中心的課程。我們講授 for 迴圈和物件導向的程式設計,而不是軟體設計。
此外,程式設計師之間的程式碼品質和開發效率差異很大,但我們很少探究最優秀的程式設計師為何如此出色,也很少在課堂上傳授相應技能。我曾與幾位自己認為很優秀的程式設計師交談,但其中大多數人也難以說清,究竟是哪些具體方法讓他們佔據優勢。許多人認為軟體設計是一種無法教授的天賦。然而,大量科學證據表明,在許多領域,相比先天能力,傑出表現與高品質練習的關係更密切(例如,參閱 Geoff Colvin 的《哪來的天才?練習中的平凡與偉大》)。
多年來,這些問題一直讓我困惑和沮喪。我想知道軟體設計能否透過教學傳授,也猜想設計能力正是優秀程式設計師與普通程式設計師的區別所在。最終,我認定,回答這些問題的唯一辦法,就是嘗試親自開設一門軟體設計課,斯坦福大學的 CS 190 課程由此誕生。我在課上提出一套軟體設計原則,讓學生透過一系列專案理解並實踐這些原則。授課方式類似傳統英語寫作課:學生先寫草稿,獲得反饋,再修改完善,反覆迭代。在 CS 190 中,學生從零開始開發一個具有相當規模的軟體,隨後我們透過大量程式碼審查找出設計問題,再由學生修改專案、解決問題。這樣,學生就能看到如何運用設計原則改進程式碼。
我已經講授過幾輪這門課程,本書正是根據教學過程中形成的設計原則寫成的。這些原則較為抽象,近乎哲學概念(例如“透過定義來規避錯誤”),學生很難僅憑抽象論述理解它們。最有效的學習方式是親自編寫程式碼、犯錯,再觀察錯誤及其修正與這些原則之間的關係。
讀到這裡,你也許會問:我憑什麼認為自己知道軟體設計的所有答案?坦白說,我並不知道。我學習程式設計時,沒有軟體設計課程,也從未有導師向我傳授設計原則,程式碼審查幾乎還不存在。我對軟體設計的認識,來自親自編寫和閱讀程式碼的經驗。在職業生涯中,我用多種語言編寫了約 25 萬行程式碼。我參與的團隊曾從零構建三個作業系統、多個檔案系統和儲存系統、偵錯程式、構建系統及圖形介面工具包等基礎架構工具、一種腳本語言,以及用於文字、圖形、簡報和積體電路的互動式編輯器。在此過程中,我親身經歷了大型系統的問題,也嘗試了各種設計技術。我還閱讀了大量他人編寫的程式碼,接觸過各種好的和壞的做法。
我試著從這些經驗中找出共同之處,歸納出應當避免的錯誤和值得采用的方法。本書正是這些經驗的總結:書中描述的每個問題我都親身經歷過,推薦的每種技術也都在自己的程式設計實踐中成功使用過。
我並不期望本書成為軟體設計的定論。我肯定遺漏了一些有價值的技術,長遠來看,其中某些建議也可能被證明並不好。但我希望本書能開啟關於軟體設計的討論。請結合自己的經驗,判斷書中的方法是否真的能降低軟體複雜性。本書表達的是我的個人觀點,有些讀者自然不會贊同所有建議。如果你不同意,請試著想清楚原因。我很想了解哪些方法對你有效、哪些無效,以及你對軟體設計的其他想法。希望這些討論能加深我們對軟體設計的共同理解;我也會將從中學到的東西納入本書的未來版本。
與我交流這本書的最好方法是將電子郵件傳送到以下地址:
software-design-book@googlegroups.com
我歡迎關於本書的具體反饋,例如錯誤或改進建議,也希望聽到大家對軟體設計的看法和經驗。我尤其希望收到可用於本書未來版本的有說服力的範例。最好的範例既能說明一項重要設計原則,又足夠簡單,用一兩個段落就能講清楚。如果想閱讀他人發到上述郵箱的內容並參與討論,可以加入 Google Group software-design-book。
如果 Google Group software-design-book 將來因故消失,請在網際網路上搜索我的主頁,那裡會提供最新的本書交流方式。請不要將與圖書相關的電子郵件傳送到我的個人電子郵件地址。
我建議你不要盲從本書的建議。總體目標是降低複雜性,這比書中任何一條具體原則或想法都重要。如果嘗試某種方法後發現它並未降低複雜性,就不必勉強繼續使用(不過,請告訴我你的經歷;無論方法是否有效,我都希望得到反饋)。
許多人提出了批評或建議,以提高本書的品質。以下人員對本書的各種草稿提供了有用的意見:Abutalib Aghayev,Jeff Dean,Will Duquette,Sanjay Ghemawat,John Hartman,Brian Kernighan,James Koppel,Amy Ousterhout,Kay Ousterhout,Rob Pike,Partha Ranganathan,Daniel Rey,Keith Schwartz 和 Alex Snaps。Christos Kozyrakis 為類和介面建議了術語“深”和“淺”,代替了之前有點模糊的術語“厚”和“薄”。我很感激 CS 190 中的學生,閱讀他們的程式碼並與他們討論的過程有助於明確我對設計的想法。