01 前言
80多年來,人們一直在為計算機編寫程序,但令人驚訝的是,關於如何設計這些程序或什么是好程序的討論卻少之又少。關於軟件開發過程(如敏捷開發)和開發工具(如調試器、版本控制系統和測試覆蓋工具),已經有了相當多的討論。還廣泛分析了編程技術,如面向對象編程和函數式編程,以及設計模式和算法。所有這些討論都是有價值的,但是軟件設計的核心問題在很大程度上仍然沒有觸及。David Parnas的經典論文“關於將系統分解成模塊的標准”發表於1971年,但是在隨后的45年里,軟件設計的技術水平並沒有超過這篇論文。
計算機科學中最基本的問題是問題分解:如何把一個復雜的問題分解成可以獨立解決的幾個部分。問題分解是程序員每天都要面對的核心設計任務,然而,除了這里描述的工作,我還沒有在任何一所大學里找到一個以問題分解為中心主題的類。我們教循環和面向對象編程,但不教軟件設計。
此外,程序員之間在質量和生產力方面存在巨大差異,但是我們很少嘗試去理解是什么讓最好的程序員變得更好,或者在我們的課堂上教授這些技能。我曾與一些我認為是優秀的程序員的人交談過,但是他們中的大多數人都很難清楚地表達出那些給他們帶來優勢的特定技術。許多人認為軟件設計技能是一種天生的天賦,是不能被教授的。然而,有相當多的科學證據表明,在許多領域的傑出表現更多地與高質量的實踐有關,而不是天生的能力(例如,傑夫•科爾文高估了才能)。
多年來,這些問題一直困擾和困擾着我。我想知道是否可以教授軟件設計,我假設設計技能是區分優秀程序員和一般程序員的關鍵。我最終決定,回答這些問題的唯一方法是嘗試教授一門軟件設計的課程。結果是斯坦福大學的CS 190。在這門課上,我提出了一套軟件設計的原則。然后學生通過一系列的項目來吸收和實踐這些原則。這門課的教學方式與傳統的英語寫作課類似。在英語課上,學生們使用一種迭代的過程,他們先寫一份草稿,得到反饋,然后重寫以做出改進。在CS190中,學生們從零開始開發了大量的軟件。然后,我們進行廣泛的代碼審查,以確定設計問題,學生修改他們的項目來解決問題。這讓學生看到如何通過應用設計原則來改進他們的代碼。
我現在已經教過三次軟件設計課,這本書是基於這門課的設計原則。這些原則是相當高水平的,接近於哲學(“定義錯誤不存在”),所以學生很難理解抽象的思想。學生通過編寫代碼、犯錯誤,然后查看他們的錯誤和隨后的修復如何與原則相關,從而獲得最佳的學習效果。
此時您可能會想:是什么讓我認為我知道關於軟件設計的所有答案?老實說,我不知道。當我開始學習編程的時候,我沒有上過軟件設計的課程,也沒有導師來教我設計原則。在我學習編程的時候,代碼評審幾乎是不存在的。我對軟件設計的想法來自於編寫和閱讀代碼的個人經驗。在我的職業生涯中,我用各種語言寫了大約250,000行代碼。我的團隊從零開始創建了三個操作系統、多個文件和存儲系統、基礎設施工具(如調試器、構建系統和GUI工具包)、腳本語言以及用於文本、繪圖、演示和集成電路的交互式編輯器。在此過程中,我親身體驗了大型系統的問題,並嘗試了各種設計技術。此外,我還閱讀了大量其他人編寫的代碼,這使我接觸到各種方法,有好的也有壞的。
在所有這些經驗中,我嘗試提取一些常見的線索,包括要避免的錯誤和要使用的技術。這本書反映了我的經驗:這里描述的每一個問題都是我個人經歷過的,每一個建議的技術都是我在自己的編碼中成功使用過的。
我不希望這本書成為軟件設計的最后定論;我確信我錯過了一些有價值的技巧,從長遠來看,我的一些建議可能會變成糟糕的主意。然而,我希望這本書能夠開啟一個關於軟件設計的對話。將本書中的思想與您自己的經驗進行比較,然后自行決定這里描述的方法是否真的降低了軟件的復雜性。這本書是一篇觀點文章,所以有些讀者會不同意我的一些建議。如果你不同意,試着去理解為什么。我感興趣的是那些對你有用的東西,那些沒用的東西,以及你對軟件設計的其他想法。我希望接下來的對話將提高我們對軟件設計的整體理解。我將把我學到的東西寫進這本書的未來版本里。
與我溝通這本書的最好方式是發郵件到以下地址:
software-design-book@googlegroups.com
我對聽到關於這本書的具體反饋很感興趣,比如bug或改進建議,以及與軟件設計相關的一般想法和經驗。我特別感興趣的是可以在本書未來版本中使用的引人注目的例子。最好的例子說明了一個重要的設計原則,並且簡單到可以用一兩段話來解釋。如果你想知道其他人在電子郵件地址上說了什么,並參與討論,你可以加入谷歌組軟件設計書籍。
如果因為某種原因,軟件設計書籍谷歌組將來應該消失,在網上搜索我的主頁;它將包含如何溝通這本書的更新說明。請不要將與書籍相關的郵件發送到我的個人郵箱。
我建議你對這本書中的建議有所保留。總的目標是減少復雜性;這比你在這里讀到的任何特定的原則或思想都要重要。如果你從這本書中嘗試了一個想法,發現它並沒有減少復雜性,那么不要覺得有義務繼續使用它(但是,一定要讓我知道你的經驗;我想要得到關於什么可行什么不可行的反饋)。
許多人提出了批評或建議,以提高這本書的質量。以下這些人對這本書的不同版本提供了有益的意見:傑夫·迪恩、桑傑·格瑪沃特、約翰·哈特曼、布萊恩·克尼漢、詹姆斯·科佩爾、艾米·奧斯特豪特、凱·奧斯特豪特、羅伯·派克、帕莎·蘭加納坦、基思·施瓦茨和亞歷克斯·斯納普斯。Christos Kozyrakis建議用“深”和“淺”來表示類和接口,而不是以前的“厚”和“薄”,這兩個詞有些模棱兩可。我很感激CS 190的學生們;閱讀他們的代碼並與他們討論代碼的過程有助於明確我對設計的想法。