最近幾年,IT行業中的各個群裡突然流行了一個詞——“大牛”。有些人因為在學術界發了很多論文而被稱之為牛;有些人因為在群裡努力幫助大家解決問題而被稱之為大牛;有些人因為寫了一本技術的書而被稱之為大牛;有些人因為開源了很多技術知識二被稱之為大牛;還有些人因為程式碼能力強被稱之為大牛……今天我們不聊其他的大牛,就來聊聊那些因為程式碼能力強而被稱之為大牛的人。

10年前的一個案例

實際上這個程式碼能力強的大牛一般是要和普通的碼農來對比,與普通碼農相比,這些程式碼能力強的人,到底強在哪裡?首先來給大家講一個在我身邊所發生的真實的事件。

大概是10年以前,那個時候微控制器非常流行,很多人都喜歡在微控制器上開發一些應用,但是微控制器有一個問題,就是儲存相對來講不是很通用,導致很多時候對於微控制器的儲存需要寫很多程式碼進行處理。那個時候雖然已經有了sqlite資料庫,但是業內應用的並不是很多,很多時候大家都是使用基於記憶體地址的儲存方式進行儲存。當時我們就在想,能不能自己寫一個簡單的資料庫,用來儲存我們所需要的資料(當時我們資料傳輸使用的是xml格式的資料),於是我們團隊裡的一個大牛就決定試一試,於是他花了大概不到一週的時間,使用C語言寫了一個相對比較簡單但功能卻非常全的XML資料庫。大家可以想象一下,四五天寫出的資料庫支援自定義的查詢語言(類似於sql語句),並且還能支援各種遍歷和節點存取操作,且單次查詢執行效率也是在10ms以內,這即使是放在現在,也是一個比較艱鉅的任務,更何況是10年以前。

現在事情過去差不多10年的時間了,我們來分析一下為什麼他就那麼牛,為什麼他就能成為技術大牛呢?其實要想分析他之所以能夠成為就是大牛的原因,我們應該把這件事情從後向前來推一推。

當時他是使用C語言寫了一個簡易的XML資料庫,並且這個資料庫的執行效率非常高,要想達到這一點,首先要做到的就是對於C語言的各個函式的熟練程度,已經對於資料結構和演算法的熟悉程度。大家都知道,想要使用C語言來寫出一個比較完整的商業級的應用絕非易事,尤其是C語言中對於指標的處理更是令許多同學望而生畏的,但是我們也知道,正是由於C語言中的指標,才使C語言對記憶體操作更加便捷,使得可以更加高效的開發出具有商業級別的專案出來。

另一方面,要想把這個功能完成,還需要對整體的系統底層有著比較深入的研究,並且對記憶體的最佳化足夠了解。在業務層面,還需要對XML格式的解析,儲存,以及與記憶體地址的互動有著深入的瞭解,才能將這一套完成。

最最重要的,實際上還是對於程式碼的能力,也就是我們所說的coding,其實在這裡,coding的能力也取決於兩個方面,一個是對於整體語言和系統底層架構的熟悉程度,另外一方面就是對於整體問題的分析和解決思路。而這些問題,往往是普通程式設計師和大牛程式設計師的區別所在,接下來,我們就來對這幾個方面做一個簡單的分析。

對於資料結構與演算法的認知和使用

對於資料結構和演算法的認知和使用是普通程式設計師與大牛程式設計師最主要的區別。很多人都會認為,資料結構和演算法,我會啊,大學學過,你讓我寫一個單鏈表,寫個

二叉樹

,手到擒來。

實際上,這個是一般人對於資料結構和演算法的看法,大多數人都會認為,我只要對各種資料結構和基礎演算法懂就可以,讓我寫的時候我隨時可以寫出來就ok,這也是初學者最容易犯的問題。

因為在實際的工作和工程化過程中,沒有人會告訴你,我要用某一個演算法來解決某一個問題,而是給你一個需求,然後告訴你這個需求裡面的一些必備要求,比如

響應時間

在30ms以內,支援1000人的同時訪問等,然後讓你自己來實現,具體用什麼演算法自己來決定。

實際上這類的問題非常考驗演算法同學的基本功,對於演算法同學來講,最基本的基本功就是

資料結構與演算法

。在什麼時候,用什麼排序演算法,針對於大資料集和小資料集,用什麼樣的演算法能夠使其效率最高,實際上都能看出來一個人的程式碼水平。但是針對於大部分程式設計師來講,在真正拿到專案需求時,往往就會忘掉這一點,而是先實現了再說,最後的結果是實現了,但是程式碼的質量以及效率經常是慘不忍睹。

對於資料結果和演算法的使用,一般是在長期程式碼的開發過程中總結出來的,這個真的是需要不斷的總結積累才能夠慢慢鍛煉出來的一種能力。很多時候,我們只是為了完成需求而完成,只要這個任務能夠執行出來就萬事大吉。

