官术网_书友最值得收藏!

引言

幾年前,我跟一個(gè)瑞士來的交換生一起坐滑雪纜車。我問她有沒有想過高中畢業(yè)后打算做什么。她說她打算做工程,并且已經(jīng)在前一年修了編程課程。我問她你們學(xué)了些什么,她回答:“Java。”我下意識地脫口而出:“那太糟糕了。”

我為什么會(huì)這樣說呢?我花了一些時(shí)間才想明白這個(gè)問題。我那么說并不是因?yàn)镴ava這個(gè)編程語言不好,它其實(shí)挺好的。之所以那么說,是因?yàn)楝F(xiàn)在教授Java(以及其他編程語言)的方法很糟糕,學(xué)不到任何關(guān)于計(jì)算機(jī)本身的知識。如果你也覺得這種情況有點(diǎn)奇怪,那這本書就是你應(yīng)該看的。

Java編程語言是20世紀(jì)90年代在一個(gè)美國計(jì)算機(jī)公司Sun Microsystems由James Gosling、Mike Sheridan和Patrick Naughton發(fā)明的。它在某種程度上模仿了那時(shí)流行的C語言。C語言沒有對內(nèi)存的自動(dòng)管理功能,而且在那時(shí)內(nèi)存管理錯(cuò)誤是一個(gè)普遍存在的問題,讓人頭疼。Java從設(shè)計(jì)上消除了這類程序錯(cuò)誤。它對程序員隱藏了底層內(nèi)存管理。這就是Java對初學(xué)者友好的部分原因。但是要編寫優(yōu)秀程序,培養(yǎng)優(yōu)秀程序員,需要的不僅僅是一種好的編程語言。事實(shí)證明,Java引入了一類新的很難調(diào)試的編程問題,包括隱藏內(nèi)存管理系統(tǒng)導(dǎo)致的性能低下問題。

就像你在書里看到的,理解內(nèi)存是程序員的一個(gè)重要技能。學(xué)習(xí)編程時(shí)養(yǎng)成的習(xí)慣很難改掉。研究表明,在所謂的“安全”操場玩耍長大的孩子更容易受傷,大概是因?yàn)樗麄儾恢浪さ沟膫ΑT诰幊填I(lǐng)域也存在類似的情況。舒適的編程環(huán)境使入門不那么恐怖,但你還是需要做好準(zhǔn)備,以面對復(fù)雜的外部環(huán)境。本書可以幫你實(shí)現(xiàn)這種轉(zhuǎn)變。

為什么好的程序很重要

想理解為什么不包括計(jì)算機(jī)教學(xué)的編程教育存在問題,首先需要考慮到計(jì)算機(jī)已經(jīng)變得多么普遍。計(jì)算機(jī)降價(jià)如此顯著,很多東西用計(jì)算機(jī)建造才最便宜。舉個(gè)例子,用計(jì)算機(jī)在汽車儀表盤上顯示一個(gè)老式的模擬時(shí)鐘比使用真的機(jī)械鐘花費(fèi)得少得多。計(jì)算機(jī)芯片現(xiàn)在很便宜,用腳踩壞一個(gè)包含數(shù)十億元件的芯片不再是什么大不了的事。注意,我是在說計(jì)算機(jī)本身的價(jià)格,不是那些包含了計(jì)算機(jī)的東西的價(jià)格。通常,計(jì)算機(jī)芯片的成本比它們的包裝運(yùn)輸成本更少。未來很有可能很難找到什么東西不含計(jì)算機(jī)。

讓很多計(jì)算機(jī)去處理大量事情意味著需要大量的計(jì)算機(jī)程序。計(jì)算機(jī)使用如此廣泛,因而編程的應(yīng)用領(lǐng)域廣泛而多樣。就像在醫(yī)療領(lǐng)域,許多程序員成了這方面的專家。你可以在視覺處理、卡通動(dòng)畫、網(wǎng)頁、手機(jī)應(yīng)用、工業(yè)控制、醫(yī)療設(shè)備等更多方面成為專家。

奇怪的是,計(jì)算機(jī)編程不同于醫(yī)學(xué),在編程領(lǐng)域,你不用全面了解就可以成為一個(gè)專家。你可能不想讓一個(gè)沒學(xué)過解剖學(xué)的醫(yī)生給你做心臟外科手術(shù),但是對如今的許多程序員來說,類似的問題已經(jīng)成為常態(tài)。這真的是個(gè)問題嗎?事實(shí)上,大量證據(jù)表明部分程序的運(yùn)行效果并不是很好,每天都有關(guān)于安全漏洞和產(chǎn)品召回的報(bào)告。在一些法庭案件中,被判酒駕的人贏得了對酒精測試代碼進(jìn)行審查的權(quán)利。事實(shí)證明代碼中充滿了漏洞,這導(dǎo)致已定罪名被推翻。近日,發(fā)生了正在進(jìn)行心臟外科手術(shù)的醫(yī)療器械因殺毒軟件而崩潰的事故。還有因波音737 MAX飛機(jī)設(shè)計(jì)問題致使許多人喪生的事故。許多像這樣的事故讓人們對程序喪失了信任。

