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

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

1. “博”與“專”上的迷失 假設說一個人的學習已經聚焦,並且學習的內容和自己實際參與的專案也相吻合,那麼是不是就沒有問題了?很不幸,答案仍然是否定的,在任何一個子領域裡,仍然需要進一步去考慮“博”與“專”的均衡。 對於軟體開發而言,設計是再常見不過,再簡單不過的一個詞了。可如果把視角拔高一點就會發現,單以設計而論仍然是一個不可窮盡的領域,我們可以快速掃描一下和設計相關的部分概念:
  • 面向物件分析與設計
  • 結構化分析與設計
  • 模型驅動開發
  • 契約式程式設計
  • 面向方面的開發
  • 基於元件的開發
  • 超程式設計
有些時候方法論也會和設計牽扯到一起:
  • 測試驅動開發
  • 敏捷軟體開發
如果感覺這個還不夠多,那可以去Wiki上查程式設計的正規化(paradigms )這個條目,那裡列了47種正規化,每個都和設計多少有點關係。 上述這些還只是說了設計,如果橫向展開,那麼在特定領域中必然還會牽涉到框架的選用、輔助工具的使用等等。這也就意味著,從博的角度來看,即使是在設計這樣一個看似狹小的領域中仍然是沒邊界的。 與此同時,把一個API研究的再透,也是低值人群,因為這種深入理解和單純會用某個API相比,從創造價值的角度看,差別不大。 這也就意味著對於大多數軟體開發人員而言,要去尋找廣博與精專間的均衡點:既不能閉上眼睛,也不能就用顯微鏡來看世界。而這一均衡點的價值則可用反木桶原理來說明:木桶原理說的是桶裡的水是由最短的一塊板決定的,但考量人的價值時卻是適用於反木桶原理,即人的價值往往由最長的一塊板決定。 考慮博和專的問題不能離開產品開發進行考慮,前面曾經提到過,產品開發往往和公司的現金流繫結的更緊,能為現金流貢獻力量的技術才是有價值的技術。而產品開發本身事實上對博和專的程度提出了最基本的要求,這種要求往往具有迭代的特質。為了形象的說明這一點,這裡舉一個通用的例子來進行一點說明: 在第一次跌代裡,往往需要達到兩個最基本的目標。第一個目標是可以為產品貢獻自己力量,但程式碼質量普通。這個目標如果達不到,一個人會失去自己的存在價值。 這時候最少需要了解某種語言(比如:C++)、某個平臺(比如:Windows)、某個IDE(比如:Visual Studio)和某些業務相關的知識(比如:列印體系)。這個範圍可以儘可能圈的小點,但用到的則要學透。比如:不管接觸到那個框架,都要去了解它的記憶體機制、執行緒機制、異常處理元件構建和國際化處理這些全域性性的機制,而不能只是瞭解某個介面怎麼用。 這並非是很高的要求,沒有這些就變成了“靠運氣程式設計”,寫完程式後還要祈禱他能跑起來。瞭解這些之後就可以負擔起部分開發工作,否則的話只能做旁觀者,沒法參與到實際工作中來。 第二個目標是把事情做好,並能負擔些層次更高的工作。這時候要比較深入的瞭解面向物件、結構化方法、設計模式、理解設計原則,並能把它們用好。至少要能判定,這個程式寫的好,那個程式寫的不好,同時面對需求能把工作進行下去。 前兩個目標是基礎,一般來講學校中基礎打的越好,這個階段越短。達成這兩個基本目標之後就可以結合情境來做進一步的選擇,可以認為這是博與專選擇上的第二次迭代。當然這時候也要謹記不要和實踐分開。 完成上述兩個層次後,可以有兩個方向可供選擇。
  • 可以進一步考慮專的問題,比如在特定領域裡把知識深化下去。做驅動就要理解作業系統的核心機制,做列印的就要了解頁面描述語言等,但這個時候要適當警惕邊際效應。
