我們和優秀工程師的差距在哪兒

張磊BARON發表於2018-04-24

一道 Google 面試題告訴你如何破局而出,快速成長為優秀工程師。

關注微信公眾號:BaronTalk,更多精彩好文等著你!

我相信每個工程師都曾懷揣一個成為技術大牛的夢想,可是真正走向技術大牛這條路的少之又少。工作中我們常常會發現,有些同學工作沒幾年但成長迅速;很快就能走向團隊核心崗位,成為一名優秀的工程師;而有些同學工作幾年後卻在公司裡默默無聞,能力和職位上都沒有太大提升,得過且過最終淪為一名普普通通的碼農。所以我常常會有感慨,太多人(包括我自己)真的只不過是用一兩年的經驗在職場上混了五年十年甚至更久。

那麼普通工程師和優秀工程師到底差距在哪兒?那些優秀工程師是怎麼一步一步成長起來了的呢?以下就我自己的觀察和思考來談一談,看看能不能一探究竟,瞭解通向優秀工程師的法門;然後與大家共勉,一起朝著優秀工程師的方向去努力。

差距在哪兒?

我們拿吳軍老師在得到專欄中講解的一道 Google 面試題來展開聊一聊,看看面對同樣的問題,普通工程師和優秀工程師是如何思考解決問題的。

問題如下:如何設計一個地圖功能,找到離當前最近的加油站?

在最近公司的招聘面試過程中,我也拿類似的問題去問過部分候選人,大部分候選人都把問題想的太簡單。通常普通工程師給出的解決方案是:根據經緯度算出所有加油站到當前位置的距離,然後對這些加油站按照距離的遠近進行排序,選擇距離最近的幾個加油站。

可問題是,在路面上行駛,從 A 點通往 B 點,往往不是直線距離。因為無論是駕車還是步行,我們都不可能穿過建築直達目的地,A 點到 B 點的距離是很多距離片段的組合,這可能會有上千種組合,那麼如何從這上千種組合的路線中選擇距離最近的一條路線呢?使用動態規劃演算法能夠很好的解決這個問題,在上千種組合中只需幾十個步驟就能計算出最短路線。這對部分工程師已經是個門檻了。

接下來就需要按照距離排序,找到最近的幾個加油站。

絕大部分工程師面對這樣的問題都會想到排序,排序當然能夠解決問題,但並不是最優方案。就算使用效率最高的快速排序,也需要 N 乘 LogN 的計算量。假設城市裡有 1000 個加油站,那麼 LogN 約等於 10,也就是說計算的複雜度差不多是 1000,當然 1000 的計算量對於計算機算不上什麼,但是考慮到一個城市的路面上可能有上百萬輛行駛的汽車,這個計算量的消耗就很可觀了。

假設我們只需要最近的 5 個加油站,如果對所有的加油站排序那顯然做了很多無用功。資料結構中有一種叫二叉樹的資料結構,在二叉樹中有一種更細的分類:“堆”,通過堆排序我們可以只用排出前幾名,而不用管後面的名次。通過堆排序排出第一名的時間複雜度是N,排出第二名、第三名、第四名、第五名的時間複雜度都 LogN,比對 1000 個加油站排序要快的多。對於我們的需求:選出最近的 5 個加油站,差不多隻需要 1000 的計算量,比快速排序快了近 10 倍。

到這裡你是不是覺得問題已經解決的很完美了?

我們在解決問題的時候不由自主的做了一個假設,就是整個演算法的優化過程是圍繞一個使用者的某一次使用來進行的。但是在現實生活中,一個城市裡有很多人會同時在不同的地方尋找加油站。類似的,同一個人在不同的時間不同的地點開車時也需要尋找加油站。考慮到這個現實場景,時時刻刻都有很多人在不停的尋找附近的加油站,那麼很多計算其實是可以預先算好的,等到提供服務的時候直接把結果調出來就好了,避免重複計算。

比如我們可以把上海市所有路口點到點的距離事先計算好,當一個人要找加油站的時候,距離的計算就不再需要實時地採用動態規劃來計算了,只需要計算從當前位置出發到附近幾個路口的距離,再計算下某個加油站到它所在地附近路口的距離,由於各個路口點到點的距離是事先計算好的,因此做幾次簡單的加法即可,這樣計算距離的時間就能省幾十倍。這就是對上面的問題進行了全域性優化的好處。

其實面對這樣的問題,優秀的工程師並不會遇到問題就直接著手去解決,而是會更全面的去考慮問題。比如會考慮到目前的行車方向,比如在解決問題中其實距離要求並不需要太精準,因為對於開車的人來說 2.5 公里和 2.3 公里其實並沒有什麼差別,再考慮到道路擁堵的情況,200 米的距離更加可以忽略不計了。但如果是行人要尋找附近的便利店,200 米的距離就不得不考慮了。

那麼從上述這個問題的解決上我們能看出普通工程師和優秀工程師的差距在哪兒呢?

