編程藝術unix
1. 如何從零開始學編程
在你學習編程之前思考一下你的目標,當你有最終目標時道路會更加的清晰。那麼,你想要寫什麼?網站?游戲?iOS或者Android應用?或是你是想自動化完成一些乏味的任務讓你有更多的時間看窗外的風景?也許你只是想更具有就業競爭力找個好工作。所有的這些都是有價值的目標,這些目標都是你編程學習推動力的一部分,沒有推動力的人,是無法在略顯枯燥的漫長學習之旅中走遠的。
不要浮躁
Badprogrammingiseasy.EvenDummiescanlearnitin21days.,meswithit.
不管是在線下還是線上的書店,滿目都是《21天學通java》這種速成書目,它們都承諾在很短一段時間內就讓你能夠學會相關技術。MatthiasFelleisen在他的著作HowtoDesignPrograms,SecondEdition一書中明確指出了這種「速成」的趨勢並予以了以上的諷刺。
所謂的「捷徑」或者說「銀彈」是不存在的,智者說過,精通某個東西需要10年或10000個小時,也就是漢語中的「十年磨一劍」,所以不用著急,功不唐捐。
培養興趣
ionbythepublic,butbecauseitisfuntoprogram.
_LinusTorvalds
沉醉於編程,編程更是為了興趣。興趣是推動力的不竭源泉,保持這種充滿興趣的感覺,以便於你能將其投入到你的10年/10000小時的編程時間中。編程很有趣,那是探索的喜悅。那是創造的喜悅。看到自己親手完成的作品顯示在屏幕上很有趣。有人為你的代碼而驚嘆很有趣。有人在公共場合稱贊你的產品、鄰居使用你的產品、以及在媒體上討論你的產品很有趣。編程應該十分有趣,若並非如此,就找出導致編程無趣的問題,然後解決之。
在這里對於初學者有兩個大坑:
如果初學者們只與預先構建好的「發動機和組件」接觸(沒有理解和思考它們構造的原理),這會嚴重限制他們在將來構建這些東西的能力,並且在診斷解決問題時無從下手。
第二個坑沒有第一個那麼明顯:幼稚的「整體論」方法有些時候會顯得很有效,這有一定的隱蔽性與誤導性,但是一兩年過後(也許沒那麼長),當你在學習路上走遠時,再想回過頭來「補足基礎」會有巨大的心理障礙,你得拋棄之前自己狹隘的觀念,耐心地緩步前進,這比你初學時學習基礎知識困難得多。
但臘敏茄也不能矯枉過正,陷入還原論的大坑,初學時便一心試圖做宏大的理論,這樣不僅有一切流於理論的危險,枯燥和乏味還會讓你失去推動力。這種情況經常發生在計算機科班生身上。
為了更好理解,可以將學習編程類比為學習廚藝:你為了燒得一手好菜買了一些關於菜譜的書,如果你只是想為家人做菜,這會是一個不錯的主意,你重復菜譜上的步驟也能做出不賴的菜餚,但是如果你有更大的野心,真的想在朋友面前露一手,做一些獨一無二的美味佳餚,甚至成為「大廚」,你必須理解這些菜譜背後大師的想法,理解其中的理論,而不僅僅是一味地實踐。但拿猛是如果你每天唯一的工作就是閱讀那些厚重的理論書籍,因為缺乏實踐,你只會成為一個糟糕的廚子,甚至永遠成為不了廚子,因為看了幾天書後你就因為枯燥放棄了廚藝的學習。
總之,編程是連接理論與實踐的紐帶,是計算機科學與計算機應用技術相交融的領域。正確的編程學習方法應該是:通過自頂而下的探索與項目實踐,獲得編程直覺與推動力;從自底向上的打基礎過程中,獲得最重要的通用方法並鞏固編程思想的理解。
作為初學者,應以後者為主,前者為輪察輔。
啟蒙
「學編程應該學哪門語言?」這經常是初學者問的第一個問題,但這是一個錯誤的問題,你最先考慮的問題應該是「哪些東西構成了編程學習的基礎」?
編程知識的金字塔底部有三個關鍵的部分:
演算法思想:例如怎樣找出一組數中最大的那個數?首先你得有一個maxSoFar變數,之後對於每個數
語法:我怎樣用某種編程語言表達這些演算法,讓計算機能夠理解。
系統基礎:為什麼while(1)時線程永遠無法結束?為什麼int*foo(){intx=0;return&x;}是不可行的?
啟蒙階段的初學者若選擇c語言作為第一門語言會很困難並且枯燥,這是因為他們被迫要同時學習這三個部分,在能做出東西前要花費很多時間。
因此,為了盡量最小化「語法」與「系統基礎」這兩部分,建議使用python作為學習的第一門語言,雖然Python對初學者很友好,但這並不意味著它只是一個「玩具」,在大型項目中你也能見到它強大而靈活的身影。熟悉Python後,學習C語言是便是一個不錯的選擇了:學習C語言會幫助你以靠近底層的視角思考問題,並且在後期幫助你理解操作系統層級的一些原理,如果你只想成為一個普通(平庸)的開發者你可以不學習它。
下面給出了一個可供參考的啟蒙階段導引,完成後你會在頭腦中構建起一個整體框架,幫助你進行自頂向下的探索。
完成Codecademy的Python部分。這只是熱身部分,盡快完成它,因為你永遠只是在瀏覽器里,你不會學到如何搭建開發環境。在Codecademy這類的編程學習網站學到的那點兒東西,哪怕你只想做一個小的不能再小的項目,你都不知道該從哪兒開始。
完成MIT6.00.1x(中文化)(如果你英語不過關,完成麻省理工學院公開課:計算機科學及編程導論。MOOC是學習編程的一個有效途徑。雖然該課程的教學語言為Python,但作為一門優秀的導論課,它強調學習計算機科學領域里的重要概念和範式,而不僅僅是教你特定的語言。如果你不是科班生,這能讓你在自學時開闊眼界;課程內容:計算概念,python編程語言,一些簡單的數據結構與演算法,測試與調試。支線任務:
完成Python核心編程
完成HarvardCS50(如果你英語不過關:完成哈佛大學公開課:計算機科學cs50。同樣是導論課,但這門課與MIT的導論課互補。教學語言涉及C,php,JavaScript+SQL,HTML+CSS,內容的廣度與深度十分合理,還能夠了解到最新的一些科技成果,可以很好激發學習計算機的興趣。支線任務:
閱讀《編碼的奧秘》
完成《C語言編程》
[可選]如果你的目標是成為一名Hacker:閱讀Hacker'sDelight
PS:如果教育對象還是一個孩子,以下的資源會很有幫助:
5-8歲:TurtleAcademy
8-12歲:PythonforKids
12歲以上:MITScratch或KhanAcademy
入門
結束啟蒙階段後,初學者積累了一定的代碼量,對編程也有了一定的了解。這時你可能想去學一門具體的技術,諸如Web開發,Android開發,iOS開發什麼的,你可以去嘗試做一些盡可能簡單的東西,給自己一些正反饋,補充自己的推動力。但記住別深入,這些技術有無數的細節,將來會有時間去學習;同樣的,這時候也別過於深入特定的框架和語言,現在是學習計算機科學通用基礎知識的時候,不要試圖去抄近路直接學你現在想學的東西,這是註定會失敗的。
那麼入門階段具體該做些什麼呢?這時候你需要做的是反思自己曾經寫過的程序,去思考程序為什麼(Why)要這樣設計?,思考怎樣(How)寫出更好的程序?試圖去探尋理解編程的本質:利用計算機解決問題。
設想:
X=用於思考解決方案的時間,即「解決問題」部分
Y=用於實現代碼的時間,即「利用計算機」部分」
編程能力=F(X,Y)(X>Y)
要想提高編程能力,就得優化X,Y與函數F(X,Y),很少有書的內容能同時著重集中在這三點上,但有一本書做到了——(SICP)《計算機程序的構造和解釋》,它為你指明了這三個變數的方向。在閱讀SICP之前,你也許能通過調用幾個函數解決一個簡單問題。但閱讀完SICP之後,你會學會如何將問題抽象並且分解,從而處理更復雜更龐大的問題,這是編程能力巨大的飛躍,這會在本質上改變你思考問題以及用代碼解決問題的方式。此外,SICP的教學語言為Scheme,可以讓你初步了解函數式編程。更重要的是,他的語法十分簡單,你可以很快學會它,從而把更多的時間用於學習書中的編程思想以及復雜問題的解決之道上。
PeterNorvig曾經寫過一篇非常精彩的SICP書評,其中有這樣一段:
Touseananalogy,ifSICPwereaboutautomobiles,,howtheyarebuilt,andhowonemightdesignfuel-efficient,safe,.highway,justlikeeveryoneelse.
如果你是文中的前者,閱讀SICP將成為你銜接啟蒙與入門階段的關鍵點
雖然SICP是一本「入門書」,但對於初學者還是有一定的難度,以下是一些十分有用的輔助資源:
):由上文提到的Google研究主管PeterNorvig主講,教學語言為Python,內容有一定難度。
HowtoDesignPrograms,SecondEdition:HtDP的起點比SICP低,書中的內容循循善誘,對初學者很友好,如果覺得完成SICP過於困難,可以考慮先讀一讀HtDP。
UCBerkeleySICP授課視頻以及SICP的兩位作者給Hewlett-Packard公司員工培訓時的錄像(中文化項目)
ComposingPrograms:一個繼承了SICP思想但使用Python作為教學語言的編程導論(其中包含了一些小項目)
SICP解題集:對於書後的習題,作為初學者應盡力並量力完成。
完成了這部分學習後,你會逐步建立起一個自己的程序設計模型,你的腦子里不再是一團亂麻,你會意識到記住庫和語法並不會教你如何解決編程問題,接下來要學些什麼,在你心裡也會明朗了很多。這時候才是真正開始進行項目實踐,補充推動力的好時機。
關於項目實踐:對於入門階段的初學者,參與開源項目還為時過早,這時候應該開始一些簡單的項目,諸如搭建一個網站並維護它,或是編寫一個小游戲再不斷進行擴展,如果你自己的想法不明確,MegaProjectList中選取項目。總之,務必在這時拿下你項目實踐的第一滴血。
與此同時,別忘了繼續打好根基。為了將來的厚積薄發,在下面這幾個方面你還要繼續做足功課(注意:下面的內容沒有絕對意義上的先後順序):
計算機系統基礎
有了之前程序設計的基礎後,想更加深入地把握計算機科學的脈絡,不妨看看這本書:《深入理解計算機系統》ComputerSystemsAProgrammer'sPerspective。這里點名批評這本書的中譯名,其實根本談不上什麼深入啦,這本書只是CMU的「計算機系統導論」的教材而已。CMU的計算機科學專業相對較偏軟體,該書就是從一個程序員的視角觀察計算機系統,以「程序在計算機中如何執行」為主線,全面闡述計算機系統內部實現的諸多細節。
如果你看書覺得有些枯燥的話,可以跟一門Coursera上的MOOC:TheHardware/SoftwareInterface,這門課的內容是CSAPP的一個子集,但是最經典的實驗部分都移植過來了。同時,可以看看TheCProgrammingLanguage,回顧一下C語言的知識。
完成這本書後,你會具備堅實的系統基礎,也具有了學習操作系統,編譯器,計算機網路等內容的先決條件。當學習更高級的系統內容時,翻閱一下此書的相應章節,同時編程實現其中的例子,一定會對書本上的理論具有更加感性的認識,真正做到經手的代碼,從上層設計到底層實現都瞭然於胸,並能在腦中回放數據在網路->內存->緩存->CPU的流向。
此外,也是時候去接觸UNIX哲學了:KISS-KeepitSimple,Stupid.在實踐中,這意味著你要開始熟悉命令行界面,配置文件。並且在開發中逐漸脫離之前使用的IDE,學會使用Vim或Emacs(或者最好兩者都去嘗試)。
閱讀《UNIX編程環境》
閱讀《UNIX編程藝術》
折騰你的UN*X系統
數據結構與演算法基礎
如今,很多人認為編程(特別是做web開發)的主要部分就是使用別人的代碼,能夠用清晰簡明的方式表達自己的想法比掌握硬核的數學與演算法技巧重要的多,數據結構排序函數二分搜索這不都內置了嗎?工作中永遠用不到,學演算法有啥用啊?這種扛著實用主義大旗的「碼農」思想當然不可取。沒有扎實的理論背景,遭遇瓶頸是遲早的事。
數據結構和演算法是配套的,入門階段你應該掌握的主要內容應該是:這個問題用什麼演算法和數據結構能更快解決。這就要求你對常見的數據結構和演算法了熟於心,你不一定要敲代碼,用紙手寫流程是更快的方式。對你不懂的數據結構和演算法,你要去搜它主要拿來幹嘛的,使用場景是什麼。
供你參考的學習資源:
《演算法導論》:有人說別把這本書當入門書,這本書本來就不是入門書嘛,雖說書名是IntroctiontoAlgorithms,這只不過是因為作者不想把這本書與其他書搞重名罷了。當然,也不是沒辦法拿此書入門,讀第一遍的時候跳過習題和證明就行了嘛,如果還覺得心虛先看看這本《數據結構與演算法分析》
CourseraAlgorithms:DesignandAnalysis[Part1]&[Part2]:Stanford開的演算法課,不限定語言,兩個部分跟下來演算法基礎基本就有了;英語沒過關的:麻省理工學院公開課:演算法導論
入門階段還要注意培養使用常規演算法解決小規模問題的能力,結合前文的SICP部分可以讀讀這幾本書:《編程珠璣》,《程序設計實踐》
編程語言基礎
.,.Additionally,,
-ThePragmaticProgrammer
此外還要知道,學習第n門編程語言的難度是第(n-1)門的一半,所以盡量去嘗試不同的編程語言與編程範式,若你跟尋了前文的指引,你已經接觸了:「干凈」的腳本語言Python,傳統的命令式語言C,以及浪漫的函數式語言Scheme/Racket三個好朋友。但僅僅是接觸遠遠不夠,你還需要不斷繼續加深與他們的友誼,並嘗試結交新朋友,美而雅的Ruby小姑娘,Hindley-Milner語言家族的掌中寶Haskell都是不錯的選擇。但有這么一位你躲不開的,必須得認識的大夥伴—C++,你得做好與他深交的准備:
入門:C++Primer
[可選]進階:
高效使用:EffectiveC++
深入了解:《深度探索C++對象模型》;C++Templates
研究反思:TheDesignandEvolutionofC++;對於C++這個NecessaryEvil,看這本書可以讓你選擇是成為守夜人還是守日人。
現實是殘酷的,在軟體工程領域仍舊充斥著一些狂熱者,他們只掌握著一種編程語言,也只想掌握一種語言,他們認為自己掌握的這門語言是最好的,其他異端都是傻X。這種人也不是無葯可救,有一種很簡單的治療方法:讓他們寫一個編譯器。要想真正理解編程語言,你必須親自實現一個。現在是入門階段,不要求你去上一門編譯器課程,但要求你能至少實現一個簡單的解釋器。
供你參考的學習資源:
《程序設計語言-實踐之路》:CMU編程語言原理的教材,程序語言入門書,現在就可以看,會極大擴展你的眼界,拉開你與普通人的差距。
Coursera編程語言MOOC:課堂上你能接觸到極端FP(函數式)的SML,中性偏FP的Racket,以及極端OOP(面向對象)的Ruby,並學會問題的FP分解vsOOP分解、ML的模式匹配、Lisp宏、不變性與可變性、解釋器的實現原理等,讓你在將來學習新語言時更加輕松並寫出更好的程序。
:熱熱身,教你寫一個簡單的瀏覽器——其實就是一個javascript和html的解釋器,完成後的成品還是很有趣的;接下來,試著完成一個之前在SICP部分提到過的項目:用Python寫一個SchemeInterpreter
其他
編程入門階段比較容易忽視的幾點:
學好英語:英語是你獲取高質量學習資源的主要工具,但在入門階段,所看的那些翻譯書信息損耗也沒那麼嚴重,以你自己情況權衡吧。此外英語的重要性更體現在溝通交流上,LinusTorvalds一個芬蘭人,一口流利的英語一直是他招募開發者為linux幹活的的法寶,這是你的榜樣。
學會提問:學習中肯定會遇到問題,首先應該學會搜索引擎的「高級搜索」,當單靠檢索無法解決問題時,去StackOverflow或知乎提問,提問前讀讀這篇文章:Whathaveyoutried?
不要做一匹獨狼:嘗試搭建一個像這樣簡單的個人網站,不要只是一個孤零零的About頁面,去學習Markdown與LaTeX,試著在Blog上記錄自己的想法,並訂閱自己喜歡的編程類博客。推薦幾個供你參考:JoelonSoftware,PeterNorvig,CodingHorror
小結
以上的內容你不應該感到懼怕,編程的入門不是幾個星期就能完成的小項目。期間你還會遇到無數的困難,當你碰壁時試著嘗試「費曼」技巧:將難點分而化之,切成小知識塊,再逐個對付,之後通過向別人清楚地解說來檢驗自己是否真的理解。當然,依舊會有你解決不了的問題,這時候不要強迫自己——很多時候當你之後回過頭來再看這個問題時,一切豁然開朗。
此外不要局限與上文提到的那些材料,還有一些值得在入門階段以及將來的提升階段反復閱讀的書籍。ThePragmaticProgrammer就是這樣一本程序員入門書,終極書。有人稱這本書為代碼小全:從DRY到KISS,從做人到做程序員,這本書教給了你一切,你所需的只是遵循書上的指導。
後記
如果你能設法完成以上的所有任務,恭喜你,你已經真正實現了編程入門。這意味著你在之後更深入的學習中,不會畏懼那些學習新語言的任務,不會畏懼那些「復雜」的API,更不會畏懼學習具體的技術,甚至感覺很容易。當然,為了掌握這些東西你依舊需要大量的練習,腰還是會疼,走路還是會費勁,一口氣也上不了5樓。但我能保證你會在思想上有巨大的轉變,獲得極大的自信,看老師同學和csdn的眼光會變得非常微妙,雖然只是完成了編程入門,但已經成為了程序員精神世界的高富帥。不,我說錯了,即使是高富帥也不會有強力精神力,他也會懷疑自己,覺得自己沒錢就什麼都不是了。但總之,你遵循指南好好看書,那就會體驗「會當凌絕頂」的感覺。
首先要想學編程,選一門合適的計算機語言就十分重要了,怎麼去選擇就顯得尤為重要了,這要根據自己的興趣愛好及每個語言的特性來選擇,比如說PHP適合做web開發,易學習,易上手,非常流行的一門計算機語言了,我個人比較推薦php語言。
java可以做web開發,做安卓app開發也用的是java,在學習程度上上可能比php稍微難上手一點,不過也是沒問題的,如果對java感興趣可以嘗試一下。
python是目前比較火的一門語言了,比較適合做人工智慧領域,另外寫網路爬蟲類的程序,用python也是非常合適的了,看個人興趣來選擇了。
c,c++,c#這些語言就不推薦給了,特別是c#,已經是比較過時的一門語言了,即使學習好了,也不太適合去找工作,c與c++並不是十分適合初學者來學習,因此也是沒必要進行考慮了,還有一些更小眾的語言,更是沒有必要去考慮,因此關於語言的學習就從上面3種語言去選擇一門自己所感興趣的吧!
研發搭建環境
如果選擇好計算機語言,那麼接下來就是研發環境的搭建了,因為只有研發環境搭建好了,才可以進行後續的編程工作,比如說PHP,那麼就從網路上搜一下如何安裝PHP環境,能搜出一些簡單的教程,初學者按照教程一步一步來,頂多半天時間就可以把研發環境裝好了,如果是java,就需要先安裝jdk,進行環境變數的配置等,網上也有相關的教程,也是十分容易的,相信大家只要按照教程來做,都可以很輕易的把研發環境搭建起來的
選好視頻和書籍,輔助學習。既然是零基礎學習,就需要進行系統的學習,而不是到處網路零基礎的知識點進行學習。
代碼練習
跟隨教程一個一個章節的進行學習,需要注意的一點就是不能只是去看,那樣不行,要對每一個章節的知識點要親自用代碼敲一遍,運行一下試試效果才行,這樣才能提高自己的動手能力,才開始會覺得有一點生疏,慢慢的就會熟練起來,逐漸會增加編程的興趣。這個過程就是需要反復的進行練習,大量的代碼練習才行。這個過程是5步中最關鍵的階段了,重在代碼親自練習,對編程中有的章節不明白的地方,千萬不要放過去,可以在網上找一些相關的編程交流群,參加進去,在線上咨詢一些過來人,也許就可以輕松幫你解決疑問了,對你的學習十分幫助,並且整個過程也都是免費的。
項目實戰
如果說基礎教程都按部就班的都實踐過一遍了,那麼你就有一定的編程的基本功了,那麼自己就可以嘗試著做一些小項目,把學到的知識給串起來,進入項目實戰階段,比如說自己設計一個學生管理系統,並把它完成,如果不了解怎麼設計,可以去網上搜索。慢慢就有思路了。
我也在學習這方面,視頻書籍看過不少,最推薦的還是北京尚學堂的學習資料,Java.300集,Python400集,都是很經典的入門基礎教程,而且是結合項目學習的,很有意思,干貨滿滿,還都是免費的,推薦你可以去看看,相信可以帶你走進變成的世界。
從零開始學編程,第一關就是要選擇你所要學習的編程語言。面對著琳琅滿目的編程語言,初學者常常一籌莫展,拿不定主意,不知該選哪
2. UNIX編程藝術的介紹
本書寫作了五年之久,作者將UNIX三十年中未見紙端的艱難勝利的軟體工程智慧融入文字,使UNIX家族成為最好最具創新軟體的哲學、設計模式、工具、文化和傳統,Raymond將之第一次帶給我們,並向我們展示它們如何影響著當今的Linux和開源運動。通過大量來自頂尖項目的實例,你將學會如何運用這些智慧經驗來建造更優雅、更可移植、更加好用和更加長久的軟體。
3. 你好:如果想要讀懂《Unix高級環境編程》和《Unix網路編程卷1,套接字》
這些書我都讀過了,全是買的實體書
高級環境編程和兩本網路編程其實是相輔相成的
如果想在linux下發展,鳥哥基礎篇最好看看,很好
這些學習的前提是要有一定的c語言基礎
在學習網路編程時,可以順便參考一下《tcp/ip詳解.卷1》
其實頭三本書,已經非常不錯了,如果可以認真學完,水平也算可以了,就是要實踐來彌補不足了
建議:不要貪多,更不要放棄,切記切記
4. 小白,想入門程序員,應該從什麼開始學,順序是什麼
首選是選擇一門合適的語言,比如說:Python、Java、C、C++、GO語言等;其次,選擇合適的學習方式,比如培訓,周末班、脫產班還是網路班。
【程序員的初學者入門的方法】如下:
1、明確編程的本質。
2、 必要的輔助工具與技能。
(1)學會使用git指令和github;
(2)挑選一款合適的IDE會使編程體驗和效率大大提升,IDE即集成開發環境,是用於提供程序開發環境的應用程序;
(3)明確學習的方向,不同的劃分標准下有不同的開發方向,如按編程語言劃分有JAVA,Python,C/C++, Javascript,Ruby,PHP,etc;
3、選擇合適的學習方式與方法。
(1)學好所有相關的專業課程,無論它多麼枯燥乏味;
(2)不要質疑老師讓你閱讀代碼、抄寫代碼的意義。
想了解更多有關入門程序員的詳情,推薦咨詢達內教育。達內教育具有強大的師資力量,優秀的教學體系,教學質量突出,實戰講師,經驗豐富,理論知識+學習思維+實戰操作,打造完整學習閉環。達內教育獨創TTS8.0教學系統,並設有企業雙選會;同時,達內的OMO教學模式,已經全新升級,線上線下交互學習,直播學,隨時學,隨時問,反復學,讓學院上課安排更便捷。【感興趣的話點擊此處,免費學習一下】
5. UNIX編程藝術的序
Unix is not so much an operating system as an oral history.
與其說Unix是個操作系統,不如說是一部口述歷史。
——Neal Stephenson
知識和專能差異巨大,憑借知識可以推斷出該做什麼,而專能讓你甚至在無意之間,條件反射似的把事情做好。
這本書確實有關「知識」,但更著眼於「專能」。你將學到那些Unix專家們都不自知的Unix開發知識。少一點技術,多一些共享文化:顯見和隱微的,直觀和潛流的——這是本書和大多數Unix書籍不同的地方——不止於方法,更重乎理念。
理念於實用大有裨益,有太多設計不良的軟體:體積臃腫,難於維護、移植和擴展——這些都是蹩腳設計的癥候。我們希望本書的讀者能品出什麼是Unix所教示的良好設計。
本書分為四部分:場景、設計、工具和社群。第一部分(場景)涉及哲學和歷史,為後續內容埋下伏筆。第二部分(設計)將Unix哲學的原理細分為有關設計與實現的、更專門的建議。第三部分(工具)著眼於Unix所提供的工具,可助你解決問題。第四部分(社群)則講述人與人之間的事務與約定,而這正是Unix文化擁有高效能的原因。
這本書是關於共享文化的,我從未想像過獨自完成它。你會發現正劇中包含數位Unix資深專家的客串演出,正是這些人塑造了Unix的習俗。本書曾有過公開大范圍的審閱過程,這期間我邀請這些明星人士對書稿進行評審與研論。這些意見沒有湮沒在本書定稿中,而你可以在書中聆聽到他們的真實聲音:無論是為本書吶喊助陣、還是搖頭反對。
本書中用到人稱「我們」時,我並不是虛張聲勢,僅以此說明這是整個社群都清楚明了的事實。
因為本書著力傳遞文化,因此加入了很多野史和坊間傳說,這在技術書中並不多見。希望你喜歡,這些東西其實是Unix程序員的教養。須彌不重,芥子不輕。我們希望以這種方式更好地講述故事。了解Unix的由來和變遷,會培養你對Unix風格的直覺。
同樣地,基於此,我們不打算使用回述歷史的腔調。你會發現本書參考了眾多時下信息。我們不希望給你一種錯覺:書里說的都是亘古不變的終極真理。參考時下的信息這一做法,也提醒讀者,三十年河東,三十年河西,眼前所見,也許過不了多久就會過時,而需要重新檢省。
另外,本書不是C教程,不是Unix命令和API的手冊,不是sed/yacc/Perl/Python的語言參考,也不是網路編程入門,更不是巨細靡遺的令人費解的X指南。本書也不打算帶你巡遊Unix內幕和體系。有很多其它的好書涵蓋這些領域,本書會在適當的時候告訴你該看哪些。
在這些技術細節外,Unix文化有一個未見諸筆端的行工傳統,以熟練工的考量,它已經有幾百萬人年的發展 。本書即立足於這樣一個信念:領會此傳統,並將它的設計手法應用到手邊,你將成為更好的程序員和設計師。
構成文化的是人,一直以來,獲知文化的方式大約是口口相傳、潛移默化。本書不打算取代人際的文化傳播,但可以促進這一過程,使你能俯耳傾聽他人的心聲。
誰應該看這本書
如果你是個Unix編程老手,經常教導菜鳥,或者與人進行操作系統論戰時無法闡明使用Unix方案所帶來的好處時,可以看看這本書。
如果你是個C、C++或者Java程序員,有其它操作系統的開發經驗,現在輪到你開展一個Unix項目時,可以看看這本書。
如果你是個初級或者中級水平的Unix用戶,但是沒什麼開發經驗,想學習在Unix下如何高效地設計軟體時,可以看看這本書。
如果你不在Unix下編程卻發覺Unix的傳統給你帶來某種啟迪,那你就對了,Unix哲學適用於其它的操作系統。因此我們會花比其它Unix書籍更多的篇幅關注非Unix環境(特別是微軟的操作系統);當所用到工具或者案例可用於其它操作系統時,我們會告訴你。
如果你是一個系統架構師,正為通用市場或垂直應用准備平台方案或實現策略時可以看看這本書。本書將幫助你了解Unix作為開發平台的強大功能,以及開放源碼這個Unix的傳統所帶來的開發方式。
如果你想學到C編程的細節或者想知道怎麼用Unix內核API,本書可能不適合你。Advanced Programming in theUnix Environment [Stevens92]是探究Unix API的經典名著;The Practice of Programming [Kernighan-Pike99]是每個C程序員的必讀書目(任何語言的程序員都該看看這本書)。
如何使用這本書
這本書既重實踐,更富理念;既包含警世格言,又不忘檢點Unix開發中的特殊案例。在每個警句前後,都有生動實例闡明其由來,這些例子絕不來自小兒科式的示常式序,而均出自真實世界滿眼所見的運行代碼。
我們著力避免以大量代碼或者規範文件來胡亂湊數,當然這么做會讓本書的寫作輕松許多(某些地方或許讀起來也更輕松)。絕大多數編程書籍只授你以魚,而本書避免這種做法,力求培養讀者「探求事情何以如此」的感知力。
正由於此,本書會時常請你閱讀代碼與規範文檔,它們中極少量的內容會附在書中,其餘部分我們會在舉例時告訴你如何從網上獲取。
從這些範例中汲取養分,將有助你將所學原則消化變為皰丁之技。如果你能就著一部跑在Unix系統上的網頁瀏覽器來讀書,是再理想不過的了。任何Unix系統都適合,但是我們將要研究的案例大多都會預裝在、或者可以從Linux系統上獲得,書中會提示請你瀏覽或親身感受它們。這些提示通常是按部就班的,跑開玩一會兒並不會打散整個講述過程的連續性。
注意:我們雖力求,但無法給你打保票,聲稱我們所引用的URLs穩定可用。如果你發現某個引用連接已陳舊過時,來點常識,用你喜愛的搜索引擎來個短語搜索。如有可能,我們會在所引用的URLs附近給出如何搜索的提示。
大多數縮寫形式會在首次出現時伴隨其全稱。為方便起見,我們在附錄中提供了名詞對照表。
交叉索引通常以作者名字為主導詞。帶編號的腳注是那些可能會擾亂你閱讀正文,或者是易變的URLs;也可能是旁徵博引的戰爭故事或者笑話 。
為了使這本書不至於讓非技術人員太過難讀,我們邀請了一些非程序員試讀,並指出一些晦澀但起貫穿作用的詞彙。我們把那些編程老手不太會需要的名詞解釋也放在腳注中。
相關引文
一些Unix早期拓荒者的著名論文和書籍,比如Kernighan和Pike的《The Unix Programming Environment》[Kernighan-Pike84]就是其中佼佼者,被世人尊為圭臬。而今看來此書廉頗老矣,它沒提到Internet、萬維網以及諸如Perl、Tcl和Python這些解釋型語言的新秀。
寫作本書的中途我們借鑒了Mike Gancarz的《The Unix Philosophy》[Gancarz]。這本書在它的覆蓋范圍內極其優秀,但是我們覺得需要更多內容才能反映出事情的全貌。盡管如此我們仍對此書作者心存感激,他愈發使我們知道最簡單的Unix設計手法就是最持久耐用的。
《The Pragmatic Programmer》[Hunt-Thomas]是一本關於良好設計的書,文風機智詼諧,它與本書相比,傾向於軟體設計工藝的另一個層面(更注重編碼,而少著墨於高層面的問題劃分)。作者的哲學是其Unix領域耕耘的成果,也是本書內容極好的補充。
《The Practice of Programming》[Kernighan-Pike99]包含了一些與《The Pragmatic Programmer》共通的內容,但更鑽入Unix傳統的深處。
最後(明知道會激怒你),我們推薦《Zen Flesh, Zen Bones》[Reps-Senzaki],一部重要的佛教禪宗本源的合集。對禪的引用書目遍布全書。我們將這些書目包含進來,是因為禪為表達某種想法提供了豐富的語匯,而在軟體設計中卻很難爛熟於心。信奉宗教的讀者,請您不要把禪當成宗教,它是一種心靈雞湯似的東西,純凈而沒有神靈的干擾——此即是禪。
本書的習俗約定
術語「UNIX」技術上和法律上講,是The Open Group的商標,並且應該僅限於那些通過The Open Group嚴格的「符合標准」認證的操作系統。本書中我們使用其較寬松的定義,即大多數程序員所指的,Bell實驗室Unix代碼的後裔或旁支。在這個意義下,Linux(大多數例子都舉自它)也算是一種Unix。
本書也使用了Unix手冊頁(manual page)的傳統,即以括弧括起來的手冊節號來標記Unix設施。通常用於強調一個Unix命令首次出現。比如「munger(1)」可解讀為「munger程序加入存在於你的系統中,其文檔位於Unix手冊頁的第1節」。第2節是C的系統調用,第3節是C的庫函數調用,第5節是文件格式與協議,第8節是系統管理工具。其它節號本書未曾用到,其定義在各個Unix系統各有不同。在你的Unix外殼提示符下輸入man 1 man(老式的System VUnix系統可能要輸入man -s 1 man)以獲得更多信息。
有時我們會提及某個Unix程序(比如Emacs),後面沒有手冊節號而且首字母大寫。這意味這個名字代表一族Unix程序,其基本功能相同,而我們將討論其通用特性。比如Emacs,就包含了xemacs。
本書很多地方我們同時給出了老式(old school)和新式(new school)解法。new-school和rap音樂一樣,開始於1990年前後。在這個含義下,我們往往把它與腳本語言、圖形用戶界面、開放源碼的Unix和萬維網聯系起來。Old-school指代1990年以前(特別是1985年以前)的世界:昂貴的共用計算機、專屬的Unix,shell腳本和無所不在的C。值得指出這些差異,機器越來越便宜,內存多了起來,這些有如暗流,漸漸影響著Unix編程的風格。
所用案例
很多編程書籍為證明某一觀點而特地造出一個範例,你手中這本書不這么干。我們的案例研究均來自真實世界,在生產環境中工作已久。下面是一些主要案例:
cdrtools/xcdroast
這兩個獨立的項目通常被一並使用。cdrtools是一組刻盤工具(用關鍵字「cdrtools」可以在網上找到)。xcdroast是cdrtools的圖型界面前端,其項目網站。
fetchmail
fetchmail用於從遠程郵件伺服器上收信,支持POP3和IMAP郵箱協議。其主頁為,也可以用關鍵字「fetchmail」從網上找到。
GIMP
GIMP(GNU Image Manipulation Program,GNU圖像處理程序)是一個全特性的繪畫和圖像處理程序,可對多種圖像格式進行復雜處理。其源碼可從GIMP主頁獲得(也可以通過關鍵字「GIMP」從網上搜到)。
mutt
mutt郵件客戶端是目前各類基於文本的郵件客戶端程序中的翹楚,提供對MIME(Multipurpose Internet Mail Extensions)、個人隱私輔助程序,如PGP(Pretty Good Privacy)和GPG(GNU Privacy Guard)等特性的絕佳支持。其源碼和二進制可執行文件可以從Mutt項目主頁獲得。
xmlto
xmlto可將DocBook和其它XML文檔以多種格式渲染輸出,包括HTML、純文本和PostScript。其源碼和文檔可在xmlto主頁獲得。
為了將讀者理解本書例子所要閱讀的代碼量降低到最小程度,我們盡量挑選那些可重復使用、並能體現多種不同設計原理和設計實踐的案例。出於同樣原因,很多示例來自於我本人的項目。我沒想說這些例子最為恰當,只是我覺得它們對闡述我的觀點非常有用。
作者致謝
各位客串貢獻者(Ken Arnold, Steven M. Bellovin, Stuart Feldman, Jim Gettys, Steve Johnson, Brian Kernighan, David Korn, Mike Lesk, Doug McIlroy, Marshall Kirk McKusick, Keith Packard, Henry Spencer, 和Ken Thompson)為本書增添極大價值。特別是Doug McIlroy,給予本書恪盡職責、鞭辟入裡的評注的同時,也展現了他早在30年前管理最原始的Unix研究組時鞠躬盡瘁的高風亮節。
我要對Rob Landley和我的妻子Catherine Raymond致以特別感謝,他們都不厭其煩地逐行對本書手稿進行審閱。Rob的深富洞察力的細致評述激勵我在最終稿中加入了一整章內容,他為本書的組織結構與取材范圍奉獻極多。如果把他所給予的改進意見落在筆端,那他無愧於本書的合著者。Cathy代表讀者中非技術人員的一群,如果那些非程序員讀者覺得本書並不難讀,那全是她的功勞。
寫作的五年間,本書從不少人的討論意見中獲益良多。Mark M. Miller使我對線程有了更深的認識。John Cowan教給我不少介面設計方式,並起草了wily和VM/CMS的學習案例。Jef Raskin告訴我Rule of Least Surprise的由來。UIUC System Architecture Group對前幾章給出的反饋彌足珍貴,What Unix Gets Wrong和Flexibility in Depth兩節是他們直接激勵的結果。Russell J. Nelson提供了Bernstein chaining的素材。第3章中MVS學習案例大部分的材料來自Jay Maynard。Les Hatton對語言一章給出很多有益建議,並促使我寫成第4章中Optimal Mole Size的部分內容。David A. Wheeler貢獻了很多發人深省的批評,以及一些學習案例(特別是在設計部分中)的素材。Russ Cox幫助我進行了Plan 9的調查。Dennis Ritchie糾正了我的一些錯誤的C歷史觀念。
成百上千的Unix程序員,人數太多以至於無法在此列出他們的名字,在2003年1月到6月間的公開審閱過程間給了我建議和評論。開放的同級復審這一過程讓我覺得緊張刺激而回報極多。當然,任何最終書稿中殘留的錯誤都是我自己的責任。
「把事情說透」的風格,以及其它一些考慮因素,是受到了「設計模式運動」的影響;說實話,我對到處堆砌Unix設計模式這種做法深不以為然。我對此運動的中心教條不敢苟同,並且沒覺得把設計模式嚴格付諸實用有什麼必要,也不想背上這種思想的包袱。盡管如此,我的行事方法仍然受到Christopher Alexander成果 (特別是《Timeless Way of Building》和《A Pattern Language》兩文)的影響。Gang of Four和他們的信徒為我展示了如何用Alexander的思想,站在較高層面上,拋去含混不清的對設計通則的空話,來談論軟體設計,這一點我心存感激,永誌不忘。對設計模式有興趣的讀者可以看看這本書《Design Patterns: Elements of Reusable Object-Oriented Software [GangOfFour]》。
本書標題毫無疑問是借鑒了Donald Knuth的《The Art of Computer Programming》一書的書名。Knuth和Unix傳統文化沒什麼聯系,但他影響了我們每一個人。
有先見之明和豐富想像力的編輯並不多,好在Mark Taub就是一個,他從並不看好的項目中發現了閃光點,並極富技巧地促成了這本書的寫作。文字編輯中,文筆好而又能幫助別人提高文筆的就更少了,所幸Mary Lou Nohr是其中之一。Jerry Votta的封面設計領會了我的意圖,而且做得比我的想像還要漂亮。Addison-Wesley的編輯們讓審稿和出版這一過程不再枯燥無味,我天生怕被人管,但是他們仍然極力配合我,使得文字、版面、圖片和市場工作都達到極高水準。