1. 程式人生 > >程式設計師生存定律--成長路上常見的坑

程式設計師生存定律--成長路上常見的坑

程式設計師生存定律這系列的目錄在這裡:程式設計師生存定律--目錄

喜歡從頭瞄的,可以移步。

-------------------------------------------------------------------------------

前面講到了程式設計師成為高手需要有一張地圖,藉助這樣一張地圖,程式設計師可以嘗試成為架構師、Guru或者純管理者。但這條路總是不會那麼順暢。

升級練功流的網文中總會給修仙的主人公設定下幾大關卡,比如:金丹難成、元神難成、成了元神後還有天人五衰等等。沒有這些關口,情節很難推動,所以仙俠類的網文幾乎無一例外依賴於這類設定。這一傳統甚至可以追溯到《西遊記》和《封神演義》。

拿這個來對照程式設計師的增值道路,就會猛地發現,升級練功流也不完全是扯淡。不管走那條道路,程式設計師的修煉路上同樣的也有三災九難,要想成就高手,還是得一個個跨過去才行。如果一個程式設計師達到一定高度後再回頭觀望,那就會發現自己的同學、曾經的同事總是會因為這樣那樣的原因倒下去。這並不是一個簡單的天道酬勤就可以敷衍的行當,下面就讓我們來具體看看,究竟增值過程中可能遇到那些陷阱,掉到坑裡又需要付出多大代價才爬的出來。 

1. 學習失去焦點

軟體行業裡有幾個經典的題目,每過一段時間就會被翻出來PK一下,比如關於程式語言優劣的比較等。其中一個經典題目是軟體和數學的關係。

從結果來看,一派人認為數學是軟體的基礎,而另一派人認為數學和軟體沒什麼太大關係,除非是在某幾個特定領域裡。如果你用心觀察過這事情,你就會發現這事情特別有意思。

比如說:

2011年,CSDN轉了一篇,叫:“數學是成就卓越開發人員的必備技能”的文章,在文末作者說:

那麼,數學對所有事都有利麼?這事情很難說,我對我現在的處境十分滿意,或許你也如此,但這都和潛能有關係。如果你是協作世界的一名開發人員,你真的不需要數學。如果你樂於你的整個職業生涯是這樣的:在工作時間中做企業CRUD應用,或在閒暇時間滑翔跳傘或極限水上滑板(或其他各種時髦的極客運動),也分配較多時間在SpringHibernateVisual Studio或其它東西上。那些特殊的職位並沒有真正限制你的潛力,你能變得極具價值,甚至可深入追求。但是如果你想為多樣化的職業生涯而奮鬥,想要有能力嘗試幾乎所有涉及程式碼的事,從資訊檢索到

Linux核心。總之,如果你想成為一個開發人員、程式設計師和電腦科學家的完美組合,你必須確保你的數學技能達到標準。長話短說,如果你在數學方面有一定天賦,那在軟體開發領域中所有的大門都是向你敞開的,如果沒有,那你就安安心心地做CRUD型工作吧!

總的來看,這個作者認為數學很關鍵,得學。

而在2012CSDN又轉了篇文章,叫:程式設計需要知道多少數學知識?在文章裡作者說:

數學和程式設計有一種容易讓人誤解的聯絡。許多人認為在開始學習程式設計之前必須對數學很在行或者數學分數很高。但一個人為了程式設計的話,需要學習多少數學呢?

實際上不需要很多。這篇文章中我會深入探討程式設計中所需要的數學知識。你可能已經都知道了。

對於基本的程式設計,你需要知道下面的:

加減乘除—實際上,電腦會幫你作加減乘除運算。你僅需要知道什麼時候運用它們。

模運算—模運算是用來計算餘數,它的符號通常用%百分號來表示。所以23除以7等於3,餘數是223 mod 7 = 2

判斷是奇數還是偶數的模運算—如果你想知道一個數是奇數還是偶數,用它mod 2來作模運算。如果結果是0,它就是偶數。如果結果是1,就是奇數。23 mod 2等於1,所以23是奇數,24 mod 2等於024是偶數。

對一個數作百分數運算,就是用這個數來乘以一個百分數。譬如你要得到27954%,就是用0.54*279。這就意味著為什麼1.0等於100%0.0等於0%

知道負數是什麼。負數乘以負數等於正數。負數乘以正數等於負數。就這麼簡單。

知道迪卡爾座標系統。在程式設計中,(0,0)代表螢幕左上角,Y座標的正軸往下。

知道勾股定律,因為它是用來計算笛卡爾座標中兩點之間的距離的。勾股定律a^2+^2=c^2(x1,y1)(x2,y2)兩點之間的距離等於((x1x2)^2+(y1y2)^2)

知道十進位制、二進位制、十六進位制。十進位制就是我們通常用的十個數:0-9。通常認為這個十進位制系統是人類發明的,因為我們有十個手指。