1. 優秀的工程師必然有著紮實的計算機基礎知識,很好的掌握瞭如資料結構、演算法這些工具,能夠在工作中藉助這些工具幫助自己解決問題;

2. 優秀的工程師會盡量避免做無用功

3. 優秀的工程師不會只滿足於完成任務,他們會不斷的去思考探索最佳的解決方案;

4. 優秀的工程師不會被思維所侷限,考慮問題更加全面,懂得從全域性角度優化解決方案。

從這個例子我們也能看出來,一個優秀工程師解決問題的效能可能是普通工程師的幾百上千倍,一個優秀的解決方案甚至能幫助公司節省幾百萬的伺服器費用。

因此,在軟體工程領域一百個臭皮匠也頂不了一個諸葛亮!

做為普通工程師的我們如何提升自己?

學好資料結構、演算法、作業系統原理、計算機體系結構等基本功,打好基礎。

如果你是天才,面對像上面這樣的問題,即使你沒有學過計算機理論知識,即使你不知道動態規劃、二叉樹、堆排序,可能也能依靠智力上的優勢解決。但遺憾的是絕大多數人都不是天才,因此在解決問題的時候就需要藉助各種工具以便事半功倍。對於開發人員來說,資料結構、演算法以及各種數學知識就是我們手上的工具。

要成為優秀的工程師需要我們靜下來,沉下去,老老實實的吃透你所做的專案。做好簡單的事,才有機會去做更有挑戰的工作。

很多工程師會抱怨自己一直在做業務,沒什麼挑戰,感覺不到成長。可事實真的是這樣嗎?往往我們的業務需求就像這道面試題,看似簡單其實想要做好,背後需要下很大功夫。就算平時做的業務真的很簡單,我們是不是還可以想想,我的程式碼實現是否有更好的方式?面對類似的業務我的效率是否可以提升?線上出 Bug 了是否可以採集到線上 Log 快速定位並解決問題?你對自己開發的專案中用到的各種框架是否真的理解其原理,是否真的去翻過程式碼學習過這些優秀框架的實現?就拿 Android 開發來說,各種開源框架如 RxJava、Retrofit、OKHttp、ORM框架、熱修復框架、外掛化框架等等,如果你真的去認真學習過一遍,我相信已經遠超行業裡 90% 的工程師了。

同時在工作中要有不怕吃虧的心態,主動去承擔更多的職責;做的更多往往也意味著接受了更多的挑戰,獲得了更多的鍛鍊機會。

利用碎片時間系統化學習

很多人反對碎片化學習,但我並不完全認同這種看法。碎片化的時間既可以用來碎片化的學習,也可以用來做系統化的學習。很多人都指望能夠有一天,有一大片的時間,好好的、系統化的把計算機知識惡補一遍。所以買了演算法導論、深入理解計算機系統等等經典書籍放在家裡,等著有一天能夠有一大片時間,沐浴更衣、正襟危坐來好好學習。但是學了不久很快又被其它事打斷了,結果下一次又重新再來。最後往往只是把一本書的前幾十頁反覆看了好多遍,其實這種才是真正的碎片化學習。

而所謂的利用碎片化時間系統化的學習是指制定好完善的學習計劃,利用好每一個碎片時間,比如上下班的路上、等公交的時間、坐地鐵的時間、排隊的時間,甚至是蹲馬桶的時間來按計劃的、體系化的學習提高。

持續學習,堅持閱讀,保持輸出

技術更新迭代太快,而電腦科學之複雜也遠不是在學校的幾年學習就能完全學透的,這就要求我們保持持續學習。但往往很多人走出校門後就再也沒有正兒八經的學習過、衝過電,這也是為什麼我們畢業後會被那些優秀的工程師越甩越遠的原因。而我認為最好的持續學習的方式就是堅持閱讀了。你們看!優秀的工程師就算是掛著鹽水也要堅持閱讀的!!!???

我們和優秀工程師的差距在哪兒

另外學過的知識只有輸出出來了,才是真正的學到肚子了。向別人講述知識、寫作等都是很好的知識輸出方式。

鍛鍊自己的綜合能力

要成為一名優秀的工程師,光有過硬的技術是不夠的。出色的完成一項工作往往考研的是一個人的綜合能力。良好的表達能力、出色的會議組織能力、事情的推動能力、個人的成熟度等等都是需要我們在工作中去刻意的培養和鍛鍊的。拿表達能力來說,如果覺得自己表達上有所欠缺,就可以通過寫作、主動在團隊內做技術分享等等方式來鍛鍊自己。有時候,不逼自己一把你都不知道自己到底有多棒!

寫在最後

作為一個技術上的菜鳥,寫這樣的文章實在是有點慚愧。且算是給自己定個基調,與大家共勉好了,這樣也能督促自己不斷進步。

哦,對了!還有一點!!!優秀的工程師是不會抱著手機抖音一刷一晚上的。???

如果喜歡我的文章,就關注下我的公眾號 BaronTalk知乎專欄 或者 GitHub 吧!

相關文章