學(xué)習(xí)編程只是一個(gè)開始

出現(xiàn)這種情況的部分原因是,編寫看起來可以工作的計(jì)算機(jī)程序,或者大部分時(shí)間都可以工作的計(jì)算機(jī)程序并沒有那么困難。我們用20世紀(jì)80年代的音樂(非disco)變化來做個(gè)類比。以前人們必須打好基礎(chǔ)才能創(chuàng)作音樂,這包括學(xué)習(xí)樂理、作曲,練習(xí)演奏樂器,聽音練耳,以及其他很多練習(xí)。后來,樂器數(shù)字接口(MIDI)標(biāo)準(zhǔn)出現(xiàn)了,任何人都可以在沒有多年勤學(xué)苦練基礎(chǔ)的情況下通過計(jì)算機(jī)創(chuàng)作“音樂”。我覺得,只有很小比例的計(jì)算機(jī)生成音樂稱得上音樂,其余大部分只是噪音而已。音樂是被真正的音樂家創(chuàng)作出來的,他們可能用MIDI,但無一不擁有深厚的音樂基礎(chǔ)。如今,編程變得非常像使用MIDI創(chuàng)作“音樂”。寫程序不再需要付出很多汗水,不再需要花費(fèi)幾年的時(shí)間去練習(xí),甚至不再需要學(xué)習(xí)理論。但是這不代表這些程序優(yōu)秀或者性能可靠。

這種情況越來越嚴(yán)重了,起碼在美國是這樣。擁有既得利益的富人們,比如那些擁有軟件公司的人,一直在游說立法,要求每個(gè)人都要在學(xué)校里學(xué)習(xí)編程。理論上聽著不錯(cuò),但在實(shí)踐中并不是個(gè)好主意,因?yàn)椴皇敲總€(gè)人都有成為好程序員的天賦。我們沒有要求每個(gè)人都去學(xué)足球,因?yàn)槲覀兦宄皇敲總€(gè)人都適合踢足球。這一倡議的目的可能不是培養(yǎng)出優(yōu)秀的程序員,而是通過向市場大量輸入不怎么樣的程序員,壓低工資水平,以增加軟件公司的利潤。幕后推手們不關(guān)心代碼質(zhì)量,甚至還推動(dòng)立法以減輕他們對缺陷產(chǎn)品所負(fù)的責(zé)任。當(dāng)然,就像可以踢球踢著玩一樣,你也可以編程編著玩,就是別期待會(huì)被超級碗挑中了。

2014年,美國前總統(tǒng)奧巴馬表示,他已經(jīng)學(xué)會(huì)了編程。他確實(shí)在優(yōu)秀的可視化編程工具Blockly中拖動(dòng)了一些東西,甚至在JavaScript(一種與Java無關(guān)的編程語言,由維護(hù)了包括火狐瀏覽器在內(nèi)的許多軟件包的Mozilla Foundation的前身Netscape公司發(fā)明)中輸入了一行代碼。你覺得他真的學(xué)會(huì)了編程嗎?給個(gè)提示:如果你認(rèn)為他學(xué)會(huì)了,那么你應(yīng)該在讀本書的同時(shí)努力鍛煉你的批判思維能力。當(dāng)然,他是學(xué)了那么一點(diǎn)點(diǎn)有關(guān)程序的知識,但是,他沒有學(xué)習(xí)編程。如果能在一小時(shí)之內(nèi)學(xué)會(huì)編程,那就是說編程太小菜一碟了,根本不需要在校園里開課。

底層知識的重要性

Mathematica和Wolfram語言的創(chuàng)造者Stephen Wolfram在一篇題為“How to Teach Computational Thinking”的博客帖子中表達(dá)了一個(gè)有趣且有些相悖的觀點(diǎn):他把計(jì)算思維定義為“把事件標(biāo)準(zhǔn)化得足夠清晰,人可以通過一個(gè)足夠系統(tǒng)化的方法告訴計(jì)算機(jī)怎么運(yùn)行”。我完全認(rèn)同這個(gè)定義。事實(shí)上,很大程度上這也是我寫這本書的動(dòng)力。

但我非常不認(rèn)同Wolfram的一個(gè)觀點(diǎn),即那些學(xué)習(xí)編程的人應(yīng)該使用強(qiáng)大的高級工具(比如他開發(fā)的那些工具)來培養(yǎng)計(jì)算思維能力,而不是學(xué)習(xí)底層基礎(chǔ)技術(shù)。例如,從人們對統(tǒng)計(jì)學(xué)的興趣日益超過對微積分的興趣這一趨勢中,我們可以清楚地看到,“數(shù)據(jù)整理”是一個(gè)正在發(fā)展的領(lǐng)域。但是,如果人們只是將大量的數(shù)據(jù)輸入這些并不熟悉的程序中,又會(huì)發(fā)生什么呢?