總的來看,這個作者認為數學不太關鍵,大多時候可以不學。

你如果持續關注這事兒,各種極端對立的觀點絕對會吵爆你的頭。但這事情其實不可能有結論,因為被對立起來的兩極都是太大的概念。

比如說:如果把軟體開發縮減為應用軟體的開發,那爭議性就會降低很多。

這裡的關鍵問題是,假如一個人的目標是應用軟體開發,卻花了10年來學習數學,接下來在實際應用程式開發過程中,每天面對的是UI佈局、IDE使用、圈複雜度控制、面向物件使用、設計模式的使用和類庫的使用這類問題,那麼這個人就會發現數學其實沒啥用,他等價於因為失去焦點而失去了10年。

這裡想表明的是,一旦誤讀了知識與目的間的因果關係,那麼學習就會失去焦點,進而造成負效應,畢竟相對於人的可承受負荷而言,這個世界上的知識不是太少,而是太多。

一般的認識是隻要學習就必然有所得,所以對人生的影響一定的是正面的。但實際上這個想法是偏頗的,尤其是在軟體行業裡。

在軟體行業中,這種風險之所以異常突出,就在於前面提到過的軟體的兩個特質:更迭速度快和子領域眾多。這兩個因素導致軟體相關的知識是爆炸性增長。

而避免“失去焦點”這一陷阱的第一關鍵則是分類:對軟體開發進行分類,對軟體所關聯的知識也進行分類,形成自己的大局觀和整體檢視。

前文曾經提過集中對知識進行分類,對軟體進行分類的方法,這裡再補充一個對繞過這一陷阱有幫助的分類方法,它來自《軟體成本估算:COCOMOII模型方法》這本書。

書裡面把軟體分成了下面幾個類別:

終端使用者程式設計(一般的應用程式)

應用程式生成器(開發工具等)

應用組裝

系統整合

基礎結構(OSDB等)

在進行分類的同時,書裡還給出了一組資料,即95%的人從事的是終端使用者程式設計。

這個分類的意義在於,通過它我們可以認識到每一類別背後隱含的知識需求其實不一樣,程式設計師則要根據自己的目的設定焦點。再來看一個具體的例子:

演算法領域中,最經典的書籍恐怕是Donald Knuth的《計算機程式設計藝術》。對此書的評價已經不止是高那麼簡單了,如:

這部多卷專著是公認的對經典電腦科學最權威的描述。幾十年來,無論是學生、研究人員還是程式設計從業人員,本套書的前三卷都是他們學習程式設計理論、進行程式設計實踐的寶貴資源。 

這是一套集所有基礎演算法之大成的經典之作,當今軟體開發人員所掌握的絕大多數計算機程式設計的知識都來源於此。 

---Byte

那麼是不是每個人都應該把這書讀一讀?這書的前三卷大致有2000頁,上班的人都讀通估計要1~2年這個樣子。

至少在我來看,答案是否定的。具體情況要看你做的是那類軟體,你人生的下一步在那裡而定。

假設說一個人做的是終端使用者程式設計(比如:財務類軟體),並且目標也是在這個方向上繼續深造,那麼你讀這書其實是在浪費時間。

這是因為在終端使用者程式設計上,自己去寫演算法的機會非常的少,甚至可能沒有。反倒是業務領域知識(會計知識)、OO、設計模式、甚至於估算這些知識都比研究演算法更有價值。 既然如此,那麼從務實的觀點上看,為什麼去學習不能在可見範圍內創生價值的東西,而不是去學習立刻可以變現的東西。走極端的人會找出需要寫演算法的例子來反駁上述立論,但點不足以表徵面,即使偶爾需要自己瞭解下演算法,真就值得花那麼多時間去學習麼,為什麼不盡可能借鑑現成的。

而在基礎結構性的軟體開發中,情形就不同,這時演算法無疑是非常核心的東西。所以Google這類公司的面試中往往非常強調演算法。

這裡最關鍵的就是聚焦,聚焦的根本則是要在限定時間範圍內創生價值。

從方法上講,聚焦就是找到一個適合自己大小的區域,然後做深。才華橫溢的不論,一般來講,橫向穿越和縱向穿越都不太行,除非已經基本窮盡當前的領域。縱向穿越是指從底層穿到上層(想想開發網路協議的和用網路協議的),橫向穿越則指橫跨太多的領域(想想從核心驅動跨越到資訊管理軟體)。

其實如果一個人真的擁有無限的時間資源,那麼什麼時間點學習什麼就變得不太關鍵。但這是不可能的,同時一個人的學習時間遠不像想的那麼充沛。這點會在後面探討。 

在清楚自己的目標後,再配合前面提到的知識分類地圖,那麼避開這一陷阱的機率就大了很多。

2. 學習與實踐相分離

