技術的正宗與野路子
黃衫女子的武功似乎與周芷若乃是一路,飄忽靈動,變幻無方,但舉手抬足之間卻是正而不邪,如說周芷若形似鬼魅,那黃衫女子便是態擬神仙。
這段描寫出自《倚天屠龍記》第三十八回。
“九陰神抓”本是《九陰真經》中的上乘武功,但當初梅超風夫婦由于拿到的《九陰真經》不完整,學不到里面的內功心法,硬是把這門上乘武功練到了邪路上,于是就成了“九陰白骨爪”。周芷若為求速成,也練就了這門邪功。
但黃衫女子乃出身武林名門(相傳是楊過和小龍女的后人),自然修煉的是正宗的《九陰真經》。雖然武功路數與周芷若本同屬一脈,但更加“醇真深厚”,自然也更勝一籌。這是金庸武俠中“正宗”武功勝過“野路子”的一個典型案例。
那么,這是否能夠說明,“正宗”一定強于“野路子”呢?
且慢!
喜歡金庸武俠的朋友,可還記得《越女劍》中的阿青?
阿青本是一名牧羊女,卻在牧羊時巧遇一頭會使竹棒的白猿。在與白猿的玩耍嬉鬧中,她硬是悟得了高超的劍法,竟能以一人之力敵兩千越甲!
就是這樣一個從野路子練出來的柔弱女子,即使按廣大金庸迷的保守估計,她也能在整個金庸武俠圖譜中至少排名前五!
做技術,猶如修習一門武功。
歷數我周圍的技術牛人(牛不到一定程度的先不算),他們中既有名牌大學計算機科班畢業的,也有半路出家轉行過來的。
但他們都有一個共同特點:他們在遇到問題后,思考片刻,總是能一下子切中要害,在表達上也往往一語中的。這也包括那些平常不善言辭的程序員。反觀那些“更一般”的程序員(其中不乏科班畢業的),他們經常很難抓住問題的本質,表達起來也總是說不到點子上。
可見,“正宗”還是“野路子”,并不在出身。
寫到這里,我終于自己長出了一口氣。我出身一個極普通的農民家庭,既不是書香門第,也不是技匠世家。記得在大學一年級的上機編程課上,我才發現自己原來根本不會用鍵盤打字。相比那些初中高中就把計算機玩得很溜的同學,我算野路子嗎?
好了,那“正宗”還是“野路子”,不在出身在什么呢?
在于學習和思考的方法。
據我觀察,技術牛人的學習方法和思考方式,大體類似。
思考方式,是個很難說清的東西。所以,本文我們重點來討論討論學習的方法。
面對一項新技術的時候,我們怎樣去學習才能循序漸進,最終理解得深刻?
讓我們先把可供自學的資料列出來,分析一下:
- Tutorial(入門教程)。由該項技術的官網提供。通常是英文的。這份資料是給初次接觸該項技術的人看的,一般是一步一步地教你完成某些例子。當我們說某項技術對于新手不太友好的時候,一般也是因為這項技術的Tutorial部分做得不夠好。
- Specification,簡稱Spec。這是集中體現該項技術的設計思想的東西,是高度抽象的描述。這個一般也是一份完備的、系統的描述,包含該項技術涉及到的方方面面。這部分資料在不同的地方叫法不同,在相對簡單的技術項目中,也可能沒有;在另一些情況下,這部分資料混雜在其它文檔資料之中;它還可能以論文(paper)的形式出現。
- API Reference。大而全的API索引和文檔,針對不同的語言接口可能提供多份。當我們使用這項技術進行編程的時候,API Reference自然是個離不開的、總是要不停去查詢的一份資料。
- 別人寫的技術博客。質量良莠不齊,到底有沒有價值,我們要學會去分辨。
- 技術書籍。跟技術博客類似,質量有好有壞。稍后我們和技術博客放在一起來分析。
- Source Code。如果我們要學習的技術是開源的,那么很幸運,我們能得到源代碼。這是一份終極資料。
為了讓這些概念表達無誤,我接下來多舉一些例子。
Java語言
從來沒有接觸過Java語言的人,要想開始自學Java,從哪里開始呢?可以從Oracle官方提供的Tutorial入手:
這份資料《The Java™ Tutorials 》,集中體現了Tutorial類型的資料的特點。它從最開始的編譯和運行環境搭建說起,教你寫出第一個Hello World,再用介紹的方式將Java各種語言特性(變量、類、泛型、Lambda表達式、JavaBeans,等等)進行講解,同時還有對于JDK里常用API(集合類、多線程、IO等等)的介紹。
對初學者而言,需要的就是這樣一份資料。即使你手頭沒有任何Java的入門書籍,讀完這樣的一份資料之后,一個新手基本就可以開始使用Java來編程了。
再看Spec:
這份文檔,叫做《The Java® Language Specification》。是一份很典型的Spec,完備而規范。
任何講Java語法的資料,包括各種書籍和前面提到的Tutorial,都只能涉及部分。而這份Spec,如果你能讀通的話,那么與Java語言特性有關的所有一切,你就再也不用求人了。
JDK 8的API Reference:
用Java語言編程的時候,我們需要不斷查閱的就是這份API Reference。我們平常一般是通過IDE來快速查看某個接口的文檔說明。
Android開發
Android針對新手的Tutorial類型的資料,官網上稱為Training:
這份資料是典型的Tutorial。它教你制作第一個Android App,并針對若干個主題進行一步一步的教學。
下面這份資料在Android官網上被稱為:API Guides。
它實際上是一份介于Tutorial和Spec之間的文檔。它有很多Spec的特點,比如它介紹Android中的抽象的四大組件的概念,介紹資源尺寸的抽象(dp),介紹View層原理,等等。但是,跟前面看到的Java Spec相比,它沒有那么規范和正式,描述也更隨意一些,估計也算不上完備(但涉及到了Android技術的絕大部分)。
當我們對Android中某項具體技術存疑,或是有爭論的時候,我們就需要來翻翻這份文檔。因此,它基本可以歸入Spec類型。
然后是Android SDK的API Reference:
這份API Reference的質量并不高,描述上過于簡略,甚至模糊不清,其可讀性跟前面提到的JDK 8的API Reference完全不在一個水平上。這也是一些開源項目的通病,不重視接口文檔。
iOS開發
蘋果在iOS開發方面給出的文檔是相當豐富的,這也是一個閉源系統做得好的地方。
iOS開發的文檔,很難區分出Tutorial和Spec這兩個層面。它由很多文檔組成,每個文檔描述系統的某一方面。通常是在一個文檔中,既有教學的部分,又有完備描述的部分。
針對完全的新手入門的話,下面這個文檔,算是真正的一個Tutorial:
- Start Developing iOS Apps (Swift) (https://developer.apple.com/library/ios/referencelibrary/GettingStarted/DevelopiOSAppsSwift/index.html)
其它各個文檔也是介于Tutorial和Spec之間,更偏向Spec。比如:
- App Programming Guide for iOS (https://developer.apple.com/library/ios/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/Introduction/Introduction.html)
- View Controller Programming Guide for iOS (https://developer.apple.com/library/ios/featuredarticles/ViewControllerPGforiPhoneOS/index.html)
- View Programming Guide for iOS (https://developer.apple.com/library/ios/documentation/WindowsViews/Conceptual/ViewPG_iPhoneOS/Introduction/Introduction.html)
- Core Animation Programming Guide (https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/CoreAnimation_guide/Introduction/Introduction.html)
- Concurrency Programming Guide (https://developer.apple.com/library/ios/documentation/General/Conceptual/ConcurrencyProgrammingGuide/Introduction/Introduction.html)
然后是iOS的API Reference:
如前所述,這份API Reference的可讀性非常高,比Android SDK的要強多了。很多前后相關的概念,在這份API Reference的描述中,都有體現。
當然,除了developer.apple.com之外,iOS的文檔也都可以通過XCode取到。
Redis
Redis的Tutorial是我見過的最好的Tutorial,它對初學者非常友好,不僅能讀,還能執行。
Redis的Spec舉例:
- Redis Protocol Specification (http://redis.io/topics/protocol)
- Redis Cluster Specification (http://redis.io/topics/cluster-spec)
- Redis RDB Dump File Format (https://github.com/sripathikrishnan/redis-rdb-tools/wiki/Redis-RDB-Dump-File-Format)
Redis的Commands Reference:
TCP/HTTP
網絡協議與前面的都不同,它不是一個實現,而是一種標準。
網絡協議的Spec文檔很明顯,就是它們對應的RFC。如果你的工作經常涉及到使用某個網絡協議,恐怕就需要找來RFC通讀一遍了。
再來說一下技術博客和技術書籍。
現在網上的技術文章空前繁榮,想讀都讀不過來。胡峰同學在他的微信公眾號“瞬息之間”上,發過一篇文章《技術干貨的選擇性問題》,討論的就是技術人員在當前技術文章爆炸的情況下如何取舍的問題。
在這里,我們從另一個角度來討論一下這個問題。如果一篇技術文章,僅僅是對于所涉及技術的官方文檔(Tutorial或Spec)的復述,甚至只是個翻譯,那么就價值不高。換句話說,如果我們能通過閱讀官方文檔學到同樣的知識,那為什么要看你寫的技術文章呢?官方文檔自然更權威,直接閱讀它能確保不會遺漏重要的東西。
那什么樣的技術文章才有價值呢?大概可以說(未必那么準確),那些包涵了實踐經驗的,能將各個技術點綜合起來產生思考,從而給人以啟迪的。簡單來說,就是有深度的。
當然,技術書籍也大體如此。
我們回過頭來再看一下,各個學習資料之間的層次結構。
每當我們接觸一項新的技術的時候,我們都要把手頭的資料按照類似的這樣一個金字塔結構進行分類。如果我們閱讀了一些技術博客和技術書籍,那么也要清楚地知道它們涉及到的是金字塔中的哪些部分。
最開始,一般讀完Tutorial之后,就基本能上手做一些開發工作了。然后一邊開發,一邊查閱API Reference。注意,從這時候起,你的老板就開始向你付工資了,因為你的工作已經能夠產出成果了。
但是,工作一段時間之后,我們發現,似乎身邊的技術牛人學東西都比較快,而且在很短的時間內就能對某項新技術達到很深的理解。這是為什么呢?
這并不是因為技術牛人閱讀技術資料閱讀得快,而是他們知道閱讀正確的資料,從而很快能達到知識金字塔更高的一層。
我見過的很多技術牛人,他們如果不是把一項技術至少理解到Spec那個層次,他們是不敢隨便寫代碼的。相反另一些人則從網上隨意拷貝代碼,并在自己不能完全理解的情況下用到項目中去。技術牛人們當然也參考網上的代碼,但他們通常會確保它的每一部分都能安放在知識金字塔的某一部分,他們不容許那種不屬于任何體系的知識孤島的出現。
我們現在可以這樣總結,技術的“野路子”,其實是知識結構的不完整和不系統造成的一種狀態。只有當你沖破知識金字塔層層的障礙,邁向更高層次的時候,老板才開始向你付高價。
我們的大腦好比內存。
既然是內存,就裝不下所有的知識。但應該能裝下對于知識的索引,否則我們便沒法工作了。
那么,這里就有一個選擇性的問題:我們選擇哪部分知識加載到“內存”里呢?
顯然,應該優先選擇重要的,對我們最有用的信息。
對于那些最核心的技術,我們應該做到:
- 通讀Spec。讀完就不再困惑。
- 重要部分的API Reference要通讀。里面包含了很多跟實現有關的信息。
- 如果工作需要,還可能需要讀到Source Code。特別是對于平常一直在使用的SDK,不一定從頭到尾把源碼讀通,這樣工作量太大且效率不高,但一定要把你的開發環境設置成一點擊某個調用的方法就能跳轉進源碼實現。只有這樣,你才能把平常開發的時間利用起來,隨時隨刻都點過去看源碼。
對于剩下的知識里80%的部分,應該至少理解到Spec層次。只有這樣,我們才能游刃有余地去使用它。
通讀重要的Spec,在很多情況下,其實還是很有難度的。這需要毅力,和一點點英語基礎。
按本文前面提到的例子,做Java的人有誰讀過Java Spec?做Android的人有誰把developer.android.com上的API Guides都能通讀下來?而做iOS的人,developer.apple.com上的各個Programming Guide又完整地讀過幾個?對于經常調用的SDK,你會有計劃地去通讀其中重要部分的API Reference嗎?
能夠把這一套做下來的,有可能不成為技術牛人嗎?
到了文章最后了,總感覺還有些意猶未盡,腦海中似乎有些東西還是沒有表達出來,也不確定本文描述的學習方式是不是適用于每位讀者。仔細想想也難怪,學習本來就是一個復雜的問題,每個人并不是完全一樣的套路。
但是,不管本文介紹的方法是“正宗”的路子,還是屬于“野路子”,我在這里想要強調的一點是很明確的,那就是:要把知識梳理成系統的結構,要讓頭腦中的知識層次清楚,為此,我們需要閱讀恰當的東西,需要不斷地練習,需要克服種種困難。
成長沒有捷徑可走。需要的是一個一個堅實的突破。