計算機科學箴言集 --

6 計算機科學箴言集

程序員常常要轉換時間單位; e.g. 一個程序每秒能處理100條記錄, 那處理100w條需要多久? 用除法算, 就知道要花100000秒, 按每小時3600秒算, 差不多3小時;
而一年有多少秒? 如果我直接告訴你 3.155x10^7秒, 你可能很快就忘了; 事實上, 要記住這個很簡單, 在誤差不超過0.5%的約束下:
         π秒就是一個納世紀    ——Tom Duff 貝爾實驗室    [nano 1×10−9 ]
所以, 如果程序要運行10^7秒, 就要準備等上4個月;

1985Feb的"ACM通訊"向讀者徵集與計算有關的箴言; 讀者來稿中有些是無爭議的, e.g. Duff法則是一種很方便的記憶常數的方法; 而下面這個關於程序測試方法的法則中的數字則不那麼絕對(迴歸測試方法保存老版本的輸入/輸出數據, 以確保新版本程序能得出同樣的輸出);
        迴歸測試能將測試區間減半     ——Larry Bernstein 貝爾通信研究院
Bernstein的觀點中所說的數可能是30%也可能是70%, 然而可以確定的是, 這些測試節約了開發時間; 

不怎麼定量的忠告也存在問題; 相信大家都會同意;
        小別勝新婚;    ——佚名 
但也說 
        眼不見, 心不煩;    ——佚名
最後這句話對每個人都適用, 對這些話本身則不適用; 本章中的很多箴言也存在類似的矛盾; 儘管每句話都有真理存焉, 還是應該有所保留地看待它們;
  關於箴言的出處, 不得不聲明一下; 箴言下的名字基本上都是最早把這句話發給我的人; 在一些地方我列出了更早的參考文獻以及作者的單位; 我知道這樣做對不起那些最早說出這句話的人, 只能用下面這句話表達遺憾:
  剽竊即是最誠懇的恭維     ——佚名

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 Wei, 美國陸軍中校

  修正程序錯誤的第一步是要先重現這個錯誤        ——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英寸的紙<譯註1 216mm x 279mm的Letter型紙>上寫明白, 那麼這個東西別人就沒辦法理解    ——Mark Ardis, 王安公司

  紙上的工作沒結束, 整個工作也就還沒結束        ——佚名

6.6  軟件管理
  系統的結構反映出構建該系統的組織的結構        ——Richard E. Fairley, 王安公司

  別堅持做那些沒用的事        ——佚名

  【90—90法則】前90%的代碼佔用了90%的預定開發時間, 餘下的10%代碼又花費了90%的預定開發時間<譯註2 由於程序員難以事先預見到困難, 所以開發時間經常延長几乎一倍(90%+90%=180%), 很多軟件企業據此制定開發計劃, 把合理估計出來的開發時間再加倍>        ——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  習題
儘管每一條箴言只用了寥寥數語, 但其中大多數是可以很大程度上進行擴寫的(e.g. 可以擴寫爲一篇本科生論文); 下面的問題告訴我們應該如何擴展這些箴言;
  先讓程序跑起來, 再考慮怎麼讓程序跑得快        ——Bruce Whiteside, 伊利諾伊州伍德里奇
用類似的方式擴寫其他箴言;
1.) 用更精確的語言重新表述箴言; 上面的實例可以擴寫爲:
  在確定程序的正確性之前, 請忽略程序的效率;
或是
  如果程序不能工作, 那運行再快也沒用; 畢竟, 一個總是給出錯誤結論的空程序是根本不花時間的;
2) 舉一個小而具體的實例支持你的表述; Kernighan和Plauger在"Elements of Programming Style"第7章中列出了從一個程序源碼中截出的10行糾結而難以理解的代碼; 這段繞人的代碼節省了一次比較, 卻引入了一個小錯誤; 通過"浪費"時間進行一次本可以節省的比較, 他們把十行晦澀的代碼變成了兩行一目瞭然的代碼; 從這一現實教訓中, 他們總結出這個道理:
  欲求快, 先求對;
3) 尋找這些箴言用於大型程序設計的"實戰故事"
 a) 很高興這個箴言對於項目實踐有所幫助; e.g. 1.2描述的幾個例子, 對系統所進行的性能監視指向了程序執行的關鍵點, 然後可以通過簡單調整這些關鍵點來提高系統性能;
 b)  忽略這些箴言, 可能導致災難性的結果; 20世紀60年代, Vic Vyssotsky修改一個Fortran編譯器源碼, 想讓一個原本正確的程序更加快速, 卻因而引入了一個程序錯誤; 兩年過去, 這個程序錯誤一直沒有被發現, 因爲在100 000次編譯中連一次也沒有調用這個程序; Vyssotsky花在這次不成熟的優化上面的時間比僅僅浪費時間更加糟糕, 因爲他使一個原本好好的程序出錯了;(不過, 故事教育了Vyssotsky和貝爾實驗室一代代程序員)
4) 請評價這些箴言; 哪些是"不變的真理", 
哪些在某些情況下會產生誤導? 有一次我曾對Tartan實驗室的Bill Wulf說"如果程序不能工作, 運行得再快也沒有用"; 他舉了一個我們都在用的文檔格式化程序的例子; 儘管這個程序比其前一版本明顯快很多, 但在有些時候會慢得難以忍受, 比如編譯一本書要花上好幾個小時; 
Wulf用下面這個論據贏得了這場論戰" 正如其他所有大型系統一樣, 這一程序有10個記錄在案的輕微程序錯誤, 而下個月它又將會有10個新的小錯誤被我們發現; 如果給你機會進行選擇, 是要解決現在已知的10個小錯誤, 還是讓程序快10倍呢?"
-- <編程珠璣續>
---YCR---



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章