記得在很久之前,有一個是笑話但又非常真實的故事。就是在acm競賽中的一些練手題目中,給定一個

最大數字

,可以根據這個數字輸出指定的圖形,就像下圖這樣。

聊聊我眼中的普通碼農和技術大牛的區別

其實這道題正常應該是用迴圈來做,但是有些人說,我直接用print加上空格也能夠實現。確實,針對於這個問題,實現的方式有很多,但是往往最方便的只有一個。當然,這個例子有些誇張,但是我想借此來說明的一個問題就是,資料結構與演算法的思路,是看出新手和大牛的關鍵點所在。

我們要學會,在任何時候,都用演算法的角度去考慮問題,怎麼樣最佳化才能夠使演算法最優,效率最高。而不是僅僅把這些都停留在刷LeetCode題的階段,要把它們運用到實際的專案當中,只有這樣,我們才能夠向大牛的方向不斷進步和提升。

解決問題的思路

解決問題的思路也是決定著大牛還是普通程式設計師的關鍵因素。從解決問題的方法和思路中往往能夠看得出一個人的能力。所謂的解決問題的思路是指當程式遇到bug了,或者遇到一個新的需求,用什麼樣的思路快速的去定位到問題,並解決問題的過程。

其實這類事情在一個企業中非常常見,在任何時候,我們都不能保證我們所寫的程式碼沒有任何bug,也不能保證每一個新的需求我們都能快速的寫出解決方案,很多時候,我們都需要經過自己的思考,來尋求問題的

最優解

。我曾經遇到這樣的一個員工,當時他在我的組裡負責推薦系統的一部分演算法業務,突然有一天,測試人員跟他說:“目前演算法所跑出來的結果和實際的結果對不上,你看看是怎麼回事?”於是這個同事拿到這個測試反饋之後,就開始找問題,找了一上午都沒有找到是哪裡出了問題。於是他過來問我,說:“黃老師,這個我找了一上午,感覺沒問題啊?但是為啥就是對不上呢?”於是我又讓他重新演示了一下找問題的方法,最後我發現,是他找問題的思路出了問題。

他是根據現有的問題去結果裡面找這個問題為什麼會出現,用這樣的方式去找,很容易把自己繞進去,最後總覺得是沒有問題的。但是實際上,我們在解決問題的時候,需要跳出思維的定式,首先分析產生問題一般會出現在哪幾個階段中,然後再從這幾個階段中觀察這幾個階段的輸出,透過觀察輸出就可以看到,在哪個階段的輸出是正確的,在哪個階段的輸出是錯誤的,然後再去從錯誤輸出的階段中去尋找問題所在,把整體的業務流程理清,從而解決問題。

實際上,很多時候當我們遇到了程式的bug時就會很慌,感覺程式出了bug了,自己有很大的責任,心態亂了,心太亂了之後,就會越來越著急,越著急就越找不到問題的所在,最後就會無功而返。這其實是很多程式設計師的通病,歸根到底就是解決問題的思路不對。

其實

程式

是什麼?說到底,程式是遵循著既定的

業務邏輯

的,也就是說,當我們給定了一個程式的輸入,我們就應該能夠預判出一個程式的輸出,所以在IT界常常有這麼一句話:“程式是不會騙人的”。因此,當我們遇到問題的時候,千萬不要亂,只要思路清晰,掌握好程式中的關鍵階段,那麼定位問題一般是很容易的。

解決問題的思路除了在解決bug這一方面之外,應對新的需求也是一個能夠考察新手和老鳥的點。

透過我的觀察,對於新人而言,當來了一個新的需求時,一般都會根據業務邏輯直接上手去做,做到最後會發現有很多bug。但是對於大牛或者老鳥來說,一般會先用一些時間來想一下,看看用什麼框架,什麼演算法來做這個需求比較好,大概需要多少時間,中間可能會遇到什麼問題?這些問題應該怎麼去規避?當把這些問題都考慮清楚之後,最後在心裡或者文件中制定出一個可行的方案,然後再去實施,最後的結果往往是bug很少,程式碼質量很高。

所以說,解決問題的思路往往能夠看出一個人的能力,這對於新手向大牛的方向進軍是非常有幫助的一個點。

系統底層的瞭解程度

對於系統底層的瞭解程度在很多時候也是區分普通程式設計師和大牛的區別,尤其是對於一些與底層系統打交道的公司來講,更是這樣。