一種可能是,它們產(chǎn)生的結(jié)果看起來很有趣,但沒有意義或者不正確。例如,最近的一項(xiàng)研究(Mark Ziemann、Yotam Eren和Assam El-Osta的“Gene Name Errors Are Widespread in the Scientific Literature”)顯示,五分之一已發(fā)表的遺傳學(xué)論文由于電子表格使用不當(dāng)而出現(xiàn)錯(cuò)誤。試想一下,如果有更多人使用更強(qiáng)大的工具,可能會(huì)產(chǎn)生怎樣的錯(cuò)誤和后果!當(dāng)人們的生活受到影響時(shí),正確處理好它才是至關(guān)重要的。

理解底層技術(shù)可以幫助你了解可能出現(xiàn)的問題。只知道高級工具很容易提出錯(cuò)誤的問題。在學(xué)習(xí)釘槍之前,先學(xué)會(huì)使用錘子是值得的。學(xué)習(xí)底層系統(tǒng)和工具的另一個(gè)原因是,它能賦予你構(gòu)建新工具的能力,這一點(diǎn)很重要,因?yàn)橛肋h(yuǎn)需要工具構(gòu)建者,盡管工具用戶更常見。學(xué)習(xí)有關(guān)計(jì)算機(jī)的知識使你能夠編寫更好的代碼,程序的性能狀態(tài)也就不再神秘了。

目標(biāo)讀者

本書是為想成為優(yōu)秀程序員的人準(zhǔn)備的。是什么成就了一個(gè)優(yōu)秀的程序員?首先,一個(gè)優(yōu)秀的程序員應(yīng)該具備良好的批判性思維和分析能力。為了解決復(fù)雜的問題,程序員需要有能力評估程序是否能正確地解決恰當(dāng)?shù)膯栴}。這比聽起來要難得多。經(jīng)常會(huì)見到有經(jīng)驗(yàn)的程序員對別人寫的程序冷嘲熱諷:“將簡單事情復(fù)雜化了,制造了不是問題的問題。”

你可能很熟悉一個(gè)經(jīng)典的魔幻故事比喻:魔法師通過了解事物的真名來獲得力量,如果忘了某個(gè)細(xì)節(jié),魔法師就會(huì)遭殃。優(yōu)秀的程序員就是那種能夠牢牢把握住事物的本質(zhì),不放過任何一個(gè)細(xì)節(jié)的魔法師。

優(yōu)秀的程序員也應(yīng)該有一定的藝術(shù)修養(yǎng),就像熟練的工匠一樣。遇到讓人完全無法理解的代碼的情形并不少見,就像許多說英語的人對詹姆斯·喬伊斯(James Joyce)的小說《芬尼根的守靈夜》很困惑一樣。優(yōu)秀的程序員寫出的代碼不僅要能正常工作,而且要很容易讓別人理解和維護(hù)。

最后,優(yōu)秀的程序員需要對計(jì)算機(jī)的工作原理有深刻的理解。僅憑淺薄的知識基礎(chǔ)無法很好地解決復(fù)雜問題。本書適合那些正在學(xué)習(xí)編程,但又對現(xiàn)有知識深度不滿意的人。本書也適合已經(jīng)在學(xué)習(xí)編程,但還想要學(xué)習(xí)更多的人。

計(jì)算機(jī)是什么

一個(gè)普遍的答案是,計(jì)算機(jī)是人們用來做諸如檢查電子郵件、網(wǎng)上購物、寫論文、整理照片以及玩游戲等任務(wù)的工具。消費(fèi)類產(chǎn)品開始和計(jì)算機(jī)結(jié)合,是這個(gè)草率定義普遍存在的部分原因。另一個(gè)常見的答案是,計(jì)算機(jī)是能使高科技玩具(比如手機(jī)和音樂播放器)運(yùn)作的大腦。這種說法更接近正確答案。

發(fā)送電子郵件和玩游戲都是通過計(jì)算機(jī)上運(yùn)行的程序來實(shí)現(xiàn)的。計(jì)算機(jī)本身就像一個(gè)新生嬰兒,它并不懂很多事情的做法。我們幾乎不會(huì)去考慮人類的基礎(chǔ)運(yùn)轉(zhuǎn)系統(tǒng),因?yàn)槲覀冎饕c運(yùn)行在這個(gè)基礎(chǔ)系統(tǒng)上的人格進(jìn)行互動(dòng),就像計(jì)算機(jī)上運(yùn)行的程序一樣。例如,當(dāng)你瀏覽網(wǎng)頁時(shí),你不是只用這個(gè)計(jì)算機(jī)本身去閱讀,而是通過在你的計(jì)算機(jī)上運(yùn)行的別人編寫的程序、承載網(wǎng)頁的計(jì)算機(jī)、構(gòu)成網(wǎng)絡(luò)的所有計(jì)算機(jī)去閱讀。

什么是計(jì)算機(jī)編程

教師是訓(xùn)練人的基礎(chǔ)運(yùn)轉(zhuǎn)系統(tǒng)來完成某些任務(wù)的人。同理,編程就是讓程序員成為計(jì)算機(jī)的老師,教計(jì)算機(jī)做程序員要它做的事情。