邊際效應是說,你讓一畝地從畝產500斤增加到1000斤可能只需要投入100塊;讓畝產從1000增加到1500可能就需要200塊;讓畝產從1500增加到2000則需要400塊了。 一個典型的例子是對C++的學習,C++是公認的複雜,如果想做C++的律師,那麼估計搞個10年可能夠資格了,但問題是把時間都投在這個上,投入產出比可能不好。而停在那裡合適則是個尺度問題,大致來講是可以靠時間彌補的細節問題,並不適合專到最底層。比如對於100萬行的程式,預先花時間去了解每一處細節,就有點過了。
  • 可以把博再推進一步,比如:熟悉專門領域的專業知識、熟悉多種既存框架的特性、熟悉提高使用者體驗的關鍵點。熟悉多種既存框架的特性的具體含義是:
設計某一種解決方案時,首先要考慮的就是是自己開發還是使用現有的模組。一旦決定使用現有的模組(包,框架等),那就要進一步考慮究竟用那個。 做這類工作時,如果沒有一定廣博的知識,做選擇的時候就會特別的艱難。 假使說現在公司內部要匯入一套專案管理系統,那麼做決定的負責人必須至少考慮所有下面這些事情: 自己從頭造,還是用現成的做二次開發? 用現成的,是用開源產品,微軟的還是其他公司的? 用微軟的話,是用MS Project還是基於SharePoint,還是混合?考慮License費用的話真的划算麼? 用開源產品,有這麼多選項究竟匯入那一個? 如果自己從頭造,那麼是基於微軟的技術,還是基於LAMP這樣的技術? 使用什麼框架? 如果要做,用什麼語言? 一個人很難精通上面所有的領域,但當做選擇時,完全沒有概念也是災難性的。 此外,考慮博與專平衡點時似乎有一種特例,鑽研特定演算法的人,從一開始就只往專的方向發展,並不會考慮其他。比如:鑽研TTS的人,可能幾十年如一日只要專注於TTS就完了。 至於具體選擇那個方向,則要根據自身情形來定。總的原則是要以當下工作為根基,以實用為目的甄選各種知識,並追求平衡點。 大致上講,期望做技術專家的更適合前一個方向,而期望做技術管理的則更適合後一類方向。  學習軟體工程的時機與必要性
簡單來講越是沒實踐經驗的人越不適合學習軟體工程,越需要規劃整體把握全域性的時候越需要學習軟體工程。 軟體工程中覆蓋的元素非常繁雜,可以有管理、流程、開發模型、估算、分析設計方法等。這無疑會把知識面擴充套件的很寬,一旦沒有根底,就很容易變成紙上談兵,誇誇其談。 在眾多軟體相關的知識中,軟體工程絕對是很特別的一個。很多人很鄙視軟體工程,說:我一看到軟體工程的書就直接略過;與之相對應,很多人很推崇軟體工程,會花很大的心思去研究敏捷、CMMI等。 剛入職場的程式設計師大致上是討厭軟體工程的,因為這東西離自己的實踐有點遠,並且主要是新增束縛。但既然更加複雜紛繁的歷史都可以總結出規律,忽視軟體開發的內在規律無疑的對有志於成為管理者的人是不利的。
真要學習軟體工程,不太適合從抽象層次很高的教科書開始,而適合從《程式碼大全》這樣與實際關聯比較緊密的書籍開始。 在國內軟體工程的落地似乎始終困難,軟體工程相關名詞始終在不停的變換(ISO,CMMI,敏捷等),但實際能落地起作用的卻不多,這最終導致了一種弔詭的局面:剛對一個絕望,就開始對新的一個報以希望,並在這兩個簡單的步驟上做無限迴圈。這種狀況也許有其更深層次的原因,比如生存壓力過於強大導致工程力量的長遠價值被漠視,進而使方法論並不為解決現實問題而存在,而是為了證書而存在。很難據此就說軟體工程毫無價值。  2. 錯過人生中的好時機 沒畢業的程式設計師或者剛畢業的程式設計師往往感覺空餘時間比較充沛,還很苦惱不知道如何打發時間,但實際上一個人一生中可以用於充電的時間遠比想的少。一旦錯過時機,往往悔之莫及。 對於大多數人而言,人生就像個模板,小處還有偏差,大處卻基本相同。 20~30歲這個階段可以講是黃金時期,這個階段裡,家庭負擔較小,可以自由支配的時間較多。當然撞到了很特別的、需要瘋狂加班的公司只能另算。 30歲之後因為娃娃出生等,家庭上的時間開銷增加,個人可支配時間變少。其中很大一部分人還有很大可能會面對電視劇裡常說的婆媳矛盾,讓你每天心緒不寧。 40歲之後,家庭瑣事會進一步增加,典型的上有老下有小。實在運氣不好的自己也會生點病---頸椎病、腰間盤突出、胃病大概可以入選程式設計師的三大職業病。 50歲之後,時間上會再次解脫,但可惜的是自己也老了,時機不在。 如果把人生按照年齡畫一條拋物線的話,40歲左右一個人可以達到的人生的頂點,未來再突破的機率則變小。從歷史人物來看,大器晚成的不是沒有,但真的很少。 用心觀察就會發現,招聘啟示裡經常會註明年齡要在35週歲以下或者40週歲以下,除非是招聘高層。這反過來意味著如果沒有到高層,人生會在40之前定型,之後有下滑危險(如遭遇不景氣、公司倒閉等)。對程式設計師而言,這種風險尤其的大,因為很可能你辛苦掌握的知識體系被更迭掉了。 學習本身無疑的是需要順應這種自然規律的。 很多人很大的一個錯誤在於,在黃金時期,沒做什麼積累,就顧得享受生活了,而一旦意識到積累的必要性時,卻又受困於諸多瑣事而欲振乏力,最終人生高度有限,並迅速走低。這就是現代程式設計師版的“少壯不努力,老大徒傷悲”。 基本上講,35歲以前要把需要花大量時間,比較硬的技能,學習曲線陡的技能掌握,具備工作所需要的所有主要技能,而35歲之後則主要關注知識的更新和某些軟技能。 學習時添水戰術效率真的很差,每次點一根火柴燒水,一億年水也燒不開一壺。同時,比較硬的技能(比如:Donald Knuth的《計算機程式設計藝術》)往往是需要大塊時間投入的,但年紀越大時間越呈現為碎片化,越難搞定硬的知識---先天就容易造就添水戰術。比較軟的技能,則可以用碎片時間來學習,比如:提高PPT的製作水平,提高表達能力。 如果能夠安排好自己的時間和軟硬知識的關係,那麼就可以在特定基礎上做積累,小步前進,使自己的價值越來越高。從這個角度看,年輕絕對是一種債務,大多數人必須在他沒完全結束前,還掉所欠的東西。 那麼具體來講那些東西是比較硬的,要在35歲前搞定呢?這因目標而異,但下面這些專案應該具有非常高的通用性:
  • 精通一門最常用的語言
  • 瞭解一個最常用平臺的基本機制,比如:記憶體管理、執行緒機制等
  • UML圖和麵向物件分析設計方法
  • 設計原則,如:職責單一等
  • 設計模式
  • 《程式碼大全》裡講的一切
  • 精讀一個知名的,但有點規模的程式。這點上要感謝開源專案給我們提供了這麼多優秀程式。但要謹防好高騖遠,動輒挑戰Linux核心,精讀是關鍵。
  • 累積一定的程式碼量,比如:獨立的完整做過一個數萬代碼行的東西。這裡的關鍵是完全自己打造,一定不要拷貝貼上。
  • 掌握基本演算法和資料結構(可以不自己寫,但至少要知道其複雜度和區別)
  • 養成一種清晰的編碼風格
  • 有自己的專業(金融、高併發網站,影象處理,TTS等)