記得在2015年左右的時候,我去上海的一個團隊幫忙帶一個比較重要的專案,在這個專案的團隊中有一個程式設計師出身的專案經理能力特別強,並且對於手下的人要求也特別嚴格。有一天我們技術研討會,一位技術經理用PPT的方式向我們解釋了android端應用程式的資料流是怎麼走的,這個時候,那個專案經理問了一個問題:“你幫我把這個資料流在底層與記憶體的指令暫存器和bus匯流排的互動畫一下,還有就是是怎麼排程記憶體的,這裡大概需要多少的開銷,記憶體是怎麼定址的幫忙畫一下”。實際上這位專案經理並不是有意刁難技術經理,而是這位專案經理真的是技術太牛了,以至於他對於很多專案中的底層細節都要求瞭解的清清楚楚,包括怎麼和記憶體互動,怎麼去節省開銷,怎麼去做定址等等。但是這些,對於一位普通的程式設計師或者技術經理來講,確實是非常有難度的,最後,這位技術經理也沒有畫出來。

還有一次,也是這位專案經理,在開會的時候要求技術人員用標準的UML圖來解釋內部執行的原理,包括採用時序圖和活動圖來做。實際上,這些都是我們大學學過的,但是由於大家很少用,所以基本上都淡忘了。這個時候,專案經理說了一句話:“UML是大學時候大家都學過的知識點,在我看來,只要大學學過的,你們都應該是掌握的,不然這個大學豈不是白學?”,確實,這個說法沒錯,這些都是我們大學所學過的,但是正是因為很多人並不注重這些基礎的內容,以及對於底層互動的內容,以至於做了很多年的程式設計師都沒有得到本質上的提升。

所以說,瞭解系統底層的工作原理,對於一個高階的程式設計師是非常重要的。

對於疑難問題的鑽研程度

對疑難問題的鑽研程度實際上可以說是上面幾個點的綜合體。很多時候,我們會經常遇到一些比較難的問題,這些問題可能需要查閱各種各樣的資料、論文,可能需要考慮到各種各樣的情況和複雜的環境問題,可能會要求對演算法非常熟悉,因此,這個也是普通程式設計師和大牛程式設計師之間的核心差異。

我們在這裡所說的疑難問題並不是說一個bug,或者是一個小的需求,這裡所涉及到的可能還需要有一定的創新能力和綜合能力。比如,老闆有的時候可能會說這麼一句話:“我看最近谷歌出了一個新的技術框架叫XXX,你去研究一下”。這句話實際上看起來是很輕鬆的一句話,但是這裡面卻是對一個人非常全方位的考察。

這裡說的你去研究一下,我們就要先來定義一下,在企業中所說的研究到底是什麼?一般來講,我們在企業裡所說的研究,或者領導讓研究一件事,其潛臺詞基本上就是:“這個東西別人沒有搞過,你去搞一下,按照官方文件來搞,可能沒有更多的資料,並且,你還要給我出一個demo和一個報告”。是的,這是老闆的最終目的,我們可以發現,這個難度實際上是非常大的。

對於一般的新手程式設計師,往往是按照官網給出的文件搭建出一個demo,然後拿去交差,甚至很多人都無從下手,更或者連demo都搭建不起來。但是對於一個技術大牛來講,他們的做法往往不僅侷限於這些。

之前也跟很多技術大牛交流過這個問題,總結出的結果是,他們會先把這個demo搭建好,然後再去網上找一下與這個框架相關的競品框架並且也搭建出來一套,並試圖改善這兩套框架,並用同一套資料分別在這兩套框架中進行測試,最後生成一個報告給老闆,目的是告訴老闆:“這個框架我研究了,並且我還透過類似的框架來證明了這個框架的優缺點,針對於缺點我認為可以用什麼方法來代替或改進”,你會看到一套很完整的資料報告。

實際上,很多人都會遇到這樣的問題,在2年以前(2018年初)我也遇到過這樣的問題,當時領導只有一句話:“你去調研一下目前文字分類在長文字二分類模型下哪個比較好一點”。於是,我整理出了這麼一個報告,這個報告裡面明確的說明了我都嘗試過哪些模型(一共嘗試了大概10個模型),每個模型的準確率多少,召回率多少,耗時多久,並和其他廠商的對比是怎麼樣的,的人,這只是報告裡面比較關鍵的一個部分,並不是報告的全部。我透過這個只是想解釋,當時我們做的工作就不僅僅是告訴老闆,哪個模型好,你就用吧!而是告訴老闆,我把目前主流的文字分類模型都試了一遍,並且用資料做了對比,把

平均耗時

(工業專案很關注這個)和準確率都列了出來,並給出最終我人分為哪個會好一些的建議。最後老闆肯定是非常滿意的。

因此,我們說對疑難問題的專研程度指的是什麼?實際上,指的就是你對於整個問題的思路、分析,幷包括了你的程式碼能力、 創新能力以及對於行業的敏銳程度。這是一個人能否成為大牛的關鍵。

實際上,除了上面列舉的幾個點之外,大牛程式設計師和普通程式設計師的區別還有很多,在這裡我們就不一一做分析了,也歡迎大家踴躍留言,說說你們的看法。

最後,祝大家以後都成為大牛。