知道如何去教計(jì)算機(jī)是很有用的,特別是當(dāng)你想讓計(jì)算機(jī)做一些它不知道該怎么做的事情,而又買不到相關(guān)程序的時(shí)候。例如,你可能認(rèn)為萬維網(wǎng)的存在是理所當(dāng)然的,但它不久前才被發(fā)明,當(dāng)時(shí)Tim Berners-Lee爵士需要一個(gè)更好的方法讓歐洲核子研究組織(Conseil Européen pour la Recherche Nucléaire,CERN)的科學(xué)家們分享信息。而他因此被封為了爵士。

教計(jì)算機(jī)學(xué)東西很復(fù)雜,但比教人學(xué)東西容易多了,畢竟我們對計(jì)算機(jī)的工作原理了解得更多。而且計(jì)算機(jī)不大可能學(xué)到吐,它沒那么容易對學(xué)習(xí)厭煩。

計(jì)算機(jī)編程是一個(gè)兩步驟的過程:

1. 理解宇宙。

2. 向三歲的孩子解釋宇宙。

這是什么意思呢?你無法編寫計(jì)算機(jī)程序去做一些你自己都不理解的事。比如,如果你不懂拼寫規(guī)則,你就無法寫出拼寫檢查程序;如果你不懂物理學(xué),你就無法寫出好的動(dòng)作電子游戲。所以,要成為一名優(yōu)秀的程序員,第一步就是要盡可能多地學(xué)習(xí)其他知識。解決問題的辦法往往來自意想不到的地方,不要因?yàn)槟臣驴雌饋硭坪鯖]有直接的關(guān)系就忽略了它。

這個(gè)過程的第二步需要向計(jì)算機(jī)解釋你所知道的東西。計(jì)算機(jī)對世界的看法非常僵化,就像小孩子一樣,在三歲左右的時(shí)候,孩子的這種僵化看法真的很明顯。比如,你們想出門,你問你的孩子:“你的鞋子在哪里?”孩子說:“這里。”她確實(shí)回答了你的問題。問題是,她不明白你是在要求她穿上鞋子,這樣你倆就可以出門了。靈活性和推理能力是孩子們在成長過程中才會(huì)學(xué)習(xí)到的技能。但計(jì)算機(jī)就像小飛俠彼得·潘:它們永遠(yuǎn)不會(huì)長大。

計(jì)算機(jī)也像年幼的孩子,因?yàn)樗鼈儾恢廊绾螝w納總結(jié)。但它們還是很有用處的,因?yàn)橐坏┠阆牒昧嗽趺聪蛩鼈兘忉屢恍〇|西,它們就會(huì)不厭其煩、快速地去做,盡管它們沒有任何常識。計(jì)算機(jī)會(huì)不知疲倦地做你要求的事情,而不去評估那是否是錯(cuò)誤的任務(wù),這很像1940年的電影《幻想曲》中“魔法師的學(xué)徒”片段中的魔法掃帚。要求計(jì)算機(jī)做事,就像向魔法燈籠里的精靈(不是FBI版)許愿一樣,你必須非常小心你的措辭!

你可能會(huì)懷疑我所說的,因?yàn)橛?jì)算機(jī)似乎比它們本身更有能力。比如,當(dāng)你使用計(jì)算機(jī)時(shí),它知道如何畫圖、糾正你的拼寫、理解你說的話、播放音樂等。但請記住,實(shí)現(xiàn)這些任務(wù)的不是計(jì)算機(jī),而是人為編寫的一套復(fù)雜的旨在讓計(jì)算機(jī)完成這些任務(wù)的計(jì)算機(jī)程序。計(jì)算機(jī)與運(yùn)行在計(jì)算機(jī)上的程序是分開的。

就像在路上看到的汽車一樣,它似乎很擅長在適當(dāng)?shù)臅r(shí)候停車和啟動(dòng),避開障礙物,到達(dá)目的地,沒油了就加油,等等。但是,這不僅僅是汽車完成的,而是汽車和駕駛員結(jié)合在一起完成的。計(jì)算機(jī)就像汽車,程序就像駕駛員。如果沒有知識,你就不能分辨出什么是汽車做的以及什么是駕駛員做的。(參見May Swenson的“Southbound on the Freeway”。在不同的人生階段,你對詩末提出的問題的答案可能會(huì)不同。)

總而言之,為了解決問題,計(jì)算機(jī)編程涉及學(xué)習(xí)你需要知道的東西,然后再把它解釋給小孩子。因?yàn)榻鉀Q問題的方法有很多,所以編程既是一門藝術(shù),也是一門科學(xué)。它涉及尋找優(yōu)雅的解決方案,而不是使用蠻力解決。在墻上打一個(gè)洞的確能讓你走出家門,但要想走出家門可能還有更容易的方法。很多人可以用幾百萬行代碼寫出像HealthCare.gov這樣的東西,但要用幾千行代碼來完成,那是需要技巧的。

