女兒問了我一個問題:什么是抽象?
晚上吃飯的時候,有人提到了“抽象”這個詞,孩子的好奇心是最強的,我女兒立刻就問我:“爸爸,什么是抽象?”
剎那間我的腦海中涌過了很多畫面:
頭腦特工隊的電影
牛頓的萬有引力公式
三個代表
k8s的pod, rs, service
設計模式
接口和抽象類
......
這些她都聽不懂,于是我決定用一個簡單的例子來敷衍她:
“我先給你一個蘋果,然后又給了你一個蘋果,你現在有幾個蘋果?”
“兩個”
“我先給你一根香蕉,然后又給你了一根香蕉,你現在有幾根香蕉?”
“兩根”
“1 + 1 等于幾?”
“2”
“對,1+1 = 2就是抽象,知道了吧。”
她點點頭。
"將來你還會學代數,x+y = z,那是更高級的抽象......”
她似懂非懂地點點頭,眼神中充滿了迷茫。
回到正題吧,我今天想給大家分享的是下面這幅圖以及由它引發的感想。
這幅圖來自于《深入理解計算機系統》, 我第一次看到它時候可以說是拍案叫絕,畫得實在是太棒了。
1
對程序員來講,我們并不是直接面向硬件進行編程的,因為硬件細節實在是太復雜了,所以必須要做封裝和抽象。
比如說你要是想針對CPU這個硬件來編程, 這實在是太難了。
但是如果我們把CPU抽象為指令集,其中無非就是一些 MOV 指令,ADD指令, JUMP指令,那難度一下子就降低了一個數量級。
有了指令集,以及依托于指令集的匯編就夠了嗎?遠遠不夠!因為匯編語言還是非常低級,需要直接操作CPU的寄存器和內存,如果一直用匯編語言編程,我估計現在的程序員數量要減少90%以上。
所以C語言,Pascal,C++出現了,Java,Python, Ruby出現了,用這些語言編程,根本不用考慮寄存器的事情,程序員離物理機器越來越遠,和硬件打交道的事情都交給了編譯器和解釋器。
有時候,有了高級語言還不夠,為了更加貼近業務領域,甚至讓業務人員直接編程,程序員還會創建領域特定語言(DSL)。
2
硬盤在沒有抽象的情況下,我們看到的就是盤面,磁道,扇區這樣的底層概念, 你要是想在上面寫點兒東西,或者讀取一點兒東西,可就要累死了。
可以先做一點簡單的抽象,隱藏磁道扇區這樣的概念,讓磁盤變成邏輯上按順序編號的磁盤塊,即磁盤塊1、磁盤塊2、磁盤塊3......這就好多了,但使用起來依然非常低級。
于是操作系統給我們提供了一個漂亮的抽象,文件!你只需要打開文件,寫入數據,關閉文件即可,根本不用考慮底層的概念。
更重要的是,在Linux/Unix中,一切都是文件,可以用統一的接口來處理,這就更漂亮了。
3
文件是個非常好的抽象,可是對于商業應用來講,它關注的是業務概念,是用戶名,電子郵箱,地址,部門,賬戶,存款,取款,余額等等,在這種場景下,文件就變得太低級了。
所以數據庫出現了,把文件這個概念也隱藏了,對于關系數據庫來說,你面對的就是一個個邏輯上表格,你只要發出SQL語句就可以存取數據,并且還能保證ACID的特性,根本不用考慮底層的實現細節, 用起來就更加舒服了。
4
前面說的這些抽象,看起來似乎是分層的:
在日常的編程中,我們經常做的一件事情就是“數據抽象”,或者說找出抽象數據類型(ADT),在Java中就是抽象類或者接口。比如說List就是一個ADT,它的實現可以是ArrayList,可以是LinkedList。
ADT的特點就是穩定,很少變化,在項目和產品的開發中,一個非常重要的工作就是定義自己項目的ADT(以及ADT之間的關系),ADT一旦確定,那這個項目的骨架基本上就定下來了。
但是這個ADT不好找,有時候可以直接和業務概念對應上,有時候需要自己“造”一些概念出來,這就考驗開發人員的抽象能力了。
軟件業發展到今天,就是一部不斷抽象的歷史。抽象降低了復雜度,是一件非常好的事情,但是現在很多程序員日常的工作就是針對抽象的概念進行編程,由于很多細節被屏蔽,工作就顯得比較無趣,如果想讓自己的編程生涯變得有趣一點,我有兩點建議:
一、要了解這些抽象下面是什么東西。
二、努力爭取到創建抽象的權力,即設計的權力和架構的權力。
【本文為51CTO專欄作者“劉欣”的原創稿件,轉載請通過作者微信公眾號coderising獲取授權】