應(yīng)人民郵電出版社圖靈公司的邀請,我有幸參與了Bob大叔所著Clean Coder的翻譯。

  與前作Clean Code不同,這本書著重講述的是開發(fā)人員的“職業(yè)素養(yǎng)”,也即職業(yè)開發(fā)人員應(yīng)當(dāng)如何做事。在閱讀中,我時常會忍俊不禁,也會拍案叫絕,感嘆Bob大叔把深刻的道理講得這樣通透。我雖然沒有Bob大叔那樣好的文筆,不過對“開發(fā)人員的職業(yè)素養(yǎng)”這個話題,仍然有很多話想說,索性分幾個方面寫下來。

  學(xué)習(xí)

  開發(fā)人員在工作之前,一般都已經(jīng)經(jīng)過大學(xué)階段的專業(yè)學(xué)習(xí)。眾所周知,大學(xué)的很多課程已經(jīng)相當(dāng)落后,教材也非常保守,所以我見過的好開發(fā)人員,不少都是自學(xué)成才。但是,這些問題并不能否認(rèn)通過專業(yè)課程學(xué)習(xí)知識的意義,職業(yè)開發(fā)人員理解的“學(xué)習(xí)”,應(yīng)當(dāng)明確地區(qū)分知識、課程、教材:知識是重要的、穩(wěn)定的,課程和教材是不那么重要的、變化的。

  可以非常肯定地說,數(shù)據(jù)結(jié)構(gòu)、編譯原理、操作系統(tǒng)這類知識,是整個計算機世界的基石,是任何時候也不會過時的。即便畢業(yè)后不從事專門的科研,這類知識也會從你接觸到的各種現(xiàn)象中體現(xiàn)出來。我在大學(xué)時基本拋棄了學(xué)校指定的課程和教材,但自己反復(fù)啃過影印版的《現(xiàn)代操作系統(tǒng)》,反復(fù)做過北大屈婉玲老師的三本《離散數(shù)學(xué)習(xí)題集》,后來在工作中受益匪淺??調(diào)優(yōu)程序的性能,很可能需要理解調(diào)度、死鎖、用戶空間與系統(tǒng)空間等知識;重構(gòu)復(fù)雜的布爾邏輯,很可能要依賴數(shù)理邏輯中的定律。如果當(dāng)時沒有反復(fù)的研習(xí),沒有深入理解這背后的原理,并且沒有領(lǐng)悟到這些原理和各種現(xiàn)象之間的聯(lián)系,遇到很多問題我很可能會兩眼抓瞎,充其量憑經(jīng)驗試錯,無論如何,其效率遠不及知識體系指導(dǎo)下的實踐。

  據(jù)我觀察,大學(xué)生之所以對課程不感冒,除去學(xué)校和教師的原因,另一個因素是,幾乎很少有教材能把看起來乏味的原理,和生活中遇到的問題講清楚。學(xué)習(xí)圖算法時,你是否想過“人、狼、羊、草過河”的問題可以直接由它來解決?學(xué)習(xí)內(nèi)存管理時,你是否想過為什么Windows 95、Windows 98都那么容易藍屏,到了Windows XP才有了長足的進步?我相信,如果能把原理與這類例子對應(yīng)起來,你的理解會深刻許多,印象也會深刻許多。不幸的是,這類“聯(lián)系”的工作,在國內(nèi)教材基本是一片空白,國外教材也只有部分涉及。其結(jié)果是,不少“有經(jīng)驗”的開發(fā)人員面對“32位機為什么只能支持4G內(nèi)存”、“一個字是多少個字節(jié)”、“進程間通訊有哪幾種方式,各有什么優(yōu)劣”之類基本的問題一臉茫然,不要小看了這些問題,不懂它們,你開發(fā)出來的程序只能湊合用,后期遇到問題要重構(gòu)、調(diào)優(yōu),簡直難比登天。

  對此,我的建議是:如果你現(xiàn)在還在學(xué)校,不妨仔細想想知識、課程、教材之間的聯(lián)系,確定重要的知識,選擇好的教材,自己安排自己的課程。如果你已經(jīng)離開學(xué)校,而且感覺自己的基礎(chǔ)并不牢靠,不妨從手頭的工作開始,想想它用到了哪些原理,對應(yīng)哪些知識,逐步、有針對性地補習(xí)。這其實并沒有太多難度??我的朋友張東亮(@zhasm),之前幾乎沒有任何計算機基礎(chǔ)知識,只是因為對正則表達式的愛好,找到了一份開發(fā)人員的工作,一年之后,他已經(jīng)開始啃編譯原理之類的書籍了。

  以上說的主要是“專門”的學(xué)習(xí),如果是工作之后的學(xué)習(xí),會有很大的不同。

  首先,工作之后的學(xué)習(xí)更多依靠自覺,沒有幾家公司會付出代價讓員工像學(xué)生那樣“學(xué)習(xí)”,所以更多時候,你只能花自己的時間、自己的金錢來學(xué)習(xí)。很多人一想到要花自己的時間,自己的金錢,心里打了退堂鼓。要明確的是,公司沒有老師那樣強烈的責(zé)任培養(yǎng)員工“成長”,如果你找不到好的、薪水高的工作,恐怕很難責(zé)怪上一家公司沒給你好的培訓(xùn)。所以,擔(dān)心金錢和時間而放棄學(xué)習(xí),終的結(jié)果是自己停止了成長,逐漸喪失競爭優(yōu)勢。相反,投入時間和金錢來學(xué)習(xí),不但可以保持甚至擴大你的競爭優(yōu)勢,如果這種行為可以堅持、內(nèi)化到生活中,也有助于保持健康、飽滿的精神狀態(tài)。

  其次,工作以后的學(xué)習(xí),需要努力擺脫工作環(huán)境的限制。我見過不少開發(fā)人員,因為工作限定在某個平臺,某種語言,業(yè)余時間的學(xué)習(xí)便全部投入到這種平臺、這種語言上,而沒有思考自己是否合適做這些平臺和語言,這些平臺和語言是否在走下坡路。在學(xué)校里,考分或許往往是的度量,但在工作中,行將沒落的語言和平臺,你運用再熟練,也于事無補。況且,過于專精于一門語言、一個平臺,反而會限制你的思維和視野,影響迅速學(xué)習(xí)陌生知識的能力??要在短時間內(nèi)熟悉陌生平臺和語言的例子,在我們工作中并不少見,在整個IT業(yè)界中更是家常便飯。為了讓它真的成為“便飯”,平時還是應(yīng)當(dāng)有意識地擺脫工作環(huán)境的限制,挑戰(zhàn)自己的思維慣性。

  責(zé)任

  我曾經(jīng)見過很多的簡歷,在“工作經(jīng)歷”里,項目描述寫得天花亂墜,如何先進,如何復(fù)雜,采用了多少新技術(shù),但是具體到個人責(zé)任,或者語焉不詳,或者極其潦草。這樣簡歷,體現(xiàn)的是責(zé)任感的缺失??對于自身責(zé)任沒有明確的認(rèn)知,也沒有足夠的擔(dān)當(dāng);這樣的人,通常不用面試,可以知道并不是合格的“職業(yè)開發(fā)人員”。

  另一方面,我在面試時,經(jīng)常會問兩個問題,其中很重要的一個是:在你的工作經(jīng)歷中,收獲大或者印象深的事件是什么。一般來說,如果能回答得有條理、有依據(jù),大多可以判定為合格的職業(yè)開發(fā)人員。因為,有責(zé)任感的開發(fā)人員,大多不會把程序看成身外之物,更多地會把程序與自己的道德、聲譽等等聯(lián)系起來,甚至把程序看成自己的孩子;所以,必然會投入時間精力去總結(jié)、反思、完善、改進,像照顧自己的孩子那樣。其實,我的經(jīng)驗看,真正的職業(yè)開發(fā)人員,不但能很好地回答這個問題,而且說起自己做過的事情,多有種充沛的自信感:XX項目是我做的,其特點是什么,我是如何如何做的,遇到什么問題,是如何解決的……涉及的技術(shù)不必很先進,開發(fā)的系統(tǒng)也不必很復(fù)雜,只要能夠這么自信滿滿地一條條歷數(shù)下來,你的職業(yè)素養(yǎng)是無可厚非的。

  業(yè)務(wù)

  軟件開發(fā)中,需求變化是無可避免的。雖然敏捷開發(fā)、極限編程宣稱要“擁抱變化”,但真正做到擁抱變化,卻是難上加難。原因在于:一方面,不少開發(fā)人員對變化本身持懷疑甚至抵觸態(tài)度;另一方面,許多需求
  這個問題非常普遍,也很嚴(yán)重。我思考了很久,發(fā)現(xiàn)比較合適的解決辦法是進行角色的互換,尤其是開發(fā)方(包括開發(fā)人員),不能局限于“按照規(guī)程實現(xiàn)功能”的角色,而應(yīng)當(dāng)深入思考和理解業(yè)務(wù)。

  不少開發(fā)人員“理想”的工作環(huán)境是:根本不關(guān)心自己的工作成果給誰用,怎么用,會產(chǎn)生什么結(jié)果,他們更喜歡這樣的描述:什么類型的數(shù)據(jù)從哪里來,怎樣處理之后,后交給哪里。在架構(gòu)清晰、流程完備的大公司里,或許你只需要安心填格子即可,但是擁有這樣工作環(huán)境的開發(fā)人員,占總數(shù)的多少呢?更多的人面對的還是變化不定的需求,甚至連業(yè)務(wù)部門自己都不清楚自己要的是什么,這種情況下,只關(guān)心“數(shù)據(jù)從哪里來,怎樣處理,交給哪里”之類的問題,無異于盲人騎瞎馬,無異于挖坑埋葬自己。

  相反,如果你清楚某個實現(xiàn)方案的緣由,知道它是基于何種應(yīng)用場景,如何設(shè)計出來的,可以在相當(dāng)程度上把握它的價值和所需的工作量。如果更主動一些,可以和業(yè)務(wù)部門談,這么做,將來會遇到什么問題,如果將來要改,哪些環(huán)節(jié)是可以改的,哪些環(huán)節(jié)是不能改的??如果你設(shè)身處地地為對方考慮,給出的建議一定比技術(shù)味道濃厚的“做不出來”更有說服力。如果做不到這么主動,你也可以預(yù)估,哪些業(yè)務(wù)是穩(wěn)定不變的,哪些業(yè)務(wù)是一定會遇到問題需要改變的,然后可以合理分配工作量:對那些明顯沒什么前途的項目,可以適當(dāng)保留資源,以免將來竹籃打水;對那些目前業(yè)務(wù)部門認(rèn)為不重要,其實又相當(dāng)有價值的項目,可以適當(dāng)多投入精力,以免將來措手不及??要知道,業(yè)務(wù)部門提的“緊急”需求,多半不會考慮開發(fā)的工作量。

  需要補充的是,做到上面這點,其實有相當(dāng)?shù)碾y度:一方面,你的技術(shù)功底必須足夠扎實,在滿足需求時,不僅僅是“模仿”現(xiàn)實,而應(yīng)當(dāng)知道這種現(xiàn)實,在數(shù)字世界里應(yīng)當(dāng)如何表達,如何重構(gòu),受到哪些條件和規(guī)則的限制(比如同一個抽象操作的不同實現(xiàn),到底是選擇Switch語句還是多態(tài),其實是有章可循的,必須根據(jù)實際情況選擇);另一方面,又要能跳開技術(shù)的局限,從更全面的視角理解、把握業(yè)務(wù)。不過,這是非常值得花功夫的??從某種意義上可以說,當(dāng)前熱門的“領(lǐng)域驅(qū)動開發(fā)(Domain Driven Development)”,說的大抵是這回事。

  時間

  在軟件開發(fā)中,時間是一個非常重要的因素。在這方面,已經(jīng)有無數(shù)的巨著,無數(shù)的案例,無數(shù)的先烈,但是時間,仍然是一個值得討論的話題。

  總的來說,人月是一個神話,我們不可能精確地把握開發(fā)時間,但是這并不意味著,我們不能從某種程度上把握時間。我個人的經(jīng)驗是,計劃是在現(xiàn)實參照下的不斷調(diào)整和修正中逐漸準(zhǔn)確的。重要的,并不是確定遠大的目標(biāo),然后限定多長時間必須完成;而是可以把大的項目拆分為不同的模塊,把整個開發(fā)流程劃分為不同的階段。如果你的模塊劃分得足夠細致,可以以每個模塊的工作量,相對準(zhǔn)確地得知整個項目的耗時;如果你的流程劃分得足夠合理,可以在各個階段拿出看得見、用得著的結(jié)果,供業(yè)務(wù)方使用。這樣,一方面避免了“到后一起推出,卻發(fā)現(xiàn)與業(yè)務(wù)方想象大相徑庭”的尷尬;另一方面,在開發(fā)過程中,每個階段結(jié)束,可以提供一個階段的生產(chǎn)力,作為開發(fā)方,在面對質(zhì)疑時,有足夠的資本和底氣。

  從個人方面,我注意到,職業(yè)開發(fā)人員還有另一個特點:是可以相當(dāng)精確地估計某個“小活”的工作量。以我自己和我的一些朋友為例,面對一些細致而且明確的需求,我們經(jīng)?梢跃_估計到工作量,時間精確到以半小時計。在緊密協(xié)作的“背靠背”編程中,我會說:現(xiàn)在是幾點,所以我會在幾點之前,給你提供怎樣的功能,其行為是怎樣的,接口是怎樣的(行為和接口可以事先約定)。這樣的自信,既要求對所需技術(shù)、會遇到難題的把握,也要求在頭腦里對任務(wù)有完整清晰的模型。雖然難度不小,但能做到這一點,確實是職業(yè)素養(yǎng)的典型體現(xiàn)。