2015年大熱的動(dòng)畫(huà)片《動(dòng)腦特工隊(duì)》中描述了這么一個(gè)場(chǎng)景, 冰棒帶領(lǐng)樂(lè)樂(lè)和憂(yōu)憂(yōu)抄近路去乘坐思維列車(chē),所謂的“近路”就是穿過(guò)抽象思維的房間,在這個(gè)房間里, 他們先是變成了變成3D的塊,就像計(jì)算機(jī)圖形學(xué)里展示的那樣:
然后變成平面的圖形
最后只剩下一些線(xiàn)條了 !
真是非常生動(dòng)的展示了人類(lèi)做抽象活動(dòng)的過(guò)程。
在軟件業(yè),抽象能力的重要性怎么說(shuō)都不為過(guò),因?yàn)檐浖_(kāi)發(fā)是一個(gè)高度復(fù)雜的智力活動(dòng),程序員經(jīng)常需要面對(duì)、處理異常復(fù)雜的業(yè)務(wù)和邏輯,如果你不具備強(qiáng)大的抽象能力,無(wú)法把具體變成概念,進(jìn)而駕馭概念進(jìn)行思考, 你就很難降低問(wèn)題的復(fù)雜度,從而陷入泥潭,無(wú)法自拔。
無(wú)論你學(xué)會(huì)了多么強(qiáng)大的程序語(yǔ)言,你的編程能力也很難有質(zhì)的提高。
當(dāng)然抽象不僅僅是軟件開(kāi)發(fā)的獨(dú)有概念,在別的領(lǐng)域可以看到更多,例如帝國(guó)經(jīng)常提的“三. 個(gè). 代. 表”,“和. 諧”(當(dāng)然現(xiàn)在已經(jīng)變成貶義詞了),“中. 國(guó). 夢(mèng)” ,就是把執(zhí)政理念和民眾的訴求進(jìn)行抽象,當(dāng)然實(shí)施的效果如何就留給大家評(píng)說(shuō)了。
在自然科學(xué)領(lǐng)域,抽象的例子更多,開(kāi)普勒定律和萬(wàn)有引力就是很典型的例子。
在16世紀(jì)很多人開(kāi)始相信哥白尼提出的日心說(shuō),但一直搞不清楚圍繞太陽(yáng)的行星到底是怎么運(yùn)動(dòng)的,軌道是什么樣子,著名天文學(xué)家開(kāi)普勒仔細(xì)的研究了他的老師 --杰出的觀測(cè)家--第谷留下的大量天文觀測(cè)數(shù)據(jù)以后, 提煉出了著名的開(kāi)普勒三定律, 第一次給出了天體運(yùn)行規(guī)律的解釋?zhuān)?/p>
- 所有行星分別是在大小不同的橢圓軌道上運(yùn)行
- 在同樣的時(shí)間里行星向徑在軌道平面上所掃過(guò)的面積相等
- 行星公轉(zhuǎn)周期的平方與它同太陽(yáng)距離的立方成正比
開(kāi)普勒三定律從大量的數(shù)據(jù)中提煉出數(shù)學(xué)規(guī)律, 無(wú)疑是非常偉大的發(fā)現(xiàn)和抽象, 但這不是最終本質(zhì),當(dāng)然也不是最終的抽象。
行星運(yùn)動(dòng)的本質(zhì)是萬(wàn)有引力定律。
相比于開(kāi)普勒定律,天才的牛頓所做的抽象向前邁進(jìn)了一大步,萬(wàn)有引力幾乎覆蓋了所有大質(zhì)量物體之間互相吸引和運(yùn)動(dòng)的規(guī)律, 即簡(jiǎn)單又優(yōu)美, 配合牛頓(和萊布尼茨)發(fā)明的微積分,可以很容易推導(dǎo)開(kāi)普勒定律。
如果再加上牛頓力學(xué)三定律,尤其是F=ma , 整個(gè)經(jīng)典物理學(xué)的架子就建起來(lái)了,后人所有的工作只是在這座大廈上進(jìn)行一些裝修工作,直到愛(ài)因斯坦相對(duì)論的出現(xiàn),才建立一座更宏偉的大廈。
據(jù)說(shuō)愛(ài)因斯坦在評(píng)價(jià)一個(gè)研究時(shí),會(huì)用美和丑來(lái)作為判斷標(biāo)準(zhǔn),有人拿研究成果讓愛(ài)因斯坦看, 愛(ài)因斯坦不說(shuō)成果的好與壞,反而說(shuō)“這東西多丑陋啊”, “這東西真漂亮”。
其實(shí)一個(gè)抽象的東西形式優(yōu)美,結(jié)構(gòu)簡(jiǎn)單,很有可能是正確的,很可能抓住了事物的本質(zhì)。
相反如果連形式都丑陋不堪,十有八九不是好的成果。 以此作為標(biāo)準(zhǔn),萬(wàn)有引力定律無(wú)疑是漂亮的,正確的,當(dāng)然愛(ài)因斯坦的E=mc2 更加漂亮和簡(jiǎn)單。
抽象的例子在軟件業(yè)更是數(shù)不勝數(shù):
文件是對(duì)I/O的抽象;
虛擬存儲(chǔ)器是對(duì)物理存儲(chǔ)器的抽象;
進(jìn)程是對(duì)一個(gè)正在運(yùn)行的程序的抽象;
我們?cè)僭黾右粋€(gè)新的抽象:虛擬機(jī), 他提供了對(duì)整個(gè)計(jì)算機(jī)(包括操作系統(tǒng),處理器,程序)的抽象。
Andorid 把一個(gè)移動(dòng)應(yīng)用程序抽象成Activity , Intent, Service,Provider。
......
稍微注意一下就會(huì)發(fā)現(xiàn): 抽象層次越高,接口的語(yǔ)意就越模糊,適用的范圍就越廣,到最后就會(huì)變成數(shù)學(xué)模型或者概念。
數(shù)學(xué)模型和算法
我認(rèn)為把紛雜的事物抽象到數(shù)學(xué)層面是最高的抽象,也許會(huì)有人會(huì)說(shuō)哲學(xué)層面才是:-) ,但到數(shù)學(xué)層面已經(jīng)非常難了。尤其是重大的科學(xué)發(fā)現(xiàn),身后必然有數(shù)學(xué)的影子。
牛頓當(dāng)年為了描述天體的軌道和運(yùn)動(dòng),特別創(chuàng)立了新的數(shù)學(xué)表示: 微積分
麥克斯韋使用一組方程對(duì)電場(chǎng)和磁場(chǎng)行為進(jìn)行描述。
當(dāng)年愛(ài)因斯坦腦海中已經(jīng)有了廣義相對(duì)論,但苦于找不到合適的數(shù)學(xué)形式來(lái)描述,他特別花了幾年的時(shí)間來(lái)學(xué)習(xí)非歐幾何和張量分析,最后才得以成功。
海森堡用矩陣?yán)碚搧?lái)解釋量子力學(xué)
。。。。
程序員在開(kāi)發(fā)過(guò)程中, 也許能把一個(gè)實(shí)際的業(yè)務(wù)問(wèn)題抽象成數(shù)學(xué)模型,或者抽象成特定的算法,這樣會(huì)讓程序?qū)崿F(xiàn)變得非常簡(jiǎn)單和有趣。
我在之前的公司有幸遇到過(guò)一次,把針對(duì)稅務(wù)領(lǐng)域的一個(gè)Credit, Debit等概念抽象為在一個(gè)二維坐標(biāo)下點(diǎn)的運(yùn)動(dòng), 問(wèn)題一下子簡(jiǎn)化了很多,實(shí)現(xiàn)簡(jiǎn)單,并且非常安全可靠。
正交的概念
但是抽象成數(shù)學(xué)模型和算法通常是可遇而不可求的, 這種情況下,我們需要退而求其次,試圖抽象成若干個(gè)正交的概念,來(lái)降低復(fù)雜度。
“正交”在數(shù)學(xué)上指的是線(xiàn)性無(wú)關(guān),最常見(jiàn)的例子就是坐標(biāo)系下的x 軸和y軸,對(duì)于一個(gè)點(diǎn)來(lái)講,它的x值的變化不會(huì)影響到y(tǒng), y值得變化不會(huì)影響到x ,即x和y是正交的。
正交的威力在于互不影響,擴(kuò)展方便,單用一個(gè)坐標(biāo)軸可以表示一個(gè)直線(xiàn)上的所有的點(diǎn), 再加一個(gè)y 軸就能表示平面上的所有的點(diǎn), 再加一個(gè)z軸 3維空間中的所有點(diǎn)都能表示出來(lái)了!
我們?nèi)祟?lèi)的大腦在思考問(wèn)題的時(shí)候是有容量限制的, 難以同時(shí)駕馭太多負(fù)責(zé)的概念, 如果我們的軟件系統(tǒng)也能做成x,y,z 坐標(biāo)這樣,就帶來(lái)了無(wú)與倫比的好處,你在處理x軸相關(guān)的事情時(shí),不用考慮其他的y和z 相關(guān)的東西,因?yàn)槟阒浪麄儾粫?huì)受到影響, 這樣問(wèn)題的復(fù)雜度就從3維一下子下降到1維!更容易把握了。
如果單單x 軸仍然很復(fù)雜,你要做的就是再次分解成更小的概念,保證正交即可。
接口
如果你說(shuō)了,我的整個(gè)系統(tǒng)還沒(méi)法抽象成正交的概念, 那只好再退一步,在局部使用接口。
在著名的《設(shè)計(jì)模式》一書(shū)中,其實(shí)在反復(fù)強(qiáng)調(diào)一點(diǎn): 發(fā)現(xiàn)變化并且封裝變化,針對(duì)接口編程而不是實(shí)現(xiàn)編程。 很多人看書(shū)是只關(guān)注具體的模式,而忽略了模式的本質(zhì)目的。
我們?cè)陂_(kāi)發(fā)的過(guò)程中要保持一種敏銳的感覺(jué),發(fā)現(xiàn)可能的變化并且封裝起來(lái),只提供一個(gè)精心定義的接口讓外界調(diào)用。這樣你在接口后面所做的任何變化,外邊就不受影響了。
例如在JDK中Iterator 就是一個(gè)很好的抽象, 它將集合本身和集合的遍歷分開(kāi)。 Stream 抽象也不錯(cuò),封裝了對(duì)文件和網(wǎng)絡(luò)操作,只是使用起來(lái)稍顯麻煩。
其實(shí) 一組定義良好的接口一定是正交的,不然的話(huà)接口之間的依賴(lài)就會(huì)讓實(shí)現(xiàn)非常麻煩。
總結(jié)
說(shuō)到底,軟件設(shè)計(jì)和開(kāi)發(fā)就是把現(xiàn)實(shí)中的問(wèn)題映射的計(jì)算機(jī)的語(yǔ)言實(shí)現(xiàn),但現(xiàn)實(shí)問(wèn)題太復(fù)雜,細(xì)節(jié)太多,而且在不斷的變化過(guò)程中,一般人很難同時(shí)對(duì)這么的細(xì)節(jié)進(jìn)行思考 ,這時(shí)候就需要抽象。
我們只有從紛繁復(fù)雜的現(xiàn)象中抽取事物的本質(zhì),從具體事物提煉出正交的概念,才能駕馭這些概念,才能在一個(gè)低復(fù)雜度的世界中進(jìn)行思考。
抽象能力的高低,很大程度上反映了一個(gè)程序員的能力的高低