不過在指導(dǎo)三歲的孩子之前,你需要先了解三歲的孩子,了解他們的理解能力。而且計(jì)算機(jī)不是真的普通三歲小孩,而是一種“外星生命體”。計(jì)算機(jī)的游戲規(guī)則和我們不一樣。你可能聽說過人工智能(AI),它試圖讓計(jì)算機(jī)表現(xiàn)得更像人。該領(lǐng)域的進(jìn)展比原先預(yù)計(jì)的要緩慢得多。這主要是因?yàn)槲覀儾⒉皇呛芮宄亓私膺@個(gè)問題,我們對人類的思維也不夠了解。你可以想象,當(dāng)我們自己都不知道到底該怎么做的時(shí)候,要教會(huì)外星人像我們一樣去思考這件事有多難。

人的大腦在不自主的思維情況下,就能做一些事情。你的大腦一開始只是一塊硬件,然后就好像被編程了。例如,你學(xué)會(huì)了移動(dòng)手指,然后就學(xué)會(huì)了抓東西。經(jīng)過練習(xí),你就可以不經(jīng)思索地抓住東西,而不需要思考其中的步驟。對于這個(gè)學(xué)習(xí)過程是如何運(yùn)作的,哲學(xué)家讓·皮亞杰(Jean Piaget,法國心理學(xué)家)和諾姆·喬姆斯基(Noam Chomsky,1928年出生的美國語言學(xué)家)等人提出了不同的理論。大腦是一個(gè)一般的設(shè)備,還是它有特殊的硬件來實(shí)現(xiàn)語言等功能?這個(gè)問題還在研究中。

我們不可思議的無意識執(zhí)行任務(wù)的能力使學(xué)習(xí)編程變得困難,因?yàn)榫幊绦枰獙⑷蝿?wù)分解成計(jì)算機(jī)能夠遵循的更小步驟。比如,你可能知道如何玩井字棋游戲。找一群人一起玩,讓每名玩家各自列出應(yīng)該采取的步驟。在大家都列好之后,舉行一場比賽。看看誰的規(guī)則好!你的規(guī)則有多好?你錯(cuò)過了什么?在玩游戲時(shí),你真的知道你在做什么嗎?很有可能有很多因素你都沒想出來,因?yàn)槟闶窃趹{直覺理解它們。

你可能覺得第一步比第二步更重要,即了解宇宙比向三歲孩子解釋宇宙更重要。想想看:如果你不知道說什么,那知道怎么說又有什么用呢?盡管如此,目前的教育還是把重點(diǎn)放在了第二步。這是因?yàn)榕c創(chuàng)造性內(nèi)容相比,機(jī)械原理方面的教學(xué)和打分要容易得多。而且一般情況下,教師在這方面的訓(xùn)練很少,都是按照別處開發(fā)的課程來進(jìn)行教學(xué)。而本書則側(cè)重第一步。雖然它不能涵蓋整個(gè)宇宙,但它檢查了計(jì)算機(jī)領(lǐng)域的問題和解決方法,而不是糾纏于實(shí)現(xiàn)這些解決方法需要的具體編程語法。

編碼、編程、工程和計(jì)算機(jī)科學(xué)

有許多描述軟件工作的術(shù)語,雖然這些術(shù)語有一些粗略的定義,但并沒有確切的定義。

編碼是最近相當(dāng)流行的一個(gè)術(shù)語,作為“學(xué)習(xí)編碼”的一部分,可以看作有點(diǎn)機(jī)械的翻譯工作。我們把它代入醫(yī)療編碼的工作中。當(dāng)你去看醫(yī)生時(shí),很容易得到診斷。難的是將診斷翻譯成ICD標(biāo)準(zhǔn)(在編寫本書時(shí)為ICD-10)中的10萬多個(gè)編碼之一。學(xué)過這些編碼的注冊專業(yè)編碼員知道,當(dāng)醫(yī)生提出“被牛撞了”的診斷時(shí),應(yīng)該將其分配為W55.2XA編碼。這其實(shí)比編程領(lǐng)域中的很多編碼工作都要難,因?yàn)榫幋a的絕對數(shù)量非常大。但是,這個(gè)過程類似于指示編碼員在網(wǎng)頁上“加粗文字”,編碼員知道用什么編碼來完成這件事。

ICD-10標(biāo)準(zhǔn)非常復(fù)雜,以至于很少有編碼員知道它的全部內(nèi)容。因此,醫(yī)療編碼員均在某個(gè)專業(yè)領(lǐng)域,如“神經(jīng)系統(tǒng)疾病”或“精神和行為障礙”獲得認(rèn)證。這類似于程序員精通一門語言,比如HTML或JavaScript。

編程,也就是做一名程序員,意味著要了解的不僅僅是一兩個(gè)專業(yè)領(lǐng)域。在這種情況下,醫(yī)生就類似于程序員。醫(yī)生通過對病人進(jìn)行評估來診斷。這可能會(huì)相當(dāng)復(fù)雜。比如,如果病人燒傷,而且渾身濕透,是“怪異的個(gè)人外觀”(R46.1)還是“滑水板著火所致的燒傷,首例”(V91.07XA)?醫(yī)生有了診斷,就可以制定出治療方案。治療方案必須是有效的:醫(yī)生大概不希望看到同樣的病人因?yàn)椤案改傅倪^度保護(hù)”(Z62.1)而痛苦不堪。

