程序員要掌握的知識,要具備的能力實(shí)在太多,多得頭發(fā)都不夠掉聂儒。
大體有兩大方向色难。一是對工具的熟練掌握,如操作系統(tǒng)贞绵、網(wǎng)絡(luò)、IO、編程語言等橘券;另一個是用代碼為現(xiàn)實(shí)問題生成解決方案的能力,這其中最重要的是抽象能力。
前一個方向是很容易意識到的约郁,很多現(xiàn)象可以說明這一點(diǎn)缩挑,比如,世面上介紹如何使用語言鬓梅、框架的書汗牛充棟供置;比如,很多人眼里進(jìn)這一行的門檻是上1個月的語言培訓(xùn)課绽快。
工具的意義不容否認(rèn)芥丧,為此我還寫過一篇《工具優(yōu)先》。但工具的生命周期其實(shí)很短坊罢,從個人發(fā)展角度看续担,把過多時間投入到半衰期很短的事物上,并不劃算活孩。我入門時接觸的是Pascal, BasicScript, ASP, IIS物遇,不知道現(xiàn)在還有沒有人用這些。很多程序員也趕時髦憾儒,本來寫java的询兴,golang流行了,python流行了起趾,學(xué)诗舰!本來搞業(yè)務(wù)開發(fā)的,大數(shù)據(jù)火了训裆,機(jī)器學(xué)習(xí)火了眶根,學(xué)!打的旗號自然很鮮明:持續(xù)學(xué)習(xí)边琉。幾次之后属百,卻悵然若失,貌似沒一個是拿得出手的艺骂,不過是低水平重復(fù)诸老,換個工具,繼續(xù)做原來的事而已钳恕。充其量效率提高了别伏,但效率型工作是可替代性最強(qiáng)的,被其它人替代忧额,被機(jī)器替代厘肮。
一顆上進(jìn)愛學(xué)習(xí)的心,怎么就被辜負(fù)了呢睦番?因?yàn)楹诵哪芰]有提升类茂。人的能力好比電子圍繞原子核旋轉(zhuǎn)耍属,大部分情況下處于巡航狀態(tài),在這過程中不斷積蓄能量巩检,始終向核心方向用力厚骗,就會躍遷到更高級軌道(這里指更靠近核心的軌道,實(shí)際電子是更遠(yuǎn)離核心的道)兢哭×旖ⅲ“一萬小時理論”和“10萬行代碼理論”只片面強(qiáng)調(diào)了量,如果沒有聚焦核心迟螺,刻意練習(xí)冲秽,只能是低水平重復(fù),甚至軌道降級矩父。
核心是抽象能力锉桑。這個世界的運(yùn)行,有講邏輯的窍株,也有不講邏輯的民轴。程序員要處理的事是講邏輯的那部分,因?yàn)槟闼蕾嚨挠嬎銠C(jī)是講邏輯的夹姥,要讓它意氣用事杉武,感情用情,目前還很困難辙售。通過抽象,我們識別并保留邏輯部分飞涂,拋棄其它內(nèi)容旦部,然后用計算機(jī)語言翻譯、實(shí)現(xiàn)這個邏輯较店,進(jìn)而解決問題士八。
抽象這個詞,本身就挺抽象的梁呈。到底什么是抽象婚度?
抽象是去除多余和細(xì)節(jié)。比如下面這個標(biāo)志官卡,一看就懂是座拱橋蝗茁,但并沒有顯示拱橋的幅度、寬度和長度寻咒,因?yàn)檫@些數(shù)據(jù)對于你意識到這是一座拱橋并沒有幫助哮翘。
什么是多余信息,取決于目的毛秘》顾拢考慮地鐵換乘圖阻课,其目的是告訴乘客該搭哪條線,在哪里換乘艰匙,所以保留了結(jié)構(gòu)關(guān)系:站點(diǎn)的分布限煞,以及線路的匯合點(diǎn),但忽略了物理關(guān)系:站點(diǎn)的地理位置员凝、相對距離署驻,甚至扭曲了線路的方向。而如果是開車用的導(dǎo)航圖绊序,則必須保證比例尺和實(shí)際情況一致硕舆,方向也不能有差錯,以免誤導(dǎo)骤公。
抽象是建立模板或藍(lán)圖抚官。不少公司里有郵件模板、文檔模板阶捆、PPT模板凌节、報銷單模板,等等洒试,它們規(guī)定好了結(jié)構(gòu)倍奢、風(fēng)格,并留出一個個空白垒棋,使用的時候填空就好卒煞。模板描述不變的內(nèi)容,變量則延遲到使用場景中確定叼架。Java編程時畔裕,經(jīng)常要應(yīng)用各種設(shè)計模式,其實(shí)質(zhì)是通過抽象乖订,固化不變的扮饶,封裝變化的。比如乍构,很常用的模板方法甜无,流程和步驟無論什么場景都不變,已經(jīng)在父類寫好了哥遮,將具體場景的方法在父類里聲明岂丘,但延遲到子類實(shí)現(xiàn),封裝的是方法實(shí)現(xiàn)昔善。又比如元潘,創(chuàng)建對象時,不常寫new Tesla()君仆,而是運(yùn)用簡單工廠模式翩概,寫成TeslaFactory.create()牲距,因?yàn)閷ο蟮膭?chuàng)建是易變的。與其在特斯拉多一個型號時钥庇,把所有new的地方都改一遍牍鞠,不如在create方法里集中改。
總之评姨,抽象是應(yīng)對變化难述,或者說尋找不變性的手段。既可以是不同事物之間的不變性吐句,也可以是同一事物不同歷史時間的不變性胁后。雖然這里講的是編程,但其應(yīng)用遠(yuǎn)不止于此嗦枢,看看貝索斯是怎么說的:
我常被問一個問題:“在接下來的10年里攀芯,會有什么樣的變化?”……但我很少被問到“在接下來的10年里,什么是不變的?”我認(rèn)為第二個問題比第一個問題更加重要文虏,因?yàn)槟阈枰獙⒛愕膽?zhàn)略建立在不變的事物上侣诺。
有了上面的解釋,便不難理解面向?qū)ο缶幊痰脑瓌t:依賴接口而不是實(shí)現(xiàn)氧秘,依賴抽象類而不是具體類年鸳。它讓代碼的適應(yīng)性更強(qiáng),將來少改代碼丸相,少出錯搔确。同時,做一些參數(shù)設(shè)定時灭忠,更加有理有據(jù)妥箕,而不是trial and error。線程池大小怎么定更舞?不用關(guān)心具體工作,分析阻塞和非阻塞的時間比例坎吻,應(yīng)用Amdahl’s law搞定缆蝉。隊列大小怎么定?不管究竟放的是什么瘦真,確定你期望的排隊時長刊头,用Little’s law算下。
世面上鮮有講如何培養(yǎng)抽象思維的書诸尽,設(shè)計模式一類的原杂,算搭一點(diǎn)邊,但那是人家抽象的結(jié)果您机,而不是關(guān)于抽象的方法穿肄。也許我們在運(yùn)用這些模式年局,或?yàn)g覽一些工具和類庫的代碼過程中,偶有靈光一現(xiàn)咸产,能從這些結(jié)果中反推作者的設(shè)計思想和精妙之處矢否,畢竟它們也是抽象的結(jié)果。
學(xué)習(xí)使用工具時脑溢,如果多個心眼僵朗,留意為什么有這個工具,做了什么取舍屑彻,工具于你將不僅是效率意義验庙。做業(yè)務(wù)開發(fā)時,如果不是簡單地翻譯需求社牲,多想一層粪薛,哪里易變,哪里不易變膳沽,如何隔離變化汗菜,再簡單的開發(fā),于你也有精進(jìn)意義挑社。
抽象的層級可以有很多陨界,能做多少層級的抽象是一種能力,而判斷需要多少層級的抽象則是一種藝術(shù)痛阻。
地上一個猴菌瘪,樹上七個猴,一共有幾個猴阱当?1+7=8俏扩,一共八個猴,用數(shù)字符號代替猴子弊添,這是第一層录淡。從對象到數(shù)字,大多數(shù)人對此熟悉到甚至沒有意識到這是一種抽象油坝。再進(jìn)一層嫉戚,則有些困難了,當(dāng)初我理解“加速度”這個概念澈圈,就費(fèi)功彬檀。不光是數(shù)量,還有結(jié)構(gòu)的抽象瞬女,關(guān)系的抽象窍帝。當(dāng)然,它們離我們都很遠(yuǎn)……
可是诽偷,真的很遠(yuǎn)嗎坤学?當(dāng)大部分人在關(guān)心如何寫程序時疯坤,有人開始研究如何用程序?qū)懗绦颍?dāng)大部分人在關(guān)心如何看書拥峦、學(xué)習(xí)時贴膘,有人在教別人看書、學(xué)習(xí)略号。