學習英語的時機和必要性 總的來看,程式設計師學習英語是一項投資回報率相對比較好的投入。從目標上來看,程式設計師未必一定要口語流利,但最低要達到閱讀英文資料沒有障礙的程度。這裡面有一個微妙的事情,一旦英語閱讀問題較大,查詢問題會習慣用百度,這天然會限制一個人的視野。不是說百度自身有多不好,而是說英語的世界裡有著更多更精彩的內容。不管喜歡不喜歡,我們必須承認一種現實,在IT的世界裡英語是一種世界語,一方面是由於美國公司的強大,一方面則是由於開源選擇了英語。這最終導致IT世界裡的新動向、解決問題的小技巧、網站的架構等等都要到英語的世界裡去找。在StackOverlow很容易找到各種小問題的答案,在Quora則很容易找到各種網站的架構。 從學習時機來看,這件事情特別應該在大學裡面搞定,如果不行至少也要在畢業1~2年內達到閱讀無障礙的程度,當然希望加入外企還需要額外的付出。從學習方法來看,學習外語真沒什麼特別的竅門,堅持並投入時間即可。  3. 停止知識更新 對程式設計師的增值而言,人生裡最大的陷阱也許是為安全的假象所欺騙而徹底的放鬆自己。這種狀況在生存環境比較惡劣的情形下不太會發生,但在壟斷企業或某一領域中絕對領先的企業裡則容易滋生。發現自己是否停止知識更新了並不困難,比如:一年一本書沒看,一年一點新知識沒接觸,一年中工作負荷基本不滿等都可以成為一種訊號。 這真的是溫水煮青蛙,一旦到了三十幾歲,並在這種環境中呆習慣了,那麼再想跳出來,基本沒可能。唯一能做的事情是,祈禱公司不要掛掉,公司也不要來場運動,進行人員的大換血。孔夫子說:日當三省吾身,這是很有必要的,至於認識危險後能否做點什麼,那就是事在人為了。
  • 技術人員的知識更新