就像醫(yī)生一樣,程序員也會(huì)對問題進(jìn)行評估并確定一個(gè)解決方案。例如,也許有必要建立一個(gè)網(wǎng)站,允許人們把ICD-10代碼按質(zhì)量高低進(jìn)行排序。構(gòu)建網(wǎng)站時(shí),程序員會(huì)確定存儲和處理數(shù)據(jù)的最佳算法,網(wǎng)絡(luò)客戶端和服務(wù)器之間的通信結(jié)構(gòu),用戶界面,等等。這不是一個(gè)簡單的“插上代碼”之類的東西。

工程的復(fù)雜度進(jìn)一步提升。總的來說,工程是一門利用知識完成某些事情的藝術(shù)。你可以把ICD標(biāo)準(zhǔn)的創(chuàng)建視為工程,它把龐大的醫(yī)學(xué)診斷領(lǐng)域縮減為一組比醫(yī)生筆記更容易跟蹤和分析的編碼。這樣一個(gè)復(fù)雜的系統(tǒng)是否代表著好的工程,這是個(gè)見仁見智的問題。舉個(gè)計(jì)算機(jī)工程的例子,很多年前,我參與過一個(gè)項(xiàng)目,建造一個(gè)低成本的醫(yī)療監(jiān)護(hù)儀,比如你們在醫(yī)院里看到的那些儀器。我的任務(wù)是制作一個(gè)系統(tǒng),讓醫(yī)生或護(hù)士可以在5分鐘內(nèi)知道如何使用,而不需要任何文件說明。正如你可能想象的那樣,這不僅僅需要編程知識。我的目標(biāo)實(shí)現(xiàn)了,解決方案最終只需大約30秒就能學(xué)會(huì)使用。

編程常常與計(jì)算機(jī)科學(xué)混為一談。雖然很多計(jì)算機(jī)科學(xué)家都會(huì)編程,但大多數(shù)程序員并不是計(jì)算機(jī)科學(xué)家。計(jì)算機(jī)科學(xué)是研究計(jì)算的學(xué)科。計(jì)算機(jī)科學(xué)的研究成果被工程師和程序員所使用。

編碼、編程、工程和計(jì)算機(jī)科學(xué)是相互獨(dú)立但又相互關(guān)聯(lián)的學(xué)科,它們所需的知識類型和數(shù)量不同。做一名計(jì)算機(jī)科學(xué)家、工程師或編碼員并不會(huì)自動(dòng)成為一名優(yōu)秀的程序員。雖然這本書能讓你了解到工程師和計(jì)算機(jī)科學(xué)家的思維方式,但它并不能讓你躋身其中,躋身其中通常還需要獲得大學(xué)教育和一些通過勤奮得來的相關(guān)經(jīng)驗(yàn)。工程和編程類似于音樂或繪畫,它們既是技能,也是藝術(shù)。本書里這兩方面的論述應(yīng)該能幫助你提高程序員的技能。

計(jì)算機(jī)全景圖

計(jì)算機(jī)設(shè)計(jì)和編程是一個(gè)巨大的學(xué)術(shù)領(lǐng)域,這里就不再贅述了。你可以像圖1展示的那樣分層想象計(jì)算機(jī)的結(jié)構(gòu)。

圖1 計(jì)算機(jī)全景圖

請記住,圖1是簡化后的結(jié)果,在實(shí)際中,各層之間界限并沒有這么清晰明顯。

大多數(shù)人都是計(jì)算機(jī)系統(tǒng)的用戶。你現(xiàn)在可能就屬于這個(gè)陣營。有一類專門的特殊用戶叫作系統(tǒng)管理員,他們的工作是保持計(jì)算機(jī)系統(tǒng)正常工作。他們需要安裝軟件,管理用戶賬戶,做備份等。他們通常擁有普通用戶沒有的特殊權(quán)力。

編寫網(wǎng)頁、手機(jī)應(yīng)用程序、音樂播放器等程序的人被稱為應(yīng)用程序程序員。他們使用其他人創(chuàng)建的塊來編寫軟件,讓用戶通過這些軟件與計(jì)算機(jī)交互。在大多數(shù)的“學(xué)習(xí)編程”課程中,應(yīng)用程序設(shè)計(jì)中被認(rèn)為需要程序員掌握的就是如何導(dǎo)入這些塊并將其黏合在一起。雖然很多時(shí)候你都可以這樣做,但能真正理解這些塊和“膠水”會(huì)更好。

應(yīng)用程序不會(huì)直接與計(jì)算機(jī)硬件交流,這就需要系統(tǒng)程序設(shè)計(jì)來處理。系統(tǒng)程序員做的是構(gòu)建應(yīng)用程序程序員要使用的塊。系統(tǒng)程序員需要了解硬件,因?yàn)樗麄兊拇a需要與硬件進(jìn)行交互。本書的目標(biāo)之一就是教你成為優(yōu)秀的系統(tǒng)程序員需要知道的東西。

