知乎日報:
做為技術道路上的過來人,我也分享一下我的體會。簡單來講,成為技術大牛雖然有難度,但其實也沒那麼難。要成為任何一個領域的專家,你需要做的是學會該領域的已有知識,所以你只要學習就行了。真正有難度的事情是創新,是利用已有知識和技能創造出人類還不知道的有價值的東西。
如何學習專業技能?我自己總結了一句話:“技能學習這件事,有技巧無捷徑”。有技巧是説,並不是説你花了很多時間,技能就一定會提高的,這裏面有方法論的區別;無捷徑是説,即使知道了技巧,不下功夫也是不行的,正所謂,紙上得來終覺淺,絕知此事要躬行。
拿我自己來舉例子。我在上大學之前從來沒有接觸過 PC,甚至都不知道有個人電腦這種東西。操作電腦、編程這件事對我而言完全是零基礎,自學成才。由於對計算機有強烈的興趣,從大一開始,我花了很多時間學習編程(當然也花了很多時間玩電腦遊戲),諸如個人電腦操作指南、打字法、Windows 用户手冊、微機原理、Windows/Unix 操作系統、各種 C/C++ 編程書籍(Turbo C、Borland C/C++、Visual C++),我看了一大堆書,也寫了一些程序練手。直到大四,我還是覺得很迷茫。一方面感覺自己學了很多東西,另一方面又覺得好像什麼都不會。具體點説,如果讓我寫個編程作業,問題不大;但是如果讓我寫一個有完整功能的應用程序,幹不了。換句話説,我的水平可以應付學校裏的作業,但是還沒能力做真正的產品開發。
這讓我很焦慮,不知道畢業怎麼找工作。當時我的想法,是找一家公司實習,工資多少無所謂,一定要能鍛鍊技術。我選擇的公司是一個創業公司(現在不存在了),同學推薦的,領導和技術團隊都很牛。我的面試很糟糕,人生的第一場面試,幾乎所有問題都搞砸了。領導看在推薦人的面子上把我留下,工作內容是組裝電腦和安裝各種軟件,跟電腦城裏賣電腦的差不多。由於在大學裏裝過無數次電腦,我乾的不錯。印象最深刻的一次是有一回別人剛攢好的電腦系統(SunOS 4)啓動到登錄界面時出現花屏,鼠標滑到哪兒花到哪兒。領導讓我判斷是什麼問題(他技術很好,其實在考驗我),我説可能是因為顯存不夠,換一塊有兩兆顯存的顯卡試試。換顯卡後果然好了。
大約是從那以後,領導開始讓我參與軟件開發。我寫的第一個商業程序是一個應用網關,把一種醫療儀器集成到我們自己開發的醫療信息系統。由於後來需求的不斷擴大和我本人的完美主義傾向,這個軟件我重寫了三遍。最開始很普通的一個模塊,最後可以做到可以方便地接入各種新設備(不同廠商、不同種類),也因此變成了核心模塊,產生了獨特的商業價值。有的項目中公司拿出來單獨賣,也專門為它申請了專利保護。
這兩件事我學到的是,做任何事情都要用心,要非常關注細節。看起來不起眼的、繁瑣的工作做透了會有意想不到的價值。從技術角度,我也學到了很多東西。比如,如何用 RS232 和設備通信;如何寫一個 TCP 服務器;如何寫一個獨立的 Windows 應用程序;如何把一個普通程序做成 Windows NT Service;如何寫一個跨平台的程序(Windows 和 Linux 都能跑);如何設計一個框架,能夠快速集成多種協議(RS232 串口、TCP/IP、有狀態協議、無狀態協議等);如何逆向分析各種設備協議(我們是小公司,拿不到醫療設備公司的協議文檔);如何把設備集成框架設計得簡單易用,我不在的時候(當時我還沒畢業)別人也能快速集成新設備。我覺得任何一個值得做的項目都會學到很多新知識,成為技術專家的關鍵一點是你要把每一個有價值的知識點研究透,這樣多個項目積累下來,你就有了很多很紮實的知識點,這些知識點積累起來,結合書本知識,就能系統化。什麼叫研究透?想像一下世界上該領域的頂級專家來跟你交流,你是否能做到他問的任何問題都能對答如流。
已經過了快二十年,我對這個程序的很多技術點還能記住,是因為當時真的下了很多功夫(不然不會重寫三遍)。我面過很多人,不太理解的一點是發現有些人對自己做過的東西説不清楚,有的細節甚至才過了幾個月就忘了。我麪人的基本要求是知其然還要知其所以然,自己做過的東西説不清楚説明不怎麼動腦子,知其然不知其所以然説明對技術沒有追求,不關心背後的原理。
基本上我寫過的所有軟件,設計要點我到現在都能記住。要做到這一點,一方面是做任何事情都要下功夫,關注細節;另一方面是要把設計和實現分開,實現可以忘記但是設計不能忘。
這個網關程序我在兼職狀態下做了三年多(從大四到讀研),真正的密集開發可能只有不到一年的時間,還不是全職的,後面忙着本科畢設和研究生學業,變成顧問角色,很少去公司。我在那時就已經成為了 Windows 技術專家。做 d2hackmap 遊戲外掛是在研究生後期,那個時候我的 C++、Windows 技術水平已經很高了,如果你去看 d2hackmap 的源代碼,可以發現裏面用了各種 Windows、C/C++、彙編技巧。
在這個網關開發的過程中和研究生期間,我學習了哪些技術?具體來説,有當時所有主要的 Windows 開發書籍,所有主流的 C/C++ 編程書籍,還有歷期 Microsoft System Journals(後改名叫 MSDN Magzine)上感興趣的專欄文章,都看了一遍。
問題是,同樣的我,為什麼從大一到大四花了那麼多時間學習編程,進展很慢,然而實習了不到一年就有很大進步呢?我覺得有幾個原因。一是原來的學習雖然有一個模糊的方向,但是沒有明確目標。二是沒有特定的工作環境。三是缺乏過來人的指點,不可避免走了彎路。
有明確的交付目標和時間點,才會有壓力,才會針對具體問題去尋找答案,這樣就把漫無目的的學習範圍大大縮小了。環境也很重要,在家裏工作和在公司工作效率差很多,這跟在宿舍自習和在教室自習差很多一樣。過來人的指點可以避免走彎路,讓你在第一時間做出正確選擇,節省大量時間。但是要記住,別人對你沒有義務,所以別指望高手會手把手教你。我的學習更多的是觀察優秀的人如何做事以及他們對事情的觀點。
通過項目學技能的好處是任務很具體目標很清晰,缺點是容易見樹木不見森林,知識不繫統。通過看書學技能的好處是知識體系比較完整,有全局觀,缺點是書本知識比較抽象和枯燥,不容易理解。所以這兩者一定要結合起來。
總結起來一句話,技能學習有技巧無捷徑。有技巧是説學習技術需要實踐和看書相結合,有高手指點就更好,關鍵是一定要實踐,光看書或者做練習題是不行的;無捷徑是説一定要自己下苦功夫,不要幻想有高手帶你飛。我在上海生活十幾年,上海話都聽不懂。因為智商不夠嗎?肯定不是。因為我不知道學習語言的技巧嗎?也不是。是因為我沒有學習上海話的壓力,也缺乏主動性,沒有下功夫而已。
關於技術大牛,其實也分兩個方向:領域專家和系統架構師(我的選擇是系統架構師)。前段時間正好在公司內部做了一個架構師講座,藉此分享一下。
下面引用的兩張圖來自這個網站:Gaud&iacute System Architecting homepage 是一個專門研究系統架構設計的一個項目,免費的。
技術專家和系統架構師的區別如下圖。技術專家和系統架構師是兩個不同的方向,無所謂誰好誰壞。技術專家在某一個領域非常精通,比如説音頻編解碼算法。系統架構師是一專多能,在某些點上追求深度,其他領域追求廣度。在技術專家和系統架構師這兩個方向之間還有多領域專家和領域架構師。
從新人到系統架構師的職業道路如下圖。
做為架構師,雖然追求廣度,但是必須對某個領域非常精通,這是你的根,要扎的非常深。我面過很多架構師,是在做上層架構設計,説的也頭頭是道,但是對一線技術精通的就不多。
架構師的第二個層次是要追求技術廣度,有很多技術你可能沒有做過,但是要知道怎麼回事,需要的時候能迅速鑽進去。
第三個層次是要了解業務、應用場景還有各種組織流程。瞭解業務和應用場景是因為技術需要靠創造商業價值來變現,瞭解組織流程是因為商業化不是單打獨鬥,需要協作。架構師是把商業需求轉換成產品的一個關鍵角色,因此他需要了解這些技術以外的東西。
第四個層次是要了解社會心理學。因為產品最終是為了滿足人的需要才有價值,而產品研發本身也需要多人協作。社會心理學主要是研究人際關係。自我評價的話,我現在大約在第三、第四階段的某個程度。
關於智商。有人擔心自己智商不夠做不了技術大牛。我的看法是智商這個東西看做什麼。如果是創新型工作,比如科研,需要突破人類已有的知識疆界,這是需要很高的智商(不過科研裏也有很多搬磚的活兒)。絕大部分的工作,包括軟件開發,並不需要很高的智商,重要的是勤奮、學習技巧和工作的態度。
關於工作態度。我很喜歡的一句話是 Everything happens for a reason(凡事皆有因)。這句話的真正意思是,做為工程師,你必須有打破沙鍋問到底的精神,對每一個問題都追查到底。開發中會碰到大量的 bug,有的偶現 bug 很難查,有沒有這種精神,直接決定了產品的品質和你在技術上能走多遠。我在前一段時間,為了一個客户反饋的 iOS 上的偶現崩潰,查了兩天兩夜,其他工程師覺得可能是客户自己的問題放棄了。我以前在博客裏也分享過一個案例,為了驗證這個 bug fix,我做了 14 萬次實驗,細節見這裏:Sting 的專欄 - Under the hood。技術就是這樣一點一滴積累出來的。
我分享一下 14 萬次的驗證實驗這個案例。我們當時新發布了一款設備,客户反饋説有時關機下不了電,這個後果比較嚴重,會直接耗盡電池導致電池損壞。這個問題其實在產品發佈前發現過,出現的概率大約是百分之一,當時也做了修復。在客户那兒復現了説明沒徹底解決。我當時剛進公司沒多久,從來沒做過硬件相關的開發,甚至都不知道有邏輯分析儀這種東西。但是我有很好的思路,建議做自動化測試重現問題。測試的結果發現出現問題的概率是兩千分之一,換句話説,平均每兩千台設備會損壞一塊電池,或者每台設備下電兩千次電池會壞掉。通過用示波器和邏輯分析儀捕捉下電過程的信號邏輯,做了大量分析,我們找到了問題,是因為 CPU 在下電時寄存器狀態沒保持住,一定概率上會影響主板上的下電邏輯。修復以後,接下來的問題是,這種小概率事件,解決方案怎麼驗證是正確的。我的想法是,因為我們知道出現問題的概率大約是兩千分之一,如果驗證次數比這個概率高一個數量級,我就有信心説基本解決了這個問題,如果驗證次數高兩個數量級,我的信心是非常足的。所以我的目標是要做 20 萬次實驗。最後由於市場壓力比較大,時間來不及,做了 14 萬次覺得足夠了。
關於商業軟件開發。商業軟件開發和編程作業、算法競賽等最大的區別在於這句話:軟件的首要技術使命是管理複雜度。這是《代碼大全》裏的一句話,是我覺得這本書中最重要的一句。很多軟件工程師包括很多技術大牛都沒有意識到它的重要性。仔細想想,很多重要的編程思想、方法論其實都跟這句話有關。比如,為什麼要建立代碼規範,要有代碼倉庫管理 /Check-in 流程;各種軟件研發流程:瀑布模型、V 模型、敏捷開發;各種設計思想:分層、模塊化、面向對象、基於連接和組合、KISS 原則 (Keep It Simple and Stupid)、高內聚低耦合。所有這些其實都是為了管理複雜度。心中有管理複雜度的意識,軟件自然會越寫越好。
最後關於如何做事如何學習,我推薦一本書:史蒂芬.柯維的名作《高效能人士的七個習慣》。我很早以前就知道這本書,很多外企都有相應的培訓課程,系統架構師的培訓講師也推薦過,我自己偶爾也翻翻,但一直以來都當成功學、心靈雞湯看待。我真正對待這本書,是因為幾年前認識一個朋友,他説這本書改變了他的人生。這給我很大的震撼,因為我從來沒聽過有人説一本書改變了人生。如果有一個清華本科畢業、留美博士、回國創業成功的絕頂聰明人,跟你説一本書改變了他的人生,你是否也應該重視呢?
這本書給我的體會是,道理非常好,但是説理的方式有點教條(也許是翻譯的問題),很多道理需要結合人生閲歷來仔細體會。現在讀不太明白也沒關係,過幾年再看,會有新的體會。
寫這個回答是因為我前幾天寫了這個回答以後,有人對我的成長經歷比較好奇,也有些人覺得我是一個破壞分子,因此在這裏澄清一下,我是一個正經的程序員!