819A - 如何成爲一名職業程序員

修煉一名程序員的職業水準

一、掌握基礎知識:十六年寒窗的持續積累
 
計算機組成、操作系統原理、彙編語言、數據結構、編譯原理、數據庫原理、軟件工程、結構性設計語言(PASCAL、C)、面向對象設計語言(C++、C#)、計算機網絡等,你最好還懂一些算法分析、分佈式系統、計算機圖形學、形式邏輯、人工智能原理、軟件設計模式、軟件構架/框架等研究生的課程。

二、在實踐中提高:成爲一名高水平的Coder

通常,你在工作中都會用到某一種單位/公司固定的操作系統和編程語言開發環境,比如Windows、UNIX、LINUX等操作系統,又比如用VC、VB、 PB、Delph、JAVA、Motif/XWindow、QT、OpenGL、OpenInventor等編程語言和開發環境,我們在後面把它們合稱爲開發環境。
其實你既對又不對,對的是單從使用的角度而言,你確實用不上開發手冊的大多數內容,比如龐大的VC開發類庫和複雜的開發環境,你在實際工作中能用到的不到總數的1/10或1/5。不對的地方在於,你用到的部分不是孤立存在的,它們是整個體系中的一部分,只有對整個體系有了一個較完整的瞭解,才能得心應手、隨心所欲地用好你用到的部分,你纔算初步具備在這種開發環境下進行Coding的職業水準(還遠不夠程序員的職業水準呢),而這只是剛開始。

1、開發指南/教程、參考手冊

如何才能真正掌握一種開發環境的全面的知識呢,最原始的辦法就是讀(1)開發指南/教程、(2)參考手冊。

一般來講,學習開發指南/教程時,你如果是一個認真的人,都會完成5/10~7/10左右內容的學習和練習,如果你想成爲職業選手,就應該完成9/10以上內容的學習和練習。

參考手冊不同,大多數所謂的“程序員”們只是用到了才翻翻,這差的太遠了,你應該象讀開發指南/教程一樣,每個環節都要讀,比如VC,參考手冊中的每個類,類的每個函數,都要讀上幾遍,它們往往是一小夥一小夥地糾纏在一起使用的,開始時讀得你毫無頭緒、心煩意亂。不要緊,還有一手呢,如果你開發環境安裝的全面,它們往往都有開發商做的demo例子可看,你就進入另一個境界了。

開始時你關注demo中的具體技術,後來你發現這些demo的程序寫的都還算不錯,結構簡單但合理。如果你真的用心,就一定能發現一些個別的demo是極品,它所展現的程序邏輯結構你是設計不出來的,你現在有點更關心它的程序設計構架,甚於對你原始目的(某種相關的技術/技巧)的關注。

這時的你,開始了從一名Coder向一名Programmer的轉變,你會忍不住要看看開發商提供的源程序,比如.h和.cpp,通常你會找到include路徑下所有的.h程序,你才知道,哇!好多好多東東在參考手冊中都沒提到,你要學的太多了,沒時間顧及其它的業餘愛好了。

現在知道爲什麼程序員是年輕人的職業了吧,你要有足夠多的時間才行,即使你的智商有160。如果你走到這一步,在你工作的團隊中,已經是經常有人向你請教技術問題,經常有人請求你幫忙debug,你已是公認的“高手”了。

別得意,因爲你仍然是個Coder。爲什麼這麼說呢,你想想,你已深入瞭解了這個開發環境中的各種技能,知道一名Coder如何用好這些東西,可是你能設計的出提供給Coder們用的東西嗎?唔……,你想了想,可能還不太行。對了,就是這樣,你還是一名小我境界的程序員呢,本質是個Coder,當然已是一名高水平的Coder了,然而你需要進一步登堂入室才能成爲一名真正的程序員。

2、兩個挑戰

讓我們繼續吧,通常你都是從精通一種編程環境開始的,假設你已經較爲精通在Windows下用VC開發軟件了,這時在技術和技巧方面你將面臨一小一大兩個挑戰。

第一個小挑戰是如果公司/單位改換了開發環境,比如用LINUX下的QT交互語言工具進行開發,你不過是把前面掌握VC的過程再來一遍,由於在主觀上經歷了VC工具的學習過程,在客觀上各種開發環境都有太多相似的方面,這回你掌握的應該較快。

要小心,在這時第一次誘惑之門打開了,因爲你感覺良好,看!這回這麼快,我就這麼好地掌握了新的開發環境,你開始關注其它暫時還用不到的同類環境,比如VB、Delph、JAVA,如飢似渴地掌握各種開發工具,證明自己的學習能力和價值。

但你忘了一點,你仍然是個Coder,只不過是一個在好多開發環境下都能編程的Coder,就像你生活在中國,因而精通了漢語,工作需要你又掌握了英語,然後你就來了勁,把俄語、日語、阿拉伯語、拉丁語,等等等等,都學習個遍,我只能說,有點BT。你忘了自己是個職業人,同一類的東西工作中用得到才需學習。太多太多的Coder們喜歡在一起比較和炫耀自己會掌握了幾種開發工具,不信你看看招聘時的求職書就知道了,sigh!他們中絕大多數人永遠都只能停留在這個層次上,心浮氣躁,一生都再也當不成真正的程序員了。

總結一下,其實你在這時需要的是對自己掌握新開發環境的能力的自信,而不是一遍遍地重複來證明自己。

第二個大挑戰就是你明白了只掌握VC是不夠的,你發現自己有點淺薄,有很多東東你會用但你不太懂,很多方面支持VC編程的知識你都沒掌握,比如操作系統的源碼、網絡協議知識、Windows 的註冊表、進程和線程的基礎知識、硬件驅動方面的知識、ActiveX、 Windows 龐大的 API,又是一個等等等等,這些基礎知識的學習和掌握可是要花費大量時間的,你再一次深切地感到時間太不夠用了,因爲這時的你大概有許多俗務纏身了,所以有點沮喪,還不用提IT業每天不知有多少新東西在發佈,永遠都跟不上,越拉越遠了。哎!

彆氣餒,振作一點,你還是忘記了自己是個職業人,既然好多東東在工作中你永遠都沒機會用,那麼幹嘛要學呢?用什麼才學什麼,最多預測到馬上要用什麼,先一步學什麼好了,要知道沒有人是真正的、無所不精的全科大夫,除非你是神,但如果你還在耐着性子看這篇文章,你肯定是個人嘛。

OK,一般工作後三五年,你經歷了上述過程,經受了誘惑和考驗,終於明白了一個道理:你要的是強勁的學習知識的能力,是對某種軟件知識/技能的有深度的精通,一種摸到它的根的深度,而不是已掌握的技能的種類和數量。這時無論誰用他掌握了多少種你不會的技能來嚇唬你都沒用,你對他的層次只有蔑視。

通過幾年的學習和工作,要記住最重要的一點,永遠最重要:對自己學習IT知識能力的自信,一個程序員一生都要不停地進行高強度的學習,用心問問自己,有沒有這個自信?別用虛榮心來騙自己哦,如果沒有的話,那就不必花費你寶貴的時間向下看了,作者在此感謝你有耐心看到這裏,現在建議你關閉這篇文章,趁着年輕,當機立斷轉行吧!
 
三、注重邏輯:成爲一名職業程序員

我們在前一節提到過,“你發現一些個別的demo是極品,它所展現的程序邏輯結構是你設計不出來的,你現在有點更關心它的程序設計構架,甚於對你原始目的(某種相關的技術/技巧)的關注”,其實你是在關注這個demo程序作者的思維邏輯,所有程序的本質就是邏輯。

技術你已經較好地掌握了,但只有完成邏輯能力的提高,你才能成爲一名職業程序員。打一個比方吧,你會十八般武藝,刀槍棍棒都很精通,但就是力氣不夠,所以永遠都上不了戰場。這個力氣對程序員而言就是邏輯能力(其本質是一個人的數學修養,注意,不是數學知識)。

邏輯能力也是逐步提高的,開始時你一定是用直觀的邏輯能力來編程的,怎麼想就怎麼編,不對就再改,在改進中提高自己的邏輯能力,從直觀邏輯能力提高到抽象邏輯能力,這是很正常的。提前說一句吧,到達邏輯能力的至高境界,其表現是用數學語言來描述問題和問題的解決辦法,高度抽象!好,說回來吧,你要提高邏輯能力,最快的辦法就是讀別人寫的結構優秀的程序。優秀的代碼是百讀不厭的,暫時放放對其中某種技術和技巧的關注吧,你要推導和學習的是這些好程序的邏輯結構,它們是被精心設計出來的。你可以先捂住這個demo程序,自己設計一個功能相同的程序結構,然後比較一下demo的程序結構,如果差距較大,那你就不應簡單地改進一下,而是要把demo作者設計的過程在心裏復原一遍,做到這一點也許有點困難,但這種事乾的多了,你就會越幹越快,越來越得心應手,你的邏輯能力飛速提升,你能看得上的邏輯結構優秀的程序開始不多了,下一步就是練習。

從工作中開始吧,如果你有空閒,你需要做至少兩類練習。

(1)一類是算法練習

所有的經典算法都是經典的邏輯。題目有的是,像個好學生一樣吧,每年的國內國際編程競賽都有邏輯要求非常高的題,你可以只選一兩道難題來做做。當你可以把複雜的單遞歸程序(只有A調A)變成非遞歸程序時,已經不錯了,如果你能看得懂雙遞歸程序(A調A、A調B、B調A、B調B都有),我爲你鼓掌!你不必往下看了,我有點不好意思班門弄斧。

(2)另一類是把以前和當前你工作中你不滿意的程序推倒重新設計一遍。

這非常重要,省時省力,因爲你熟悉需求,技術上也沒問題,目的就是改進程序的邏輯結構,很划算。唯一要克服的就是:你對推翻以前工作中那點小小成就的心理障礙,如果你真想優秀,這點心理障礙算個屁,一遍遍反覆地推倒已有的成果只能使自己快速進步,放手幹吧,沒什麼好可惜的,“在這個過程中,你失去的只有鎖鏈(禁錮你思想的鎖鏈)”。

在這個過程中,如果你能注意以下一些小的方面,你前進的步伐也許會快一些。

從編譯原理的角度來理解你工作中使用的高級語言。

如果你做到這一點,至少有兩個好處:

第一個好處是避免一大堆低水平重複出現的編譯錯誤。一名優秀的 Coder平均在一個工作日中應該完成200行以上的源碼,其編譯錯誤應該控制在5個以下,要知道這200行源碼不是一次完成的,所以大多數情況下你都要追求一次編譯通過,而一名職業水準的程序員,應該進一步做到即使用purify這類的工具來檢查源碼,也不會存在嚴重的內存泄露。

第二個好處是可以提高源碼的可讀性和效率。規範地編寫你的代碼使你自己的邏輯清晰,因爲你明白多加幾個括號和空行、多換行對齊、多註釋,編譯器是會自動識別的,不影響程序執行的效率,反過來,控制好遞歸調用和循環內的if語句纔是提高程序效率的關鍵,要全力避免遞歸,但要深刻理解遞歸,能通過自己建立堆棧來把遞歸程序轉換成非遞歸程序,要求還是較高的!

避免思維陷阱,只要是人,就一定有自己的思維慣性,這一定又會表現在你的程序邏輯中,有時你就是從這個慣性中跳不出來(誰都有這個時候),但要心裏有數才行。所以,你需要幫助。如果你有幾個水平相若或更高的職業夥伴,太好了,當遇到花30分鐘還打不下的bug時,就別浪費時間了,找他們吧。最要緊的是能思路清晰明確地表述你的問題,通常你自己在這個過程中或者夥伴中就有人把問題解決了,又快又好。另外,有幾個可以良性競爭的職業夥伴是人生的一件幸事,1+1>2,大家各有所長,你最好做到及時公開你的成果,技不壓身嘛,IT發展的這麼快,你再優秀,那點東東也沒有什麼值得隱藏的,所以你可以技術或水平不夠高,但千萬不可以讓真正具有職業水準的選手鄙視你的職業品質和行爲。

有自己debug的特點。

下面的說法作者不敢太肯定,只是經驗之談。即使在VC這種高度完善的開放環境下,你仍然應該要求自己僅憑打印語句就能 debug。這也有兩點好處。

(1)第一個好處是遇到bug,你會認真想問題所在,而不是用debug工具一步步簡單地追蹤卡在哪兒了,你定位bug範圍的方式是從大到小、從粗到精,這是一種自頂向下的思維方式,而用工具追蹤,容易形成自底向上的思維方式,這不算好,你應該先看到森林,再看到樹木。

我反覆提及:程序就是邏輯過程,大多數程序從main函數開始,是由數據結構和功能子程序組成的一個樹形結構的邏輯過程(要認清即使是面向對象的程序語言也是一樣的),它的執行過程是深度優先的,但你定位bug應該是廣度優先的,好好想想這一點。

(2)第二個好處是強迫你思考並記住而不是用工具看到調用過程,你大腦的抽象邏輯思維能力和胳膊上肌肉的力量一樣,都是練出來的,如果你的bug是程序結構上的邏輯錯誤引起的,這一點就非常重要了,順便說一句,最難打的bug就是程序邏輯結構錯誤導致的bug。你要是真正明明白白地認識到這兒了,那我就沒什麼東西可以告訴你了。

總之,程序員的職業水準:生產效率和程序質量,主要是取決於源碼中bug的數量和debug的速度,而不是取決於編寫源碼的速度。給你一個我自己定義的考查一個職業程序員的指標:

一個合格水準的職業程序員,編程的時間如果算一份的話,其累計debug的時間不能超過一份,真正職業高手累計debug的時間應該控制在0.5份以下

你關上門悄悄問問自己,你花費在編程和debug上的時間比例是多少?如果你把程序員作爲自己一生的職業,那麼就永遠都要牢記一點:追求做一個0 bug的優秀程序員!這是任何一個想成爲職業程序員的人的理想,請相信:堅忍不拔地追求實現這個理想將讓你出類拔萃!

做好程序的單元測試,這是另一項考查你是否是一名具有合格職業水準的程序員的一個必要指標。

其實在你拿到需求的時候就要準備單元測試用例了,並且這些用例將直接影響你的詳細設計(有關軟件設計本來是該放在第四節講的)。

我們還是打比方吧,當你拿到一個需求時,除了分析它靜態的功能外,還應明確它動態的操作/執行過程,把這個動態過程明確地用流程圖畫出來,比如分爲A~Z的26步,其中A又可以進一步分解爲A1~A5的5步,直到不能再分解爲止。又比如說A3步不可分解了,那麼你應該把A3步的正常操作和所有五花八門的異常操作都列出來,確保正常的操作肯定正確,異常的操作起碼程序不退出才行。

這樣你就要寫好多好多的測試用例,說句老實話,我也從來不寫!但我一般會列一個提綱,比如A3步有正常的操作a、b、c、d、e共5項,異常的操作有f、g、h、i、j、k、l、 m、n共9項,你在進行單元測試時都應該跑一遍,這樣的程序都還不敢說質量如何好,但起碼可以說較穩定吧!

如果要想在進行單元測試時幹得快、效率高,那麼在進行詳細設計時,你就應該把A3步中對所有正常操作和異常操作的判斷都設計好,在編程實現A3步時,使得程序的結構合理高效,對不對?所以,如果你在工作中是割裂地看待軟件工程中從需求、分析、設計、編程、測試等各個環節,恐怕水平很有限喔!但如果你在分析需求時就能看到測試的問題,並改進設計和實現,爲此做好相應的準備工作,嘿嘿,整個軟件開發過程你的效率會高很多,通常你在一個開發團隊中就會高度自信的,你已越過當一名偏頗、露骨的高手的境界,成爲一個平靜的高手,這可是The best in the best!,用周星星的話說:是高手之高高手,因爲別人看不出你高在哪兒,沒見你有什麼高招或特拚命幹,但反正你就是幹得又快又好、又省力。

關於進行單元測試還有很多複雜的方法,在此本文只提到了最基本的一點,目的是讓你在工作上考慮周全、安排有序,其它的自己琢磨吧,沒有人能替你吃飽飯!

如果你是用C++編程,我再簡單談談有關內層釋放的一個小技巧,就是對所有你編寫的類,在構造和析構函數中加打印語句,統計每個類在運行程序時構造和析構的地方,如果是配對的,那麼起碼沒有對象類一級的內層在程序運行結束時沒有釋放,然後你就可以把打印語句刪掉了,招數雖土,但管用!

還有其它一些好習慣,在這裏我隨筆寫一些,你要是有不同看法也請一笑過之吧。

編程時應該對齊縮進,一個縮進用一個tab鍵,一般是4個空格,嚴格遵守開發團隊的編程規範也是非常重要的。一個子程序不應超過 30行(不算空行),其內多重循環不應超過3層,否則都應該分裂成兩個子程序,個別算法程序可以長一些,但也不宜超過200行。通常一個類的所有成員函數總和不宜超過1500行,多了就應該考慮分解成兩個類(這個工作最好在設計時就完成)。

每完成一小段程序,比如15~30行,就立即編譯運行,不要假裝高手,先敲它一大堆程序,再編譯運行,妄想一次成功,體驗一種假爽的、虛榮的快感,或炫耀給別人看,這麼做只能證明自己是一個不折不扣的傻瓜,裝酷而已。因爲只要有一次不成功,你就會花費大量的時間來調程序,別人的進度在這時就遠遠地超過你了,平常心是道,還是修煉真功夫吧!孫子兵法裏關於這一點有明確的闡述,我就不引用了,但建議你真的不要這麼幹,除非你確實就是這樣總是一次就成功的天才,那你還看這篇文章幹什麼呢?我又不是寫給你們這些天才們看的。

再就是有學會買好書、讀好書,關於計算機和軟件方面的書太多了,時間有限,比如有一個叫侯捷的傢伙,幾乎寫的每本書都不錯,張國峯的C++編程也不錯,這只是我的個人意見啊,好書多着呢,列出來比這篇文章長好多倍,我就不多說了。

還有一招,要是你運氣好,能搞到一些著名軟件系統的源碼,好好讀讀吧,在此我只能告訴你,Linux操作系統的一些源碼不錯,是開放的,你可以合法地搞到,其它的不要說是我建議你侵犯知識版權啊!
 
四、天生神力:成爲系統分析員

你要是運氣好,直接進入了一個嚴格規範生產的軟件企業就業,剛開始就應該是按別人做好的軟件設計來實現編程,你可以有機會直接學習軟件設計。當你積累的足夠多了,能夠對其中的一些設計提出好的改進建議,而且幹得又快又好,就會漸漸地展露頭角,我相信你終有一天成爲一名軟件設計人員(注意,不是軟件產品設計人員),步入系統分析員的行列,但這還需其它的一些條件和自我修煉。

如果你在一個不規範的軟件企業工作,那也不錯,你很可能直接就有機會進行軟件設計,然後開發、測試,甚至還不得不自己定義需求,把軟件開發過程的各個環節走一個遍,當然這樣對你的要求更高,而且你也不容易得到及時有益的指點,在正態分佈的情況下,你應該是成長的很慢。但不管就業的單位如何,如果你決心要成爲頂尖軟件職業選手,通常什麼客觀困難都阻擋不了你,然而你個人的因素可能會阻止你的前進。

作者自己沒有到微軟面試過,但身處軟件行業,關於微軟的許多東東當然還是有耳聞的,據說微軟招聘一名程序員要過五個已經成爲微軟程序員的面試關,而且是一票否決制,又據說大多數面試題並非編程,而是一些有關邏輯和智力的題,作者私下也做過許多流傳的微軟面試題,並對此做法深以爲然。程序的本質就是邏輯,所以幾十年前就有人提出編程是一門藝術,而藝術是要靠天份的,這一點少有人反對。一個人的邏輯能力可以不斷提高,但其能到達的終極邏輯能力的層次必定爲其天生智力所限制,這一點就讓人不易接受了。

在工作中,你基本上遇到的是兩類方式的設計,一個是結構化設計,另一個是面向對象設計。就個人經驗而言,面向對象的設計更好。

金大俠在《倚天屠龍記》裏講到張無忌初學太極,學會的標誌是把剛學的招數全忘了,記住的是太極的道理和精神,和李小龍有些相似喔,軟件設計也一樣,忘記所有的設計模式,隨心所欲進行設計纔是至高境界,所以你能到達多高的軟件設計的境界最終將取決於你的哲學素質,這一點實在是不好寫啊,你自己領悟吧!作者只有祝福了!

五、職業人的終極目標:全面修煉,成爲Leader

這一節更不好寫,涉及到太多其它非技術方面的因素,特別是個人人生觀和世界觀的修煉。如果本帖的點擊率超過作者私下期望的一個數值,那我就爭取盡力厚着臉皮再補上吧。我只說一句,雖然大家都知道軟件開發是一個團隊性的工作,但追求參與一個大型軟件系統的成功開發,是一名軟件人員的本能,就像拿破崙說的不想當元帥的士兵不是好士兵,所以不追求實現大系統的軟件人員,也不是一個好的職業軟件人員,但你只有成爲Leader,領導一個優秀的軟件開發團隊,纔有機會實現這個終極職業目標,對不對?

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章