計(jì)算機(jī)硬件不僅包括進(jìn)行實(shí)際計(jì)算的部分,還包括該計(jì)算部分與外部的連接方式。計(jì)算機(jī)硬件是用邏輯表示的,該邏輯和編寫計(jì)算機(jī)程序的邏輯是一樣的,也是理解計(jì)算機(jī)工作原理的關(guān)鍵。邏輯在物質(zhì)上的實(shí)現(xiàn)是各種電子電路。電路設(shè)計(jì)不在本書討論的范圍內(nèi),你可以通過學(xué)習(xí)電氣工程專業(yè)來了解更多的電路設(shè)計(jì)知識。如果你想征服世界,可以考慮修電氣工程和計(jì)算機(jī)科學(xué)的雙學(xué)位!

當(dāng)然,支撐著這一切的是基礎(chǔ)科學(xué),它們提供從我們對電學(xué)的理解到創(chuàng)造芯片所需的化學(xué)知識等各種知識。

如圖1所示,每一層都是在其下面一層上建立起來的。這意味著下層的不佳設(shè)計(jì)選擇或錯(cuò)誤會(huì)影響到上面的所有層。例如,大約在1994年,Intel Pentium處理器中的一個(gè)設(shè)計(jì)錯(cuò)誤導(dǎo)致一些除法運(yùn)算產(chǎn)生了不正確的結(jié)果,影響了所有在這些處理器中使用浮點(diǎn)除法的軟件。

正如你所看到的,系統(tǒng)程序設(shè)計(jì)處于軟件結(jié)構(gòu)層的底層。它類似于基礎(chǔ)設(shè)施,如公路、電力和水。能不能成為一個(gè)優(yōu)秀的程序員總是很重要,但如果你是系統(tǒng)程序員,那就更重要了,因?yàn)槠渌硕家蕾嚹愕幕A(chǔ)設(shè)施。你也可以看到,系統(tǒng)程序設(shè)計(jì)夾在應(yīng)用程序設(shè)計(jì)和計(jì)算機(jī)硬件之間,這意味著你需要學(xué)習(xí)這兩方面的知識。梵語yoga的意思是“聯(lián)合”,就像瑜伽修行者追求身心合一一樣,系統(tǒng)程序員也是技術(shù)型的瑜伽師,他們需要將硬件和軟件結(jié)合統(tǒng)一起來。

你不一定要學(xué)會(huì)系統(tǒng)程序設(shè)計(jì),才能從事其他層上的工作。如果你不懂,你可以找別人幫你處理超出你擅長的領(lǐng)域的問題,不要自己想辦法。當(dāng)然對核心技術(shù)的理解會(huì)讓你在更高的層上給出更好的解決方案。這不只是我的觀點(diǎn),2014年Ville-Matias Heikkil?的博客文章“The Resource Leak Bug of Our Civilization”中也有類似的觀點(diǎn)。

本書的目的是涵蓋大量的歷史知識。因?yàn)橛刑鄡?nèi)容要學(xué)習(xí),所以大多數(shù)程序員并沒有時(shí)間或精力去學(xué)習(xí)關(guān)于技術(shù)的發(fā)展史。結(jié)果就是很多人還在犯別人曾經(jīng)犯過的錯(cuò)誤。知道一些歷史,至少可以讓你只犯些新的有意義的錯(cuò)誤,而不是重復(fù)過去的錯(cuò)誤。牢記,你今天使用的熱門新技術(shù)很快就會(huì)變成明天的歷史。

說到歷史,本書不僅給出了很多有趣的技術(shù),還介紹了其發(fā)明者。建議大家花點(diǎn)時(shí)間去了解一下這些技術(shù)和人物。本書中提到的大多數(shù)人都至少解決了一個(gè)有趣的問題,他們?nèi)绾慰创约旱氖澜纾约八麄儗Υ龁栴}和解決問題的方式,都是值得學(xué)習(xí)的。Neal Stephenson 2008年出版的小說Anathem中有一段很精彩的對話:

“我們的對手是一艘裝滿原子彈的外星飛船。我們有一個(gè)量角器。”

“好吧,我回家看看能不能找一把尺子和一根繩子。”

要注意對基本面的依賴。這不是“讓我們在維基百科上查一下該怎么做”,也不是“我在Stack Overflow上發(fā)個(gè)問題”或者“我在GitHub上找一些項(xiàng)目包”。學(xué)會(huì)解決別人沒有解決過的問題是一個(gè)重要的技能。

本書中的許多例子都是基于舊技術(shù)的,比如16位計(jì)算機(jī)。這是因?yàn)槟憧梢詮乃鼈兩砩蠈W(xué)到幾乎所有你需要知道的東西,而且它們更容易在紙上表達(dá)。

本書涵蓋內(nèi)容

本書在概念上分為三個(gè)部分。第一部分探討計(jì)算機(jī)硬件,包括它是什么以及它是如何構(gòu)建的。第二部分研究在硬件上運(yùn)行的軟件的行為和表現(xiàn)。最后一部分介紹編程的藝術(shù)——與他人合作寫出好的程序。

第1章:計(jì)算機(jī)的內(nèi)部語言

本章將開始探索計(jì)算機(jī)這個(gè)三歲小孩的心態(tài)。計(jì)算機(jī)是比特大玩家,它們靠“放牧”比特為生。本章將具體介紹它們是什么,可以用它們做什么,用像“過家家”一樣的假想游戲來賦予比特和比特集合意義。

