本文出自:
http://blog.youxu.info/2008/11/23/software-tool/ 和
http://blog.youxu.info/2008/11/23/the-elements-of-programming-styl/
比代碼大全好的兩本書(shū)A
上次我說(shuō)到“比代碼大全好的書(shū)”, 第一本指的是 <Software Tools>. 為了說(shuō)這本書(shū)的優(yōu)點(diǎn), 得先說(shuō)這本書(shū)的缺點(diǎn).
這么書(shū)基本上絕版了. 而且也沒(méi)有中文版. Amazon 連舊書(shū)攤總共就不到50本. 可見(jiàn)這本書(shū)目前不是一本讓廣大程序員喜聞樂(lè)見(jiàn)的書(shū).其次, 這本書(shū)用的說(shuō)明問(wèn)題的語(yǔ)言叫做 Ratfor, 基本上是 FORTRAN 和 C 雜交的產(chǎn)物.估計(jì)全世界用這個(gè)的程序員和現(xiàn)存的這本書(shū)的數(shù)量差不多多. 但是你要是認(rèn)為這是一本古董書(shū), 爛書(shū)或者非暢銷(xiāo)書(shū), 那你就錯(cuò)了. 因?yàn)槭且槐揪幊虝?shū)籍, 生命周期本來(lái)就短, 因此單以現(xiàn)在的銷(xiāo)量判斷好壞, 并不科學(xué). 江湖失傳已久的如來(lái)神掌送給周星星的時(shí)候,周星星也不以為然. 但最后威力無(wú)窮. 希望這篇書(shū)評(píng), 能夠讓讀者信服這是一本如來(lái)神掌的秘籍.
這本書(shū)的作者是 Brian W. Kernighan 和 P. J. Plauger . 關(guān)于這兩個(gè)作者出書(shū)質(zhì)量好的廢話(huà)我就不多說(shuō)了(不知道沒(méi)聽(tīng)說(shuō)第一個(gè)的回家用C寫(xiě)一個(gè)Hello, world 并面壁). 先說(shuō)這本書(shū)講的什么吧.
這本書(shū)主要兩條線(xiàn), 一條是怎樣通過(guò)一個(gè)叫做 Ratfar 的語(yǔ)言, 一步一步構(gòu)建 UNIX 系統(tǒng)下的 cat, wc, tr,sort, tar 等等這些工具; 另一條是怎樣和低級(jí)繁瑣且不順手的 FORTRAN 語(yǔ)言做斗爭(zhēng), 克服語(yǔ)言的障礙,寫(xiě)出功能和可讀性俱佳的結(jié)構(gòu)化程序. 第一條著重強(qiáng)調(diào)的是一個(gè)系統(tǒng)的功能分解(對(duì)UNIX哲學(xué)清楚的讀者看一下目錄就一目了然),第二條實(shí)際上是敘述了一個(gè)一脈相承到”代碼大全”的哲學(xué): 如何構(gòu)建”你的”編程語(yǔ)言, 而不是簡(jiǎn)單的使用”別人的”編程語(yǔ)言. 這一條,道出了整個(gè)編程的真諦: 編程就是構(gòu)建一個(gè)一個(gè)”自己的”小積木, 然后用自己的小積木搭建大系統(tǒng).
為了說(shuō)明小積木的道理, 我們從編程語(yǔ)言說(shuō)起. 我以前的文章也提到過(guò), C 并沒(méi)有一個(gè)可以傳遞一行消息出來(lái)的 Assert 機(jī)制.因此有經(jīng)驗(yàn)的程序員會(huì)自己構(gòu)造一個(gè) Assert. 同樣的道理, Java 雖然很高級(jí), 卻沒(méi)有一個(gè)很好的單元測(cè)試框架, 所以全世界 java程序員都在用 JUnit. 這些實(shí)踐, 表明了一個(gè)現(xiàn)成編程語(yǔ)言總有一些特性不完美之處, 工具和使用者之間還有著不小的距離,因此顯得”不順手”. 如果這個(gè)例子不夠說(shuō)明問(wèn)題的話(huà), 不妨問(wèn)自己: 為什么人不能像寫(xiě)偽代碼一樣寫(xiě)程序呢? 因?yàn)槲覀兪褂昧司幊陶Z(yǔ)言,而編程語(yǔ)言有很多骯臟的細(xì)節(jié)要我們?nèi)ヌ幚? 比如下標(biāo)從0開(kāi)始, 浮點(diǎn)數(shù)不好作為數(shù)組下標(biāo)等等. 語(yǔ)言的細(xì)節(jié)需要處理這個(gè)問(wèn)題, 從 Fortran到 Python, 只有程度的改變, 并沒(méi)有本質(zhì)的改變. 況且, 通用編程語(yǔ)言之所以通用并且簡(jiǎn)單, 就是因?yàn)橹С值墓δ鼙容^基本, 可擴(kuò)展性強(qiáng).因此, 基本功能都有, 高級(jí)功能缺少成了通用編程語(yǔ)言的最大特點(diǎn). 不管編程語(yǔ)言多么”高級(jí)”, 總是沒(méi)有自己的思維高級(jí). 因此,編程的第一步就是把語(yǔ)言改造成自己的語(yǔ)言. 即使強(qiáng)大到直接能 import antigravity 的 Python, 也有需要改造的地方(最好的例子就是 Python 3000 的推出).
小積木有了, 就要構(gòu)建大系統(tǒng)了. 在這一點(diǎn)上, Software Tools 可以說(shuō)是非常好的一本源代碼導(dǎo)讀. 自從 Lion 分析 Unix 源代碼以來(lái), 源碼剖析成了程序員修煉的一個(gè)捷徑. 可是現(xiàn)在程序的源代碼樹(shù)都很繁雜, 能真的拿出來(lái)分析的很少很少了. Bell 實(shí)驗(yàn)室的兩位作者從實(shí)作UNIX 系統(tǒng)下的工具出發(fā), 挑選出經(jīng)過(guò)實(shí)踐檢驗(yàn)的優(yōu)秀代碼來(lái)講解. 這樣來(lái)自一線(xiàn)的題材是極其寶貴的, 就算在最新的 BeautifulCode 中, 大多代碼也只是教科書(shū)代碼而已. 至于代碼大全, 完全就是玩具代碼. 而 Software Tools 有幾千行代碼的大程序,也有幾行代碼的小程序; 有算法程序, 也有文件IO程序, 基本覆蓋日常所有用例, 對(duì)于內(nèi)功修煉大有裨益.
除了道出”改造你的語(yǔ)言”的真諦之外, 這本書(shū)其他論點(diǎn)也可謂字字珠璣. 比如講 goto帶給程序員的自由恰好是你不想要的自由, 因?yàn)檫@個(gè)自由會(huì)帶來(lái)很多錯(cuò)誤.(很多語(yǔ)言都有這種不想要的自由, 比如 C++, 到處都是). 比如說(shuō)講結(jié)構(gòu)化編程不會(huì)自動(dòng)帶來(lái)清晰的程序,因?yàn)闄C(jī)械的規(guī)則永遠(yuǎn)不能代替清晰的思考. 這個(gè)道理在面向?qū)ο?設(shè)計(jì)模式領(lǐng)域也一樣. 比如本書(shū)還論證了為啥要詳細(xì)設(shè)計(jì),因?yàn)樵O(shè)計(jì)和編碼環(huán)節(jié)對(duì)于程序員講是愉快的事情, 值得更多投入. 而 debug 和 測(cè)試環(huán)節(jié)是比較痛苦的事情, 所以要少投入.還比如人比機(jī)器時(shí)間貴, 所以程序員要越懶, 越快完成編程越好. 除非程序太慢, 否則從總成本看, 機(jī)器多用點(diǎn)時(shí)間沒(méi)事, 人用的時(shí)間要越少越好,等等等等. 類(lèi)似于這樣的深刻揭示編程的哲學(xué)理念的句子俯拾皆是, 比起相同內(nèi)容但是篇幅冗長(zhǎng)的代碼大全, 這本書(shū)適合隨身攜帶, 隨時(shí)閱讀,隨時(shí)提高.
老規(guī)矩, 結(jié)尾順手說(shuō)個(gè)八卦吧. 話(huà)說(shuō)為了把 Ratfor 這個(gè)假想的語(yǔ)言翻譯成當(dāng)時(shí)最流行的兩種語(yǔ)言, FORTRAN 和 PL/I,bwk 爺爺寫(xiě)了一個(gè)宏替換的工具, 能夠把 Ratfor 替換成骯臟的 FORTRAN, 而他們寫(xiě)干凈的 Ratfor. DennisRitchie 爺爺看到鳥(niǎo), 很贊, 于是推廣了一下這個(gè)宏替換工具, 起個(gè)詭異的名字叫做 m3 (macro for ap3). 然后 bwk爺爺又看到了 dr 爺爺?shù)墓ぷ? 回過(guò)來(lái)又和 dr 爺爺合作, 寫(xiě)出了金光閃閃的 m4. 如果你常常編譯開(kāi)源軟件, 肯定會(huì)注意到一個(gè)叫做configure 的生成 makefile 的程序. 這個(gè) configure 的讀入, 一般情況下是可配置的, 叫做 config.ac,就是 m4 語(yǔ)言寫(xiě)的. 雖然因?yàn)榘鏅?quán)問(wèn)題, 現(xiàn)在 GNU m4 和兩位爺爺沒(méi)啥關(guān)系了, 但是基本的語(yǔ)法和用法都是一樣的. 各位知道K&R 的讀者千萬(wàn)不要錯(cuò)過(guò)這個(gè)好用的工具(也是編程語(yǔ)言).
這個(gè)工具其實(shí)我也只懂皮毛, 也不常用, 只是用來(lái)自動(dòng)編號(hào)一些行, 做一些稍微復(fù)雜一點(diǎn)的不能用正則的文本替換.不過(guò)我似乎在某個(gè)地方聽(tīng)一個(gè)高手說(shuō), Linux 命令行下文本處理三劍客乃是 sed/awk/m4, sed 和 awk 的強(qiáng)大早就見(jiàn)識(shí)了,相必m4與他們各有千秋. 故而略介紹一下.
比代碼大全好的兩本書(shū)B(niǎo)
各位讀者老大中有不少都是大學(xué)生, 相信不少都參加過(guò)形形色色的英語(yǔ)寫(xiě)作培訓(xùn)班. 如果當(dāng)年您參加培訓(xùn)班的時(shí)候, 老師沒(méi)有介紹一本叫做 <The Elements of Style>(TEoS) 的書(shū), 建議您現(xiàn)在立即沖過(guò)去找他們退錢(qián). 為啥呢, 因?yàn)檫@本書(shū)是講解英語(yǔ)寫(xiě)作繞不開(kāi)的經(jīng)典圣經(jīng)(即使這本書(shū)已經(jīng)被說(shuō)爛了,批評(píng)也不少, 但還是經(jīng)典). 假如培訓(xùn)機(jī)構(gòu)或者老師上課沒(méi)推薦到這本書(shū), 這個(gè)培訓(xùn)機(jī)構(gòu)要不是太牛逼了, 要不是水貨. 而大家都知道,水貨和牛逼的比例總是 1:epsilon.
作為Amazon 上 297 個(gè)5星的書(shū),書(shū)評(píng)我就不狗尾續(xù)貂了. Knuth 爺爺也是很喜歡這本書(shū)滴, 因此在 Stanford 開(kāi)課的時(shí)候讓學(xué)生人手一本(我們系今年新生也強(qiáng)制人手一本). 這本書(shū)不光勾勒了英語(yǔ)的基本寫(xiě)作要素, 也刻畫(huà)了一個(gè)時(shí)代: 從此, 任何需要”藝術(shù)和技藝”的領(lǐng)域,都會(huì)時(shí)不時(shí)跳出一些牛人, 模仿這本書(shū)的題材和哲學(xué), 用簡(jiǎn)潔的文筆勾勒出這個(gè)領(lǐng)域的基本要素. 以我熟悉的計(jì)算機(jī)領(lǐng)域?yàn)槔? 就有 “TheElements of Programming Style”, “The Element of Programming Style withPerl”. “C Elements of Style”, “The Elements of Java Style”, “TheElements of UML Style” 等等書(shū), 都是希望繼承 TEoS 的衣缽, 勾勒出編程的一些風(fēng)格要素.今天我要說(shuō)的比<代碼大全>好的書(shū)的第二本, 就是叫做 <The Elements of ProgrammingStyle>的..
這本書(shū)作者和上一本 Software Tools 一樣, 屬于一個(gè)家族哲學(xué)下的兩本不同角度的書(shū). 關(guān)于它的書(shū)評(píng)也很多, 我就不一一廢話(huà)了. 只說(shuō)幾個(gè)體會(huì)較深的.
第一是寫(xiě)程序和寫(xiě)作一樣, 要寫(xiě)的清楚. 這本書(shū)翻開(kāi)第一條就是 Write clearly - don’t be too clever.看上去說(shuō)的和沒(méi)說(shuō)一樣, 其實(shí)實(shí)踐起來(lái)乃是金科玉律. 我曾自己寫(xiě)過(guò)三層嵌套的 “? :” 表達(dá)式, 寫(xiě)的時(shí)候自己被自己的聰明都感動(dòng)了,回來(lái)改的時(shí)候自己被自己當(dāng)時(shí)的聰明給打擊了: 死活看不懂當(dāng)時(shí)啥意思, 只好寫(xiě)一個(gè) printf 在后面測(cè)輸出.假如當(dāng)時(shí)多花幾分鐘寫(xiě)的清楚一點(diǎn)明白一點(diǎn), 就犯不著回頭修改的時(shí)候花半小時(shí)破譯了. 現(xiàn)實(shí)中的情況沒(méi)這么極端, 但是也比比皆是.相信任何正常的程序員, 每天都要為了理解以前寫(xiě)的不大清楚了程序浪費(fèi)不少時(shí)間 (反正我是記不住一年前寫(xiě)的代碼的每個(gè)小細(xì)節(jié)). 因此,寫(xiě)的時(shí)候?qū)懙那宄仁裁炊贾匾?
在寫(xiě)得清楚上, Knuth 爺爺是榜樣. 他提出的 Literate Programming 的思想雖然太學(xué)術(shù), 使得實(shí)踐的人不多, 但是的確使得程序更加好讀. Knuth 爺爺把他的用C語(yǔ)言作為基本語(yǔ)言的 Literate Programming 系統(tǒng)叫做 CWEB. 大名鼎鼎的 TeX 就是 CWEB 寫(xiě)成.如果對(duì) Knuth 爺爺比較粉的粉絲們恰好要做圖算法, Stanford Graphbase 是一本非常好的書(shū), 里面貼得全是程序,但是因?yàn)?Knuth 爺爺用 CWEB 寫(xiě)成, 文檔和程序渾然一體, 讀起來(lái)絲毫不覺(jué)得思維在程序和自然語(yǔ)言間做切換. Java 下有名的XDoclet 和 Javadoc, 事實(shí)上也是 Literate Programming 的一種體現(xiàn). 據(jù) Knuth 爺爺講他寫(xiě) CWEB 程序能笑出來(lái), 這種境界不是一般人能有的. 而且 Knuth 爺爺在提出 Literate Programming 的時(shí)候, 就野心勃勃的說(shuō): 寫(xiě)文章也是寫(xiě), 寫(xiě)程序也是寫(xiě), 我們 Literature Programming 的口號(hào)就是: 沒(méi)有蛀牙程序員也能拿普利策. (”I’m hoping someday that the Pulitzer Prize committee willagree.” Prizes would be handed out for “best-written program”.)
又八卦走題了. 言歸正傳, 我的第二個(gè)深刻的體會(huì)是”讓計(jì)算機(jī)干臟活”. 什么叫臟活呢? 讓你不爽的活叫臟活. 比如 Debug, 比如無(wú)窮多的復(fù)制粘帖, 比如替換一個(gè)大小寫(xiě), 數(shù)數(shù)幾個(gè)單詞, 做做單元測(cè)試等等. 用眼睛瞄肯定會(huì)死人. 我以前在 “高效能編程的七個(gè)好習(xí)慣” 這篇文章中也說(shuō)了, 就不多廢話(huà)了.
當(dāng)然, 現(xiàn)實(shí)的問(wèn)題是, 理論是理論, 實(shí)踐是實(shí)踐. 事實(shí)上, 我們要不然就是不用或者想不起來(lái)用工具(理由是不習(xí)慣),要不然就是成為工具的奴隸.. 為什么明明別人告訴我有高效率工具和習(xí)慣存在的情況下, 我們還不去用不去改,或者如何不成為工具的奴隸這兩個(gè)話(huà)題都太大了, 我也寫(xiě)不好, 就不廢話(huà)了. 然而, 不管最后實(shí)踐用還是不用,讀一些被別人實(shí)踐檢驗(yàn)過(guò)的經(jīng)驗(yàn)之談還是很有用的. 這也是我推薦這本書(shū)的原因. 不知道大家有沒(méi)有發(fā)現(xiàn),潛意識(shí)中如果有個(gè)正確的小聲音不時(shí)在原則上提醒自己, 實(shí)踐的時(shí)候潛移默化的就會(huì)越做越好.
最后依然附送兩個(gè)八卦. 第一個(gè)是關(guān)于 TEoS 這本書(shū)的. 這本書(shū)列了很多的原則和規(guī)則, 都是具體的對(duì)某個(gè)詞某個(gè)句型的建議,因此英語(yǔ)寫(xiě)作的時(shí)候可以直接應(yīng)用這些規(guī)則. 不過(guò)對(duì)著書(shū)查規(guī)則顯然屬于臟活的范圍, 所以呢, 我們的”讓計(jì)算機(jī)做臟活”的哲學(xué)就發(fā)揮作用了: 在Linux 下有一個(gè)程序叫diction, 用他可以檢查英語(yǔ)寫(xiě)作的文章符不符合 TEoS 的標(biāo)準(zhǔn), 我以前也專(zhuān)門(mén)介紹過(guò).diction 會(huì)挑出那些不符合 TEoS 的句子, 告訴你讓你修改. Knuth 爺爺也說(shuō), 雖然這個(gè)程序很笨,但是至少可以強(qiáng)迫你重新審視你的文章, 挑出弱智的錯(cuò)誤. 其實(shí) GNU/Linux 下幫助英文寫(xiě)作的工具很多, 雖然不完美, 也稱(chēng)得上完整了. 我以前的文章可供大家參考 .和 diction 一起的另一個(gè)工具叫做 style, 可以做像長(zhǎng)句分析, 被動(dòng)語(yǔ)態(tài)分析, 平均單詞和詞匯量估計(jì)等統(tǒng)計(jì),以及語(yǔ)言學(xué)水平上的英語(yǔ)水平估計(jì)(等價(jià)于美國(guó)幾年級(jí)學(xué)生水平的估計(jì)). 這些估計(jì)都是語(yǔ)言學(xué)家研究數(shù)年的標(biāo)準(zhǔn)指標(biāo). 大家都知道, GRE作文是計(jì)算機(jī)批閱的, 雖然我們不知道算法, 但是可以想象, ETS 那么笨, 肯定是請(qǐng)語(yǔ)言學(xué)家?guī)兔υO(shè)計(jì)的程序,所以必然或多或少的用到很多標(biāo)準(zhǔn)的語(yǔ)言學(xué)指標(biāo). 所以呢, 你不用計(jì)算機(jī)程序分析分析自己的文章, 光聽(tīng)培訓(xùn)機(jī)構(gòu)的一些老師忽悠,怎么知道自己文章水平吶? 相比較一些培訓(xùn)機(jī)構(gòu)的老師, 指不定 style 這個(gè)程序更像 ETS 的評(píng)價(jià)標(biāo)準(zhǔn).
第二個(gè)八卦是關(guān)于寫(xiě)清晰的程序的. 或許大家都聽(tīng)說(shuō)過(guò)史上最牛逼的注釋的故事. 雖然各人有個(gè)人認(rèn)為的最牛注釋, 我個(gè)人喜歡的叫做 /*You are not supposed to understand this. */ (我不指望你懂這是啥意思).這句話(huà)其實(shí)本來(lái)不該這么出名的, 恰好是因?yàn)槌霈F(xiàn)在開(kāi)源的第六版UNIX中, 恰好寫(xiě)的人是 Dennis M. Ritchie,恰好澳大利亞出了一個(gè)叫 Lion 的人把 UNIX 源代碼扒出來(lái)搞了個(gè)源碼解析, 又恰好當(dāng)年這本源碼解析幾乎每個(gè)黑客都人手一本. 所以,這個(gè)極其挑戰(zhàn)其他黑客智力的注釋就變得流行起來(lái)鳥(niǎo). DMR 同學(xué)對(duì)此有技術(shù)上的詳細(xì)解釋, 不再?gòu)U話(huà). 就是友情含淚勸告讀者: 您要是在你的程序里面搞這么一句然后又被你同事和老板看到鳥(niǎo), 你就完蛋鳥(niǎo). 世上只有一個(gè)牛逼的 DMR 敢這么寫(xiě).
PS: 想要看看The Elements of Style 書(shū)的內(nèi)容的老大們, 可以猛點(diǎn)這個(gè)鏈接:
想要看 The Elements of Programming Style 說(shuō)了哪些的老大們, 可以猛點(diǎn)這個(gè)鏈接
-EOF-
聯(lián)系客服