接觸一個新的崗位後,大致要經歷一個學習並逐漸勝任的過程,這個時間段裡大多數人的學習熱情是很高的。一旦基本勝任之後,事情就有了變化。 很大一部分人可能會感覺,反正工作也就用到這麼些知識,學習其他的也用不上,因此開始把自己封閉起來,不太看書,不太看技術新聞。 這其實很危險,因為這種做法等於把自己綁死在當前這份工作上。而任何一個產品都有自己的生命週期,一旦一個產品的生命週期結束時,碰巧其所用的技術也已經過時,那麼當事人就會很尷尬。因為產品可以結束,生活卻還得繼續。 這裡面一個非常經典的例子是MFC。微軟的這款產品的歷史非常悠久,從1992年釋出到2012年幾近存在了20年時間。隨著90後程序員的逐漸出現,馬上這款技術就要變得比程式設計師的年紀還要大了。 即使到今天,很多桌面應用仍然是基於MFC開發的,這可以通過檢視程式包的dll依賴來很容易的進行驗證。MFC是一個很大的池子,有深度、有歷史。想把MFC的類繼承關係、訊息機制、框架結構、RTTI、序列化都搞清楚還是要很花一點時間的。 現在我們假設一款龐大的企業應用是基於MFC開發的,一個程式設計師也通過幾年的努力瞭解了MFC,瞭解了應用本身,並可以負擔起Bug修正,新功能追加等任務了。 接下來這個程式設計師似乎沒什麼好學的了。因為MFC的更新幾乎已經停滯,因此對MFC的學習幾乎不需要花太多的時間了。現有程式碼也理清楚了,也不需要再花很多時間學習了。現有程式也比較好的滿足了企業的需求,推倒重來的可能性幾乎沒有。 那這個時候這個程式設計師不需要學習了麼?答案一定是否定的。 這裡面蘊藏著一個天大的矛盾。 從企業的角度看,一定是需要一個團隊來維持這個程式的開發的。但從個人的角度看,如果把所有的青春都耗費在老技術上,那麼一旦老技術退出歷史舞臺,個人該何去何從? 還是上面的例子,假設說一個人持續投入在這類開發上,當他45歲的時候,當前產品生命週期結束,世界變的只有移動開發和雲端開發,那麼只擅長MFC的他該何去何從? 如果真的如此,這個人就被逼到了死角里,人生很可能產生巨大滑落。所以一定不能認為所學足夠而停止技能的更新與學習。  從具體應對措施來看,一是要參照知識的地圖,橫向擴充套件知識的廣度,比如不只要盯著程式碼,也要了解業務;不只關注開發也關注一點估算;二是提升可流動性比較好的東西的掌握程度,比如:面向物件分析與設計,這樣跨越到其他技術時就能夠比較平緩的進行過渡。三是要爭取輪換崗位,爭取多種實踐機會。
  • 管理者的知識更新