第2章:組合邏輯

本章將研究使用比特而不是數(shù)字的原理,并探討數(shù)字計(jì)算機(jī)的合理性,還將討論一些為我們現(xiàn)在的數(shù)字計(jì)算機(jī)出現(xiàn)鋪平道路的舊技術(shù)。本章涵蓋組合邏輯的基礎(chǔ)知識,并介紹如何從位和邏輯實(shí)現(xiàn)更復(fù)雜的功能。

第3章:時(shí)序邏輯

本章將介紹如何使用邏輯構(gòu)建內(nèi)存,包括如何生成時(shí)間,因?yàn)閮?nèi)存只不過是一種隨時(shí)間而存在的狀態(tài)。本章涵蓋時(shí)序邏輯的基礎(chǔ)知識,并討論各種存儲器技術(shù)。

第4章:計(jì)算機(jī)剖析

本章將介紹計(jì)算機(jī)如何由前面幾章討論的邏輯和內(nèi)存元素構(gòu)造出來,并介紹一些不同的實(shí)現(xiàn)方法。

第5章:計(jì)算機(jī)架構(gòu)

本章將探討我們在第4章中看到的計(jì)算機(jī)的基礎(chǔ)附加組件,介紹它們?nèi)绾翁峁┗竟δ懿⑻岣咝省?/p>

第6章:通信故障

計(jì)算機(jī)需要與外部世界進(jìn)行交互。本章將介紹輸入和輸出,回顧數(shù)字量和模擬量的區(qū)別,以及如何讓數(shù)字計(jì)算機(jī)在模擬世界中工作。

第7章:組織數(shù)據(jù)

了解了計(jì)算機(jī)的工作原理后,我們來看看如何高效地使用它們。計(jì)算機(jī)程序?qū)?nèi)存中的數(shù)據(jù)進(jìn)行操作,重要的是將內(nèi)存的使用方式映射到需要解決的問題上。

第8章:語言處理

編程語言的發(fā)明是為了讓人們更容易地在計(jì)算機(jī)上寫出程序。本章著眼于將語言轉(zhuǎn)換成在計(jì)算機(jī)上實(shí)際運(yùn)行的程序的過程。

第9章:Web瀏覽器

很多程序都是為Web瀏覽器寫的。本章主要介紹Web瀏覽器的工作原理以及它的主要組件。

第10章:應(yīng)用程序和系統(tǒng)程序設(shè)計(jì)

本章將編寫一個(gè)程序的兩個(gè)版本,分別在圖1中的兩個(gè)不同的層上運(yùn)行。

第11章:捷徑和近似法

提高程序的效率很重要。本章將探討一些通過省去不必要的工作來讓程序更有效率的方法。

第12章:死鎖和競態(tài)條件

許多系統(tǒng)包含不止一個(gè)計(jì)算機(jī)。本章將研究讓計(jì)算機(jī)相互合作時(shí)可能會(huì)出現(xiàn)的一些問題。

第13章:安全性

計(jì)算機(jī)安全是一個(gè)先進(jìn)主題。本章在講解基礎(chǔ)知識的同時(shí),還會(huì)著重講解難消化的數(shù)學(xué)知識。

第14章:機(jī)器智能

機(jī)器智能也是一個(gè)先進(jìn)主題。大數(shù)據(jù)、人工智能和機(jī)器學(xué)習(xí)的結(jié)合帶來全新的應(yīng)用——從自動(dòng)駕駛到把你逼瘋的廣告。

第15章:現(xiàn)實(shí)世界的考慮

編程是一個(gè)非常有條理的過程,邏輯性很強(qiáng)。人類會(huì)參與決定編什么、如何編程,而人類往往缺乏邏輯性。本章將討論現(xiàn)實(shí)世界中關(guān)于編程的一些問題。

在閱讀本書時(shí),請記住,很多解釋都是已簡化的,因此細(xì)究細(xì)節(jié)可能不完全正確。要解釋得完美,就需要太多分散注意力的細(xì)節(jié)。如果你在深入學(xué)習(xí)的過程中發(fā)現(xiàn)了這一點(diǎn),請不要驚訝。你可以把這本書看成是一本可以讓你在計(jì)算機(jī)的太虛世界里神奇遨游的光鮮亮麗的旅行手冊。本書不可能涵蓋所有的細(xì)節(jié),當(dāng)你深入閱讀時(shí),就會(huì)發(fā)現(xiàn)很多細(xì)微的差別。

主站蜘蛛池模板: 宝应县| 乳山市| 深泽县| 石首市| 嘉禾县| 登封市| 蚌埠市| 普陀区| 大厂| 砚山县| 北碚区| 福清市| 黎城县| 新河县| 延川县| 区。| 错那县| 沾化县| 南华县| 凌海市| 桃园市| 兴文县| 景德镇市| 甘肃省| 饶河县| 伽师县| 高邮市| 宜川县| 大化| 长岛县| 奉节县| 水富县| 西乌| 临沧市| 望江县| 灌阳县| 城口县| 太仓市| 普兰县| 拜城县| 固阳县|