如果要問計算機領(lǐng)域中哪個思想對我的幫助最大,那么應(yīng)該就是抽象了。本文主要介紹一下抽象(abstraction)以及它和計算機課程的關(guān)系婉弹。
第一次接觸抽象是我大學(xué)低年級學(xué)數(shù)據(jù)結(jié)構(gòu)的時候屑埋,記得很清楚當(dāng)時學(xué)一個概念叫抽象數(shù)據(jù)類型(abstract data type),大概意思就是一個數(shù)據(jù)結(jié)構(gòu)愚墓,接口是一回事,實現(xiàn)是另一回事昂勉,比如棧浪册,作為使用者你只需要知道它有push、pop岗照、isEmpty等方法村象,但它的底層實現(xiàn)到底是array還是linked list笆环,你是不需要知道的。
用通俗一點的話說厚者,抽象就是你好好做自己的事躁劣,以及知道別人能幫你干什么事,至于別人是如何幫你完成的库菲,你沒必要知道账忘。
這個簡單的思想大大提高了開發(fā)者的效率,讓開發(fā)者只專注于要解決的問題蝙昙,而不是一些細枝末節(jié)的事闪萄。
孟巖在它的博客里也提到過“關(guān)注重點”這件事,雖然沒有明顯地提及抽象二字奇颠,但他的意思和抽象表達的意思是一樣的:
我主張败去,在具備基礎(chǔ)之后,學(xué)習(xí)任何新東西烈拒,都要抓住主線圆裕,突出重點。對于關(guān)鍵理論的學(xué)習(xí)荆几,要集中精力吓妆,速戰(zhàn)速決。而旁枝末節(jié)和非本質(zhì)性的知識內(nèi)容吨铸,完全可以留給實踐去零敲碎打行拢。
原因是這樣的,任何一個高級的知識內(nèi)容诞吱,其中都只有一小部分是有思想創(chuàng)新舟奠、有重大影響的,而其它很多東西都是瑣碎的房维、非本質(zhì)的沼瘫。因此,集中學(xué)習(xí)時必須把握住真正重要那部分咙俩,把其它東西留給實踐耿戚。對于重點知識,只有集中學(xué)習(xí)其理論阿趁,才能確保體系性膜蛔、連貫性、正確性脖阵,而對于那些旁枝末節(jié)飞几,只有邊干邊學(xué)能夠讓你了解它們的真實價值是大是小,才能讓你留下更生動的印象独撇。如果你把精力用錯了地方屑墨,比如用集中大塊的時間來學(xué)習(xí)那些本來只需要查查手冊就可以明白的小技巧,而對于真正重要的纷铣、思想性東西放在平時零敲碎打卵史,那么肯定是事倍功半,甚至適得其反搜立。
最近發(fā)現(xiàn)以躯,計算機專業(yè)的課程完全可以用抽象來解釋:每一門課想做的事就是利用下層提供的接口,實現(xiàn)功能啄踊,然后再給上層提供接口忧设。這樣一層一層的抽象就構(gòu)成了所有的專業(yè)課。
舉一個例子來說明這個從上往下的層級抽象是如何組織的颠通。
先來看最高層址晕,問題。剛學(xué)編程的時候顿锰,會先學(xué)一門課導(dǎo)論課或者編程入門課谨垃,我當(dāng)時的入門課叫做“程序設(shè)計”,課程內(nèi)容是介紹一些問題硼控,然后介紹一點編程語言的知識刘陶,作業(yè)是一些編程問題,比如八皇后牢撼、素性測試之類的比較常規(guī)的編程題匙隔。這門課的目的一般都是介紹“問題”的,介紹不用分支科學(xué)有哪些有挑戰(zhàn)的問題熏版,讓學(xué)生對計算機專業(yè)有一個感性的認(rèn)識纷责,而不是對特定編程語言或者算法的學(xué)習(xí),所以這類課程一般用python來編程纳决。
再往下一層碰逸,算法和數(shù)據(jù)結(jié)構(gòu)。這一層的目的是學(xué)習(xí)/實現(xiàn)各種算法/數(shù)據(jù)結(jié)構(gòu)阔加,提供給上層抽象饵史。比如排序,問題解決者只要知道這里應(yīng)該用快速排序胜榔,而不是選擇排序胳喷,而把快速排序的實現(xiàn)留給這一層的開發(fā)者,從而使各種優(yōu)化都可以對上層透明夭织,比如小數(shù)組變插入排序吭露、中位數(shù)取pivot、三向快速排序等尊惰,這些優(yōu)化調(diào)用者完全不必要知道讲竿,他只需要知道:哇泥兰,這個庫提供的快速排序還真快。
再往下一層题禀,語言層鞋诗,畢竟所有算法都要由某一門語言來實現(xiàn)轻庆。這一層的存在使得算法的設(shè)計可以脫離具體的語言象对。不同語言又提供了不同的抽象,像函數(shù)式語言就比命令式語言的抽象級高忧风,更高的抽象級意味著更加專注問題本身(不需要考慮內(nèi)存布局秀仲、CPU使用等)以及更少的代碼量融痛。
再往下一層,編譯器/解釋器神僵。我們編寫代碼是用高級語言雁刷,而cpu上執(zhí)行的是機器碼,所以這個抽象層幫我們做了這個轉(zhuǎn)化挑豌。這個抽象層的好處是安券,高級代碼的編寫者完全不需要知道這個程序所運行的操作系統(tǒng)和硬件平臺,任何有該語言編譯器/解釋器的機器氓英,程序都可以跑(從而實現(xiàn)了跨平臺)侯勉。有這一層的好處是,應(yīng)用層開發(fā)者可以不用知道這個由高級語言到機器碼的轉(zhuǎn)化具體是怎么實現(xiàn)的铝阐,畢竟編譯器優(yōu)化的編寫和優(yōu)化完全是一個團隊的工作量址貌,開發(fā)者關(guān)注問題的解決,編譯器負(fù)責(zé)轉(zhuǎn)化出高效的機器碼徘键,各干各的练对,這正是抽象的重點。
再往下一層吹害,操作系統(tǒng)螟凭。OS向開發(fā)者抽象了硬件(CPU、內(nèi)存它呀、Disk螺男、NIC等),并且以syscall的形式向用戶提供服務(wù)纵穿。OS的設(shè)計是最能體現(xiàn)抽象的下隧,虛擬內(nèi)存和進程讓程序以為自己獨占著內(nèi)存和CPU,同時隔離了不同進程以防惡意進程谓媒;文件系統(tǒng)讓用戶可以方便地讀取存儲數(shù)據(jù)淆院,而不需要直接操作底層的硬盤;文件描述符抽象了底層的設(shè)備(pipe句惯?file土辩?device支救?socket?)拷淘。
再往下一層搂妻,ISA(Instruction set architecture),俗稱軟件與硬件的接口辕棚。這個俗稱是非常形象的。指令集架構(gòu)邓厕,說得簡單點就是機器碼逝嚎,也可以理解為一個協(xié)議。ISA標(biāo)準(zhǔn)制定者指定一套指令集(比如x86详恼、PowerPC补君、SPARC),然后編譯器開發(fā)者需要根據(jù)這個標(biāo)準(zhǔn)/協(xié)議來編寫對應(yīng)的編譯器昧互;CPU制造商需要根據(jù)這個標(biāo)準(zhǔn)/協(xié)議來制造出支持這套ISA的CPU(比如intel的CPU支持x86/x86_64)挽铁。也就是說,軟件/硬件都依照這個ISA來設(shè)計敞掘,那么就可以對接了叽掘。
再往下一層,組成原理和體系結(jié)構(gòu)玖雁。這一層要做的事情是借助數(shù)字電路給它提供的抽象(組合電路和鎖存器)更扁,來設(shè)計一個能實現(xiàn)某種ISA的CPU,讓編譯器生成的指令可以在此CPU上運行赫冬。大學(xué)里一般會開一門叫“計算機組成原理”的課浓镜,一開始學(xué)單周期CPU的實現(xiàn)(取指、譯碼劲厌、執(zhí)行......)膛薛,為了提高效率又提出了流水線的實現(xiàn)。為了發(fā)掘更高的效率补鼻,之后又會學(xué)一門叫“計算機體系結(jié)構(gòu)”的課哄啄,這門課的目的是為了發(fā)掘更高的并行,從而制造出更快的CPU辽幌。那這一層是如何用數(shù)字電路提供的抽象的增淹?舉兩個典型例子:一、CPU為了做計算會有ALU模塊乌企,而ALU模塊正是一個組合電路(輸入確定那么輸出確定)虑润;二、在流水線寄存器中每一個時鐘上升沿都會保存輸入的值加酵,在這個時鐘周期內(nèi)組合電路會根據(jù)這個新值計算出結(jié)果傳輸?shù)较乱患壛魉€寄存器的輸入拳喻,等待下一個時鐘上升沿的到來哭当,這里的流水線寄存器正是某種鎖存器的實現(xiàn),而CPU開發(fā)者并不需要這個數(shù)字電路模塊是怎么實現(xiàn)冗澈。
再往下一層钦勘,數(shù)字電路。這門課的目的是教學(xué)生如何利用基本的門電路(與非或門)來實現(xiàn)一些高級的功能(譯碼器亚亲、多路復(fù)用器彻采、鎖存器、時序電路......)捌归,然后給上層提供功能肛响。上數(shù)字電路是一個用磚搭房子的過程,由基本的門電路開始惜索,慢慢構(gòu)造出復(fù)雜的電路特笋。數(shù)字電路不需要關(guān)心基本的門電路是如何實現(xiàn)的,因為這正是模擬電路向上層提供的抽象巾兆。
再往下一層猎物,模擬電路。這一層實現(xiàn)了與或非等基本門電路角塑。比如非門蔫磨、與非門、或非門都可以通過若干個p/n型MOS晶體管構(gòu)成吉拳,而與門可以通過連接一個與非門和非門構(gòu)成质帅,或門可以通過連接一個或非門和非門構(gòu)成。很多同學(xué)都覺得模電對于計算機的同學(xué)不必要學(xué)留攒,而我認(rèn)為相反煤惩,它是你構(gòu)建整個計算機抽象層級的基石。
再往下一層炼邀,就不是計算機領(lǐng)域研究的事了魄揉。
當(dāng)然,還有很多專業(yè)課我并沒有提及拭宁,比如網(wǎng)絡(luò)洛退,它是OS提供的功能,以文件描述符的形式提供給用戶使用杰标;在網(wǎng)絡(luò)協(xié)議棧實現(xiàn)的細節(jié)里兵怯,又分了好幾層抽象,這就是我們熟知的OSI七層網(wǎng)絡(luò)模型(有時候被抽象為五層:Application腔剂、Transport媒区、Network、DataLink、Physical)袜漩。各位可以自己再回憶一下大學(xué)里上過哪些專業(yè)課绪爸,以及它應(yīng)該放在抽象的哪一層上。
仔細一想會發(fā)現(xiàn)宙攻,幾乎所有的技術(shù)書籍都嘗試在解決某一層上的問題奠货,利用下層提供的抽象,然后向上層提供功能座掘。
讓我們脫離計算機領(lǐng)域递惋,再往高一點看,會發(fā)現(xiàn)整個計算機領(lǐng)域就是在為別的領(lǐng)域提供功能溢陪、并隱藏了細節(jié):醫(yī)療丹墨、交通、餐飲嬉愧、支付......
抽象,讓生活變得更簡單了一點喉前。
(原文地址:http://lifeofzjs.com/blog/2016/03/06/cs-courses-and-abstraction/)