喜歡看網文的很少有人會不知道起點,不過估計很少有人注意過起點給小說分類的標籤。在網文小說裡有很多個流派,其中一個叫做“扮豬吃虎”。這個流派的基本特徵是很厲害的一個人要假裝很菜,最後在關鍵時刻力挽狂瀾。這個流派十分有人氣,大概僅次於“升級練功”,而遠高於“重生”、“轉世”這類的流派。

網文是絕對的市場導向,所以這個現象可以從側面說明很多人喜歡“扮豬吃虎”或者說潛意識裡有著“扮豬吃虎”的情節。“扮豬吃虎”這事兒小說裡看著很爽,但挪到現實裡來很容易讓人掉到學習陷阱裡。更可怕的是,現實裡有這種心思的人其實也還很多。

有時候會看到這樣一種現象:很多人自學的東西和工作中用的東西完全沒關係。比如:一邊用著C#Web開發,一邊自己學習著C/C++做嵌入式。

這事並不一定不對,只能說非常危險,很可能會導致那樣都沒有高度。我們得承認當人生被錯位的時候,往往只能這樣來改變命運,這是沒辦法,也是正確的。但首先要認識到這樣做是相當低效的,低效到一定程度後對的事情也並不一定有結果。

CSDN曾經做過一份薪酬統計(http://www.programmer.com.cn/5877/),這裡面有三個與上述身在曹營心在漢現象有關聯的結論:

一是73%的程式設計師對自己的薪資並不滿意。

二是各個主流開發語言上的差異並沒有想的那麼大。雖然C#開發者中月收入小於5000元的比例最高,但5000~10000這個群體在主流開發語言上相差並不大。

三是平均來看,收入增長和工作年限正相關。當然認為到那個歲數工資自然就高了是很危險的。

對薪資不滿意應該是程式設計師希望跨界的一個原動力,但收入和年限正相關,與語言非正相關卻說明單純從功利角度看跨界並不明智。因為假設一個人Java語言用過三年,C#用過三年,總的來看收入水平更可能處在三年的水平上,而不是六年的水平上。

軟體是一種固化的思維,這就軟體開發更多是一種實踐而非是一種理論。軟體開發內的很多領域,總體上看體現的是複雜而不是艱難,不論是前端開發還是驅動開發。

講到到這裡就有必要簡單區分一下“複雜”和“艱難”。考試出題可以有兩種方法:一是每道題都不是很難,但題量很大;一是題量很少,但每道很難。從結果來看,兩類考試方法下,得高分都並不容易,但其難度的來源卻並不相同,前者更多的體現為複雜,而後者卻體現為艱難。

在軟體行業裡,除了一些專門的領域,比如影象演算法等,軟體開發則更類似於前者,所以經過培訓後大部分人都可以做軟體開發,進入門檻並不高。

解決艱難問題時,天分很重要;解決複雜問題時,練習很重要。所以軟體開發的學習過程中,實踐很重要,純理論知識的權重較低,當然基本的演算法複雜度還是要明白的。

這也就意味著脫離專案實踐的學習投入產出比往往會差。比如說:程式設計中常見的多執行緒問題。如果單純從學習的角度看,建立執行緒本身並不複雜,掌握各種執行緒同步方法(事件、訊號燈、互斥量等)也並不複雜。寫簡單例子的時候,也很少會出錯。但一旦落到具體的場景下,雖然多執行緒的本質沒變,但沒經驗的人幾乎一定會在涉及多執行緒的程式碼上導致一會兒出,一會兒不出的問題。

再比如說:你可能看了很多設計的書,但從來沒有從頭到尾寫過什麼程式,總是在既有程式碼上修修改改,或者只是完成幾千行程式碼的小工具,那麼你的設計知識是很難融匯貫通的,也還是無法很好的承擔大系統的設計工作。

這點上有一個旁證,根據統計最多的Bug是由新手導致的。這從側面說明,能做和能做好之間的鴻溝需要大量的實踐來填平的。

在這樣一種前提下,期望先選個工作,再自己學習,努力轉行這樣的想法是損失很大的。單純從增值效能上看,解決這點很簡單,除非必須放棄當前的工作領域,否則要以當前參加的專案為根基展開學習,這樣才能比較好的調和學習和實踐。

而除非一個工作領域過於偏狹,大多時候在程式語言(C#→C/C++)、不同領域間(圖形處理→地理資訊系統等)穿越損失可能更大。

至於如何在“博”與“專”間平衡,如何選中更適合自己的工作領域,將在後續章節裡陸續談到。

------------------------------------------------------------------------------

關於我自己的各種資訊,在左邊欄可找到,想了解下寫這書的人是不是騙子和大忽悠的可以瞄。

最後希望感興趣的支援V眾投,感覺上這應該是國內最靠譜的生活購物等的問答社群了吧,都是朋友給朋友做的答案,同時實行一人一號,一人一票制度,想找什麼答案關注公眾號:vzhongtou(左側有二維碼)就行了