到現在為止大部分人認同,管理者是需要懂技術的。從邏輯上看“懂”基本上是不瞎指揮的前提,所以這可以稱為中國版的“現場主義”,估計爭議不大。 那關鍵問題就是究竟要“懂”到什麼程度? 如果說兩個人,一個選擇了管理方向,一個選了技術方向。接下來要求管理方向上的人技術水平要和技術方向的一樣,那麼除非這個人特別天才,否則不太可能。正像前面所說,這是由於這兩個方向的“Key”不同所造成的。  如果把目標設定為確保最終產品的成功,同時假設管理者有更高的決策權,那麼管理者必須在下面這些方面有技術感覺。  從做產品來看,要想成功,有兩個關鍵維度需要同時進行把握,一是產品的概念完整性的把握;一是用合適的手段去實現這個產品。 前一個話題很老,《人月神話》就有提及,但實踐中卻總是被人忘記。好的產品必須貫徹某一種統一意志,iPhone、微信又重新驗證了這一個老的原則。 機械拼湊的產品雖然融合了很多人的想法,但往往是平庸的,並且在專案執行過程中,往往是出錯的根源。很像是雖然有法律,但每個人有自己的理解,各行其是這樣一個狀態。這種概念完整性是管理者第一個需要有所把握的事情,其次就是解決如何去構建產品這個問題。為達成這一目標在下面這幾個方面上,管理者要有自己的理解,至少要有自己的原則: 下面簡單列舉幾個比較關鍵的考量,這和前面論及的如何往博的方向發展有點重疊: 使用現有產品還是自己開發 比如:那些模組適合自己搞定而那些購入就可以了。購入的時候要遵循怎麼樣的標準去選擇。 使用那種平臺技術 比如:是使用微軟的技術,還是開源的技術。 現行架構是否可以達成產品目標 比如:在硬體加軟體可以同時支撐的併發數目。 程式碼可維護性如何約束 這要求必須熟練掌握一些原則性的東西,比如:什麼資訊隱藏、正交分解、抽象是否充分等。以及一些無歧義指標,比如:圈複雜度,單元測試的收益平衡。 那些環節必須固化為流程,那些一定要團隊自由決定 比如文件化要到什麼程度才合適,不同階段間什麼是必須的輸入輸出。  ... ... 假設說有人不這麼認為,而是在做了管理後,表現出足夠的惰性,不再持續更新自己的知識體系了,那麼會發生什麼事情? 這時候會很可能會管理倒置。即管理者是名義上的上級,但基本失去對現場的把握,所有的決策完全依賴於下屬。得力下屬不在,各種決定就只能靠瞎蒙,最終變成只會溝通的管理者---即使被食人族吃了也不會有人注意到,因為存在價值已經被無限稀釋,變成了一個象徵性的符號。也可能會和下屬爆發激烈衝突。因為這類管理者沒有自己的立場,上面有任務只能下壓。結果同實際情況偏離萬里,不具有可實現性,這類管理者無法對自己的上司陳述,也就只能向下轉移壓力。 不管是哪種,一旦到這種地步,其實是趨於失敗,只能祈禱食人族不要來。 為什麼中層管理者也要堅持知識更新? 在IT行業流傳著一個很有名的關於食人族的笑話,這個笑話說的是: 兩個食人族的人應聘進了某家大公司,公司人事主管知道這兩個這夥每天都要吃人,於是警告他們:“如果你們膽敢在公司吃一個人,你們就會立即被炒掉!”兩個食人族唯唯喏喏地答應,表示絕不會在公司吃人。兩個月過去了,公司平安無事。 突然有一天,公司發現負責打掃公司衛生的清潔工不見了。於是人事主管非常氣憤,找來兩個食人族怒斥,並當場炒掉了他們。出了公司大門,一個食人族馬上對另一個抱怨起來:“我一直警告你不要吃有在做事的人,你就是不聽!我們兩個月來每天吃一個經理,沒人發現。你看現在吃了清潔工,他們馬上就發現了!你真是個豬!” 這個笑話嘲諷的是某些大公司大企業病發作,人浮於事。大企業病的成因很難一下子說的清楚,但結果卻比較明顯,一定會導致較多人成為中層管理者。如果說成功的企業天然有感染大企業病的趨勢,那無疑的中層管理者也天然有著膨脹趨勢。從個人角度看,成為被食人魔吃掉也沒有人在意的經歷並非是什麼好事,因為這意味著存在價值減弱,也不需要什麼知識更新。一旦面臨裁員這類事情,這個人很可能已經失去了面對殘酷競爭的能力。