電腦科學箴言集

turingbooks發表於2011-09-13

  程式設計師常常需要轉換時間單位。比如說,一個程式每秒鐘能處理 100 條記錄,那它處理一百萬條記錄要多少時間?用除法一算,我們就知道要花 10000 秒,按每小時 3600 秒計算,差不多 3 個小時。

 

  然而一年又有多少秒呢?如果我直接告訴你,一共有 3.155 × 107 秒,你可能很快就忘了。事實上,要記住這個很簡單,在誤差不超過 0.5% 的約束下:

 

  π秒就是一個納世紀。

 

  —— Tom Duff ,貝爾實驗室

 

  所以,如果你的程式要執行 107 秒,你就要準備等上 4 個月。

 

   1985 2 月的《 ACM 通訊》曾向讀者徵集與計算有關的一句話箴言。讀者來稿中有一些是沒有爭議的,比如 Duff 法則就是一種很方便的記憶常數的方法。而下面這個關於程式測試方法的法則中的數字則不那麼絕對了(迴歸測試方法儲存老版本的輸入 / 輸出資料,以確保新版本程式能得出同樣的輸出)。

 

  迴歸測試能將測試區間減半。

 

  —— Larry Bernstein ,貝爾通訊研究院

 

   Bernstein 的觀點中所說的數可能是 30% 也可能是 70% ,然而可以確定的是,這些測試節約了開發時間。

 

  不怎麼定量的忠告也存在問題。相信大家都會同意

 

  小別勝新婚。

 

  ——佚名

 

  但也說

 

  眼不見,心不煩。

 

  ——佚名

 

  最後這句話對每個人都適用,對這些話本身則不適用。本章中的很多箴言也存在類似的矛盾。儘管每句話都有真理存焉,我們還是應該有所保留地看待它們。

 

  關於這些箴言的出處,我不得不宣告一下。箴言下的名字基本上都是最早把這句話發給我的人,即使事實上這句話可能出自於他們的堂兄弟。在一些地方我列出了更早的參考文獻以及作者的單位( 1985 9 月時的情況,那正是本章內容最初發表的時候)。我知道我這樣做對不起那些最早說出這句話的人,我只能用下面這句話表達遺憾了:

 

  剽竊即是最誠懇的恭維。

 

  ——佚名

 

  閒話不說了,我直接把這些箴言分成幾個大類,依次列出來。

 

   6.1  編碼

 

  如果還沒想清楚,就用蠻力演算法吧。

 

  —— Ken Thompson ,貝爾實驗室

 

  不要使用反正弦和反餘弦函式——你總能用優美的恆等式,或者是計算向量點積來更好地解決這些問題。

 

  —— Jim Conyngham Arvin/Calspan 高階技術中心

 

  在儲存日期中的年份的時候,請使用四位數字:千禧年快要到了。

 

  —— David Martin ,賓夕法尼亞州諾里斯敦

 

  避免不對稱結構。

 

  —— Andy Huber Data General 公司

 

  程式碼寫得越急,程式跑得越慢。

 

  —— Roy Carlson ,威斯康星大學

 

  你用英語都寫不出來的東西就別指望用程式碼寫了。

 

  —— Peter Halpern ,紐約州布魯克林

 

  注意細節。

 

  —— Peter Weinberger ,貝爾實驗室

 

  如果程式碼和註釋不一致,那很可能兩者都錯了。

 

  —— Norm Schryer ,貝爾實驗室

 

  如果你發現特殊情況太多,那你肯定是用錯方法了。

 

  —— Craig Zerouni Computer FX 公司(英國倫敦)

 

  先把資料結構搞清楚,程式的其餘部分自現。

 

  —— David Jones ,荷蘭阿森

 

   6.2  使用者介面

 

  【最小驚異原則】儘可能讓使用者介面風格一致和可預測。

 

  ——幾位讀者提出

 

  計算機生成的輸入通常會讓一個原本設計接受手工輸入的程式不堪重負。

 

  —— Dennis Ritchie ,貝爾實驗室

 

  手工填寫的表單中有 20% 都包含壞資料。

 

  —— Vic Vyssotsky ,貝爾實驗室

 

   80% 的表單會要你回答沒有必要的問題。

 

  —— Mike Garey ,貝爾實驗室

 

  不要讓使用者提供那些系統已經知道的資訊。

 

  —— Rick Lemons Cardinal 資料系統公司

 

  所有資料集的 80% 中,有 95% 的資訊量都可以用清晰的圖表示。

 

  —— William S. Cleveland ,貝爾實驗室

 

   6.3  除錯

 

  在我所有的程式錯誤中, 80% 是語法錯誤。剩下的 20% 裡, 80% 是簡單的邏輯錯誤。在剩下的 4% 裡, 80% 是指標錯誤。只有餘下的 0.8% 才是困難的問題。

 

  —— Marc Donner IBM 沃森研究中心

 

  在系統測試階段找出並修正錯誤,要比開發者自己完成這一工作多付出 2 倍的努力。而當系統已經交付使用之後找出並修正一個錯誤,要比系統測試階段多付出 9 倍的努力。因此,請堅持讓開發者進行單元測試吧。

 

  —— Larry Bernstein ,貝爾通訊研究院

 

  不要站著除錯程式。那會使得你的耐心減半,你需要的是全神貫注。

 

  —— Dave Storer ,艾奧瓦州錫達拉皮茲

 

  別在註釋裡陷得太深——註釋很可能會誤導你的,你要除錯的只是程式碼。

 

  —— Dave Storer ,艾奧瓦州錫達拉皮茲

 

  測試只能證明程式有錯誤,而不能證明程式沒有錯誤。

 

  —— Edsger W. Dijkstra ,得克薩斯大學

 

  新系統的每一個新使用者都可能發現一類新的錯誤。

 

  —— Brian Kernighan ,貝爾實驗室

 

  東西沒壞,就別亂修。

 

  ——羅納德•里根,加州聖巴巴拉

 

  【維護者箴言】如果我們沒能力修好它,我們就會告訴你它根本就沒壞。

 

  —— Walt Weir ,美國陸軍中校

 

  修正程式錯誤的第一步是要先重現這個錯誤。

 

  —— Tom Duff ,貝爾實驗室

 

   6.4  效能

 

  【程式優化第一法則】不要優化。

 

  【程式優化第二法則——僅對專家適用】還是不要優化。

 

  —— Michael Jackson Michael Jackson 系統公司

 

  對於那些快速演算法,我們總是可以拿一些速度差不多但是更容易理解的演算法來替代它們。

 

  —— Douglas W. Jones ,艾奧瓦大學

 

  在一些機器上,間接定址比基址定址要慢,所以請把結構體或記錄中最常用的成員放在最前面。

 

  —— Mike Morton ,馬薩諸塞州波士頓

 

  在一個非 I/O 密集型的程式中,超過一半的執行時間是花在不足 4% 的程式碼上的。

 

  —— Don Knuth ,史丹佛大學

 

  在優化一個程式之前,請先用效能監視工具找到程式的“熱點”。

 

  —— Mike Morton ,馬薩諸塞州波士頓

 

  【程式碼規模守恆定律】當你為了加速,把一頁程式碼變成幾條簡單的指令時,請不要忘了增加註釋,以使原始碼的行數保持為一個常量。

 

  —— Mike Morton ,馬薩諸塞州波士頓

 

  如果程式設計師自己模擬實現一個構造比編譯器本身實現那個構造還要快,那編譯器的作者也太失敗了。

 

  —— Guy L. Steele, Jr. Tartan 實驗室

 

  要加速一個 I/O 密集型的程式,請首先考慮所有的 I/O 。消除那些不必要的或冗餘的 I/O ,並使餘下的部分儘可能地快。

 

  —— David Martin ,賓夕法尼亞州諾里斯敦

 

  最快的 I/O 就是不 I/O

 

  —— Nils-Peter Nelson ,貝爾實驗室

 

  

 

  那些最便宜、最快而且可靠性最高的計算機元件壓根兒就不存在。

 

  —— Gordon Bell Encore 計算機公司

 

  大多數的組合語言都有迴圈操作,用一條機器指令進行一次比較並分支;儘管這條指令是為迴圈設計的,但在做普通的比較時往往也能派上用場,而且很有效。

 

  —— Guy L. Steele, Jr. Tartan 實驗室

 

  【編譯器作者箴言——優化步驟】把一個本來就錯了的程式變得更糟絕不是你的錯。

 

  —— Bill McKeeman ,王安公司

 

  電每納秒傳播一英尺。

 

  —— Grace Murray Hopper ,美國海軍准將

 

   Lisp 程式設計師知道所有東西的值,卻不知道那些東西的計算成本。

 

  —— Alan Perlis ,耶魯大學

 

   6.5  文件

 

  【否定測試】如果一句話反過來就必然不成立,那就根本沒必要把這句話放進文件。

 

  —— Bob Martin AT&T 公司

 

  當你試圖解釋一條命令、一個語言特性或是一種硬體的時候,請首先說明它要解決什麼問題。

 

  —— David Martin ,賓夕法尼亞州諾里斯敦

 

  【一頁原則】一個 { 規格說明、設計、過程、測試計劃 } 如果不能在一頁 8.5 英寸× 11 英寸的紙 上寫明白,那麼這個東西別人就沒辦法理解。

 

  —— Mark Ardis ,王安公司

 

  紙上的工作沒結束,整個工作也就還沒結束。

 

  ——佚名

 

   6.6  軟體管理

 

  系統的結構反映出構建該系統的組織的結構。

 

  —— Richard E. Fairley ,王安公司

 

  別堅持做那些沒用的事。

 

  ——佚名

 

  【 90 90 法則】前 90% 的程式碼佔用了 90% 的預定開發時間,餘下的 10% 程式碼又花費了 90% 的預定開發時間

 

  —— Tom Cargill ,貝爾實驗室

 

  只有不到 10% 的程式碼用於完成這個程式表面上的目的,餘下的都在處理輸入輸出、資料驗證、資料結構維護等家務活。

 

  —— Mary Shaw ,卡內基—梅隆大學

 

  正確的判斷來源於經驗,然而經驗來源於錯誤的判斷。

 

  —— Fred Brooks ,北卡羅來納大學

 

  如果有人基本上做出了你想要做的東西,你就沒必要自己寫一個新程式。就算你非寫不可,也請儘可能多地利用現有的程式碼。

 

  —— Richard Hill ,惠普公司(瑞士日內瓦)

 

  程式碼能借用就借用。

 

  —— Tom Duff ,貝爾實驗室

 

  與客戶保持良好的關係可以使生產率加倍。

 

  —— Larry Bernstein ,貝爾通訊研究院

 

  把一個現有成熟程式轉移到一種新語言或者新平臺,只需要原來開發的十分之一的時間、人力、成本。

 

  —— Douglas W. Jones ,艾奧瓦大學

 

  那些用手做就已經很快了的事情,就不要用計算機去做了。

 

  —— Richard Hill ,惠普公司(瑞士日內瓦)

 

  那些能用計算機迅速解決的問題,就別用手做了。

 

  —— Tom Duff ,貝爾實驗室

 

  我想寫的程式不只是程式,而且是會寫程式的程式。

 

  —— Dick Sites DEC 公司

 

  【 Brooks 原型定律】計劃好拋棄一個原型,這是遲早的事。

 

  —— Fred Brooks ,北卡羅來納大學

 

  如果開始就打算拋棄一個原型,那恐怕你得拋棄兩個。

 

  —— Craig Zerouni Computer FX 公司(英國倫敦)

 

  原型方法可以將系統開發的工作量減少 40%

 

  —— Larry Bernstein ,貝爾通訊研究院

 

  【 Thompson 望遠鏡學徒定律】先做一個 4 英尺鏡片的(望遠鏡),再做一個 6 英尺鏡片的,這比直接做 6 英尺鏡片的更省時間。

 

  —— Bill McKeeman ,王安公司

 

  拼命幹活無法取代理解。

 

  —— H. H. Williams ,加州奧克蘭

 

  做事應該先做最難的部分。如果最難的部分無法做到,那還在簡單的部分上浪費時間幹嘛?一旦困難的地方搞定了,那你就勝利在望了。

 

  做事應該先做最簡單的部分。你開始所預想的簡單部分,做起來可能是很有難度的。一旦你把簡單的部分都做好了,你就可以全力攻克最難的部分了。

 

  —— Al Schapira ,貝爾實驗室

 

   6.7  其他

 

  【 Sturgeon 定律——在科幻小說和電腦科學中同等適用】毫無疑問, 90% 的軟體都沒什麼用。這是因為對任何東西而言,其中的 90% 都是沒什麼用的。

 

  —— Mary Shaw ,卡內斯—梅隆大學

 

  對計算機撒謊是要受到懲罰的。

 

  —— Perry Farrar ,馬里蘭州

 

  如果不要求系統可靠,它可能做任何事情。

 

  —— H. H. Williams ,加州奧克蘭

 

  一個人的常量是另一個人的變數。

 

  —— Susan Gerhart Microelectronics and Computer Technology 公司

 

  一個人的資料就是另一個人的程式。

 

  —— Guy L. Steele, Jr. Tartan 實驗室

 

  【 KISS 法則】用最簡單、最笨的方法做事

 

  ——佚名

 

   6.8  原理

 

  看到這裡,你一定會接受下面這條不錯的箴言:

 

  別輕信那些看似聰明的法則。

 

  —— Joe Condon ,貝爾實驗室

 

   6.9  習題

 

  儘管本章中對每一條箴言只用了寥寥數語,但其中大多數是可以很大程度上進行擴寫的(比如說,可以擴寫為一篇本科生的論文,或是一場酒酣之餘的高談闊論)。下面的問題告訴我們應該如何擴充套件這些箴言。

 

  先讓程式跑起來,再考慮怎麼讓程式跑得快。

 

  —— Bruce Whiteside ,伊利諾伊州伍德里奇

 

  

 

  你們的“作業”就是用類似的方式擴寫其他箴言。

 

   1. 用更精確的語言重新表述箴言。上面的例項可以擴寫為:

 

  在確定程式的正確性之前,請忽略程式的效率。

 

  或是

 

  如果程式不能工作,那執行再快也沒用;畢竟,一個總是給出錯誤結論的空程式是根本不花時間的。

 

   2.      舉一個小而具體的例項支援你的表述。 Kernighan Plauger Elements of Programming Style 7 章中列出了從一個程式原始碼中截出的 10 行糾結而難以理解的程式碼。這段繞人的程式碼節省了一次比較,卻引入了一個小錯誤。通過“浪費”時間進行一次本可以節省的比較,他們把十行晦澀的程式碼變成了兩行一目瞭然的程式碼。從這一現實教訓中,他們總結出下面這個道理:

 

  欲求快,先求對。

 

   3.      尋找這些箴言用於大型程式設計的“實戰故事”。

 

   a.      我很高興這個箴言對於專案實踐有所幫助。比如, 1.2 節描述的幾個例子,對系統所進行的效能監視指向了程式執行的關鍵點,然後我們可以通過簡單調整這些關鍵點來提高系統效能。

 

   b.      忽略這些箴言,可能導致災難性的結果。 20 世紀 60 年代初, Vic Vyssotsky 修改一個 Fortran 編譯器原始碼,想讓一個原本正確的程式更加快速,卻因而引入了一個程式錯誤。兩年過去了,這個程式錯誤一直沒有被發現,因為在 100 000 次編譯中連一次也沒有呼叫這個程式。 Vyssotsky 花在這次不成熟的優化上面的時間比僅僅浪費時間更加糟糕,因為他使一個原本好好的程式出錯了。(不過,這個故事教育了 Vyssotsky 和貝爾實驗室一代又一代程式設計師。)

 

   4.      請評價這些箴言。哪些是“不變的真理”,哪些在某些情況下會產生誤導?有一次我曾經對 Tartan 實驗室的 Bill Wulf 說起“如果程式不能工作,執行得再快也沒有用”這句話,我覺得這個是無可爭議的事實。這時他舉了一個我們都在用的文件格式化程式的例子。儘管這個程式比其前一版本明顯快很多,但在有些時候會慢得難以忍受,比如編譯一本書要花上好幾個小時。 Wulf 用下面這個論據贏得了這場論戰:“正如其他所有大型系統一樣,這一程式有 10 個記錄在案的輕微程式錯誤,而下個月它又將會有 10 個新的小錯誤被我們發現。如果給你機會進行選擇,你是要解決現在已知的 10 個小錯誤,還是讓程式快 10 倍呢?”

 

   6.10  深入閱讀

 

  如果你想要更多這樣言簡意賅的箴言,請看看 Tom Parker Rules of Thumb Houghton Mifflin 1983 )。該書的封面上有如下法則:

 

   798. 一個鴕鳥蛋足夠作為 24 人的早餐加午餐。

 

   886. 潛水艇能以最高效率在水下行動的條件是:它的長寬比在 10 13 之間。

 

  這本書上一共有 896 條類似的法則。

 

   Butler Lampson 發表在 IEEE Software 1 1984 1 月)上的“ Hints for Computer System Design ”中有不少非常有用的“經驗法則”:

 

  把通常情況和最壞情況分開處理。

 

  在分配資源的時候,請努力避免引起災難,而不是妄圖獲得最優。

 

   Lampson 構建了數十套最先進的軟硬體系統,他的這些提示總結了自己的經驗。

 

 

  摘自《程式設計珠璣(續)》

  

說明: 《程式設計珠璣(續)》是《程式設計珠璣II》的編輯校訂版

 

  

 

 

相關文章