一個(gè)足球評(píng)論員可能并不會(huì)踢足球,卻并不妨礙在解說比賽時(shí)對(duì)某某球星的技藝評(píng)頭論足。同樣我也絕不敢以高明的程序員自居,而只是以類似足球評(píng)論員的角度來闡述我對(duì)程序員的理解。這樣,大家也許就不以我為鄙薄狂妄了。這是我必須首先聲明的。
什么是程序員
按照Wikipedia的定義,程序員又稱為計(jì)算機(jī)程序員(Computer Programmer)、開發(fā)者(Developer)、編碼者(Coder)或計(jì)算機(jī)工程師(Computer Engineer),和網(wǎng)絡(luò)上廣泛流傳的碼農(nóng)或程序猿同義。我無意于也不能夠?yàn)槌绦騿T給出一個(gè)精確的定義,這里,只是利用程序員的語言做一個(gè)簡(jiǎn)單描述。不是故弄玄虛,不過博取讀者諸君一笑。
程序員是徹頭徹尾的腦力工作者(Mind Worker),怠于思考者絕對(duì)不能成為好的程序員。有鑒于此,類Programmer天生的就應(yīng)該是Thinker的子類。就程序員所使用的思考技巧而言,Thinker的具體內(nèi)涵包括邏輯(Logic)和數(shù)學(xué)(Mathematics)。作為程序員,不一定非要達(dá)到邏輯或數(shù)學(xué)領(lǐng)域的專業(yè)水準(zhǔn),而是必須具有邏輯和數(shù)學(xué)的基本素養(yǎng)。邏輯用來推理,數(shù)學(xué)用來培養(yǎng)邏輯。另外,數(shù)學(xué)還有助于程序員訓(xùn)練另外兩項(xiàng)必不可少的思考的技能,分析和抽象。下文還要展開討論。程序員的工具是編程語言,日常活動(dòng)和主要工作包括設(shè)計(jì)(design)、建模(model)、編碼(code)、調(diào)試(debug)、重構(gòu)(refactor)、溝通(communicate)、學(xué)習(xí)(learn)和思考(think)。
有關(guān)程序員有一個(gè)流傳甚廣的誤解,認(rèn)為做程序員門檻低,沒什么技術(shù)含量。即使沒有學(xué)過計(jì)算機(jī)的課程如離散數(shù)學(xué)、數(shù)據(jù)結(jié)構(gòu)、算法等,也可以寫程序。寫幾行程序當(dāng)然算不得什么,但要修煉成有一定思想境界的一流程序員,卻殊非易事。這就如同會(huì)做飯的人很多,但真正的烹飪大師卻并不常見。所謂碼農(nóng)者,乃是程序員的自我吐槽,豈足深信耶?所以,作為程序員要有持續(xù)進(jìn)階的強(qiáng)烈的進(jìn)取心,斷不可妄自菲薄,自怨自艾。
程序員的思維藝術(shù)
漫長(zhǎng)的學(xué)生生涯中,我遇到的最好的數(shù)學(xué)老師是高中時(shí)的劉傳禹老師。他上課時(shí)講過這樣一段話,當(dāng)面對(duì)一個(gè)數(shù)學(xué)問題,一要想的明白,二要算的準(zhǔn)確,三要寫的清楚。直到今天,這句話對(duì)于我的程序員生涯也具有很強(qiáng)的現(xiàn)實(shí)意義,能不能想的明白其實(shí)是考量一個(gè)程序員成敗的至關(guān)重要的因素。金庸的武俠小說中有一個(gè)普遍的規(guī)律,那就是武功必定以內(nèi)力為根基。
比如張君寶與昆侖三絕何足道在少林寺的那場(chǎng)經(jīng)典之戰(zhàn)中,張君寶能夠“以少林拳中最平淡無奇的拳招,化解了最繁復(fù)的敵招”,始終不落下風(fēng),所恃者不過內(nèi)力之渾厚爾。另外的著名戰(zhàn)例還包括少林寺小和尚虛竹VS.吐蕃國(guó)師鳩摩智以及聚賢莊蕭峰VS.玄難。內(nèi)力達(dá)到登峰造極空前絕后的第一高手莫過于少林寺的掃地僧。也許風(fēng)清揚(yáng)是一個(gè)例外,好在我們討論的是一般規(guī)律,所以就顧不得他了。計(jì)算機(jī)編程所特有的思維(Thinking)就是程序員的”內(nèi)力“,思維能力不濟(jì),功能再強(qiáng)大的編程語言也無用武之地。所以,我在這里特別強(qiáng)調(diào)程序員的思維藝術(shù)。
程序員的思維有一個(gè)專業(yè)術(shù)語,叫做計(jì)算思維(Computational Thinking)。計(jì)算思維是按照計(jì)算機(jī)科學(xué)的基本概念和方法,用來理解需求、設(shè)計(jì)系統(tǒng)、實(shí)現(xiàn)編程、解決問題的思維方法。簡(jiǎn)而言之,計(jì)算思維就是程序員或計(jì)算機(jī)科學(xué)家是如何思考的。當(dāng)然,計(jì)算機(jī)科學(xué)的理論知識(shí)如數(shù)理邏輯、離散數(shù)學(xué)、數(shù)據(jù)結(jié)構(gòu)、算法以及面向?qū)ο笫怯?jì)算思維的必要條件。計(jì)算思維有一系列的智力工具,不能一一盡述,僅列舉關(guān)鍵的幾項(xiàng)如下:
抽象思維(abstract thought)。給定一個(gè)問題,抽象就是去掉紛繁蕪雜的與計(jì)算無關(guān)的部分,用規(guī)約(Reduction)的方法還原到問題的本質(zhì)。所謂本質(zhì)即把原來的問題轉(zhuǎn)換為一個(gè)或幾個(gè)可以使用計(jì)算機(jī)描述并解決的問題,進(jìn)一步講也就是轉(zhuǎn)換為在算法上可計(jì)算的(algorithmically computable)一個(gè)或幾個(gè)問題,更準(zhǔn)確更理論化更上檔次的描述是轉(zhuǎn)換為邱奇-圖靈論題(TChurch-Turing thesis)可計(jì)算的可數(shù)個(gè)問題。圖靈機(jī)(Turing Machine)和λ演算(Lambda calculus)本身就是對(duì)可計(jì)算性(Computability)的漂亮的抽象,可以作為抽象思維的經(jīng)典案例來揣摩學(xué)習(xí)。一般在實(shí)際工作中,常常需要把問題的實(shí)體對(duì)象根據(jù)需求表示為各種數(shù)據(jù)結(jié)構(gòu)如樹、堆、棧等,而業(yè)務(wù)邏輯(Business Logic)過程表示為各種算法如排序和查找等。
表示(Presentation)是解決問題的第一步,也是關(guān)鍵的一步。在程序員的實(shí)踐中,我們都有很深的體會(huì),一旦問題被準(zhǔn)確的無歧義表示出來了,解決方案就烘云托月般地呈現(xiàn)出來了。這就是“數(shù)據(jù)即代碼,代碼即數(shù)據(jù)”的道理。抽象思維也廣泛用于數(shù)學(xué)家的工作。面對(duì)一個(gè)困難的問題,數(shù)學(xué)家們常從兩個(gè)方向開展研究。
一方面,從特殊情況入手,推廣到更一般的情況;另一方面,將一個(gè)一般問題具體化成幾種特殊情況。兩個(gè)方向的結(jié)果最終匯聚在一起,就找到了問題的答案。我想這可能是論語中“我叩其兩端而竭焉”的一個(gè)最好注解。而從特殊到一般就是不斷抽象的過程。我們用一個(gè)具體的例子加以說明,有一個(gè)著名的六度分隔理論(Six Degrees of Separation)講的是世界上任意兩個(gè)人都可以通過最多另外6個(gè)人相互認(rèn)識(shí),如果要驗(yàn)證這一理論,怎么做呢?
我們可以借助一個(gè)圖(graph)來表示人與人之間的關(guān)系,每個(gè)人用圖中的一個(gè)節(jié)點(diǎn)表示,如果A和B認(rèn)識(shí),那么在代表他們的節(jié)點(diǎn)之間有一條邊連接。那么現(xiàn)在的問題就轉(zhuǎn)換為檢查這個(gè)圖的直徑是否大于6??紤]到世界人口眾多,且有生老病死,圖的規(guī)模必然超大,并且是動(dòng)態(tài)的不斷變化的,算出它的直徑仍需要更多的簡(jiǎn)化。這里就到此為止了。
邏輯推理(Reasoning)。邏輯推理對(duì)于程序員的重要性不言而喻。與其說邏輯推理用于程序新功能的開發(fā),毋寧說更多的應(yīng)用在程序調(diào)試修改BUG的過程中。程序調(diào)試有點(diǎn)類似于Sherlock Holmes偵破案件的過程。和Dr. Wason比較起來,Holmes的推理優(yōu)于常人的地方有兩點(diǎn):第一,在觀察現(xiàn)場(chǎng)或聽取來訪者敘述時(shí),他能夠得到更多的的數(shù)據(jù),尤其是一些別人容易忽略的關(guān)鍵的細(xì)節(jié),這得益于他對(duì)犯罪領(lǐng)域知識(shí)的豐富積累,知道什么才是更重要的數(shù)據(jù);第二,根據(jù)得到的數(shù)據(jù),他能夠聯(lián)想到更多的可能的結(jié)論,這得益于他大量的案例儲(chǔ)存。有了這兩點(diǎn),就能夠通過一環(huán)套一環(huán)的推理鏈逐漸縮小偵察范圍,最終認(rèn)清犯罪事實(shí)。
程序調(diào)試也是如此,首先必須掌握程序?qū)嶋H的執(zhí)行過程的細(xì)節(jié)。然后從問題出發(fā),分別朝著產(chǎn)生的原因和導(dǎo)致的后果前后兩個(gè)方向推理。逐漸定位問題的范圍,最終找到問題的根源和解決的方案。我們比Sherlock Holmes幸運(yùn)的是可以借助于調(diào)試工具來了解程序運(yùn)行的過程,所以一個(gè)不能使用調(diào)試工具的程序真是令程序員感到無比沮喪,只能通過trace信息來跟蹤程序運(yùn)行的過程。如果不知道程序運(yùn)行的過程,推理就只能靠猜,那么修改BUG是非常危險(xiǎn)的,很容易導(dǎo)致回退(Regression)的錯(cuò)誤,因?yàn)檫@種情況下如同瞎子摸象,根本不知道自己在做什么。另外,Sherlock Holmes還多次表達(dá)過這樣的觀點(diǎn),案子越是離奇,越容易解決,因?yàn)镾ingularity is almost invariable a clue。
對(duì)程序員來講,也不必?fù)?dān)心奇怪的問題,奇怪本身就是線索。關(guān)鍵看對(duì)程序運(yùn)行細(xì)節(jié)的了解程度和邏輯推理的技術(shù)水平。
分析(Analysis)。分析是上文提到的數(shù)學(xué)家所用思維方式中從一般到若干特殊情況的過程。面對(duì)一個(gè)問題,如果一下子描述不清楚或者表示不出來,可以先找出滿足問題條件的幾種特殊情況。通過仔細(xì)檢查這幾種特殊情況,求同存異,找出他們共同的規(guī)律或模式,并對(duì)這些模式或規(guī)律加以驗(yàn)證,就可以找出描述或表示問題的方法。這就是猜測(cè)加驗(yàn)證(guess-and-verify)的過程。項(xiàng)目需求分析時(shí)常見的應(yīng)用案例分析(Use Case Analysis)方法,就是用一個(gè)個(gè)具體的使用案例將模糊的項(xiàng)目需求生動(dòng)的表達(dá)出來。
分解(Decomposing)。把一個(gè)大問題分解為幾個(gè)小問題,或者把一個(gè)復(fù)雜的過程分解為幾個(gè)子過程,當(dāng)然有助于問題的解決。這也是程序員常用的手段,如算法策咯中的分而治之(Divide-and-Conquer)和合并排序就是這方面的例子。
遞歸(Recursion)。對(duì)于初學(xué)編程的人,遞歸可能是一個(gè)比較詭異的較難掌握的概念。但是一個(gè)程序員如果不懂遞歸,很難再稱之為程序員。因?yàn)楹芏嗌晕?fù)雜的算法他都不可能理解,如回溯和動(dòng)態(tài)規(guī)劃,甚至于樹的遍歷。遞歸常??梢杂煤?jiǎn)單的方法非常優(yōu)雅的表達(dá)復(fù)雜的算法。
另外,有關(guān)計(jì)算思維的特有方法還有并行、異步/同步、模擬/近似、優(yōu)化、分層、封裝、解耦等等。程序員的思維藝術(shù)即計(jì)算思維不是一天兩天短時(shí)間可以形成的,需要在實(shí)踐中慢慢琢磨,不斷提升,且永無止境。
程序員的技藝境界
程序員的思維藝術(shù)融化到到對(duì)編程語言的使用上,最終形成程序員的技藝。因此,編程語言之于程序員,就如同青龍偃月刀之于關(guān)羽,如意金箍棒之于孫悟空。離開了青龍偃月刀和如意金箍棒,關(guān)羽和孫悟空的戰(zhàn)斗力就無從談起。所以,脫離編程語言來討論程序員的技藝也無異于緣木求魚,自欺欺人。結(jié)合編程語言,程序員的技藝有四個(gè)境界,從低到高分別是:
初窺門徑。編程語言的初學(xué)者,如同小兒咿呀學(xué)語,也許可以寫一個(gè)類似于“Hello World”這樣的程序,但對(duì)語言的所有東西都是一知半解,不可能應(yīng)用于實(shí)際的項(xiàng)目中。這是我們很容易就可以達(dá)到的級(jí)別。有些人初窺門徑之后,往里面看看,感覺不容易,就放棄了。
登堂入室。對(duì)編程語言所共有的基本表達(dá)方式有了一定的了解,如變量、賦值、循環(huán)、選擇等。可以用在一般的項(xiàng)目中,但是寫出來的代碼看起來滯澀笨拙,很難做出高質(zhì)量的程序。這個(gè)時(shí)候,程序員很容易產(chǎn)生自滿的情緒,以為完全掌握了這種編程語言,編程也不過如此。如果陷入這種自滿情緒中不能自拔,就失去了進(jìn)一步進(jìn)階的機(jī)會(huì)。
熟能生巧。掌握了編程語言特有的功能,并能駕輕就熟,靈活使用。因此,寫出的代碼更加的精煉易懂,常常使用簡(jiǎn)單的方法表達(dá)較為復(fù)雜的算法。這是一個(gè)成熟的程序員的水平,也是我們大多數(shù)程序員所能追求的目標(biāo)。
妙不可言。 這是傳說中神龍見首不見尾大師級(jí)的境界。柏楊在《中國(guó)人史綱》描述李白的才華稱,李白寫詩時(shí),對(duì)漢語的使用就像魔術(shù)師手中翻轉(zhuǎn)的手帕一樣,神鬼莫測(cè)。如同李白作詩一樣,我想這個(gè)境界的程序員對(duì)編程的各種精微之處了如指掌,能夠?qū)⒕幊陶Z言的各種功能特性發(fā)揮到極致,且恰到好處。運(yùn)用之妙,存乎一心。并且往往能夠別出機(jī)杼,奇思妙想,層出不窮。寫出的程序優(yōu)雅、高效、別致。這是我們一般程序員可望不可即的。
程序員的精神素質(zhì)
開放。在以往的工作中,曾經(jīng)遇到過這樣的程序員,自以為掌握了某些核心的、關(guān)鍵的技術(shù)或技能,卻不愿意和別人共享,處心積慮的保護(hù)著他的“地盤”,擔(dān)心別人染指他的工作。也遇到過這樣的組織,幾個(gè)被信任的程序員把持著產(chǎn)品的所謂關(guān)鍵模塊,其他人莫想?yún)⑴c,即便再有才華,也只能扮演跑龍?zhí)椎慕巧?。這讓我想起《三國(guó)演義》中諸葛亮舌戰(zhàn)群儒的情節(jié),在回答江東首席謀士張召的詰難時(shí),諸葛亮將儒生分為君子之儒和小人之儒。這里不妨將這樣的程序員稱為“小”程序員吧。程序員的技藝根植于計(jì)算思維中,沒有所謂的不傳的絕招或秘笈。交流和實(shí)踐是程序員持續(xù)進(jìn)階的必要且有效途徑。固步自封和抱殘守缺是程序員的大忌,完全是作繭自縛,毫無出息。
嚴(yán)謹(jǐn)縝密。在軟件開發(fā)中,任何事情在邏輯上原因和結(jié)果都是清晰明了的,不存在任何意義上的說不清道不明的神秘主義。程序員也是軟件工程師,討論問題時(shí),當(dāng)然應(yīng)該使用工程師的語言,即用數(shù)據(jù)而不是猜測(cè),用邏輯而不是臆斷,來表達(dá)自己觀點(diǎn)。有兩種情況可能造成自己表述時(shí)似是而非,模棱兩可:第一,數(shù)據(jù)掌握的不夠;第二,沒有“想的很明白”。例如,當(dāng)我們討論性能(Performance)時(shí),一定要用響應(yīng)時(shí)間(Response Time)或吞吐量(Throughput)這樣有意義的參數(shù),而不只是泛泛的講“這系統(tǒng)咋這么慢啊”,“計(jì)算機(jī)在干什么呢,等的時(shí)間太長(zhǎng)了”,“簡(jiǎn)直受不了這樣的程序了”。用戶可以這樣抱怨,而程序員則不可。同樣當(dāng)我們講到系統(tǒng)開銷時(shí),要用CPU占用率、內(nèi)存這樣定量的參數(shù)。因此,一個(gè)腦筋清楚的程序員不會(huì)把這樣的話掛在嘴邊,“太神奇了,不知道為什么”,“弄不清楚是否可以解決這個(gè)問題”,“先這樣吧,以后再說”。一般地講,智能和非智能并沒有清晰的界限,因?yàn)槲覀儾⒉恢廊绾螄?yán)格地定義智能。然而,有了圖靈—邱奇論題,可計(jì)算的和不可計(jì)算的確實(shí)有明確定義的界限,也就是說,計(jì)算機(jī)可以解決的問題和不可以解決的問題是涇渭分明的,且是可以區(qū)分的。對(duì)于一個(gè)問題,能夠解決就是能夠解決,不能解決就是不能解決,不至于難以確定是否可以解決。所以,所有以上這些說法都不應(yīng)該是程序員使用的語言,程序員就是要把一切都弄得清清楚楚,不放過任何潛在的問題。
完美主義。我不了解完美主義的真實(shí)意義,也不大拿得準(zhǔn)完美主義是褒義詞和貶義詞。我用這個(gè)詞是為了強(qiáng)調(diào)程序員要堅(jiān)持追求工作的完美。寫代碼時(shí)是要有潔癖,不允許有任何瑕疵,這樣的代碼才可能正確、易讀、高效、簡(jiǎn)單、優(yōu)雅。對(duì)一項(xiàng)任務(wù),不僅僅是做完就算了,還應(yīng)該仔細(xì)想想是否是否可以做的再好一點(diǎn)。對(duì)遇到的問題,即使看似解決了,也要從頭至尾完全弄明白,不能似是而非,不求甚解。
面對(duì)變化。變化意味著在新的征程上,要面對(duì)許多未知的東西,加之對(duì)安定狀態(tài)下的安樂窩(Comfortable Zone)的眷戀,讓我們有著或多或少的畏懼和抗拒。我認(rèn)為這些都是人之常情,無可厚非。不幸的是,對(duì)程序員來說,變化就是家常便飯,如新的項(xiàng)目、新的應(yīng)用領(lǐng)域、新的編程語言、新的技術(shù)架構(gòu)、開發(fā)過程中新的問題、新的功能等,可以說不變的只有變化。其實(shí),好逸惡勞是畏懼變化的根源。只有克服“懶”的思想,強(qiáng)迫走出自己的安樂窩,對(duì)新的事物充滿好奇心和求知欲,才能適應(yīng)永遠(yuǎn)的變化。
程序員的價(jià)值
有的公司把程序員看作和水電、機(jī)器一樣的冷冰冰資源,做項(xiàng)目計(jì)劃時(shí),一些項(xiàng)目經(jīng)理以為只要給項(xiàng)目分配足夠的資源(包括程序員、水電、機(jī)器)并加以正確的管控,項(xiàng)目就可以預(yù)期的順利完成。就好像做東北亂燉,只要把各種食材往鍋里一丟,開火等著就萬事大吉了。但是,程序員首先是有血有肉的人,絕不等同于毫無感情的機(jī)器。一個(gè)有雄心的公司要不斷提升產(chǎn)品的競(jìng)爭(zhēng)力,什么是競(jìng)爭(zhēng)力?就是把產(chǎn)品做的好到不能再好,天下第一,誰與爭(zhēng)鋒?產(chǎn)品向好的每一步都需要借助于程序員創(chuàng)造力和想象力,這才是程序員的價(jià)值之所在。沒有程序員愿意把最寶貴的創(chuàng)造力和想象力奉獻(xiàn)給只把自己看作資源的公司。所以,聰明的管理者會(huì)想方設(shè)法把程序員這種創(chuàng)造力和想象力激發(fā)出來。
-
程序員
+關(guān)注
關(guān)注
4文章
953瀏覽量
29825
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論