如何招聘一個(gè)能干活的程序員
寫(xiě)這篇文章不是件容易的事情,因?yàn)樾枰e一些實(shí)例,就會(huì)牽扯到過(guò)去現(xiàn)在的各種見(jiàn)聞,也會(huì)牽涉到業(yè)界的各種看法。既然博客也是公開(kāi)狀態(tài),還得考慮有的話是否需要委婉一點(diǎn)講… 不過(guò)畢竟出來(lái)混了也有一年半載,對(duì)這方面還算略有心得,那就班門(mén)弄斧一下,還望高手不吝賜教。
關(guān)于一個(gè)程序員該具備怎樣的能力,這篇帖子里面一共講了7點(diǎn)。這7點(diǎn)本身沒(méi)錯(cuò),放之四海而皆準(zhǔn)。但是對(duì)于程序員這一個(gè)特定的群體,似乎又顯得過(guò)于寬泛。有一些比如善于溝通這樣的能力更多是靠環(huán)境激發(fā)出來(lái)的。如果不幸混進(jìn)一個(gè)國(guó)企,那其實(shí)鍛煉更多的還是和領(lǐng)導(dǎo)套近乎和推卸責(zé)任的能力… 所以我認(rèn)為,一個(gè)優(yōu)秀的程序員有兩個(gè)最核心的能力是不可代替的:解決問(wèn)題的能力與學(xué)習(xí)能力。
先來(lái)說(shuō)說(shuō)“解決問(wèn)題”的能力。
這個(gè)能力是相當(dāng)寬泛的:debug是解決問(wèn)題;設(shè)計(jì)某種架構(gòu)是解決問(wèn)題;提高用戶體驗(yàn)是解決問(wèn)題;根據(jù)需求給出整體的解決方案同樣是解決問(wèn)題。概括起來(lái)就是本文表退中的“能干活”,或者說(shuō)就是“getting things done”。解決一個(gè)問(wèn)題實(shí)際上分兩方面:其一需要有足夠的技術(shù)能力找到解決方案;其二需要對(duì)業(yè)務(wù)有充分的了解,明白到底該怎么做才能達(dá)到用戶的預(yù)期。結(jié)合實(shí)際來(lái)說(shuō),做一個(gè)游戲不僅要完成策劃提出的功能需求,還要考慮做出來(lái)的功能操作上是否便利,是否符合玩家的習(xí)慣和心理預(yù)期,是否可能引起玩家的誤解和不滿等等… 在技術(shù)熟練的情況下,絕大部分的功能要實(shí)現(xiàn)起來(lái)并不需要花很大的精力在技術(shù)上,而是需要把精力投入到用戶體驗(yàn)上面,對(duì)每一個(gè)細(xì)節(jié)都斤斤計(jì)較,這樣才能做出精品。這和技術(shù)實(shí)力并沒(méi)有太大的關(guān)系,很多時(shí)候關(guān)鍵看執(zhí)行者的耐心、細(xì)致,甚至是品位。在對(duì)大部分游戲系統(tǒng)有充分了解的前提下,只需要策劃給一個(gè)大致的思路,略加點(diǎn)撥就可以做出符合預(yù)期的實(shí)現(xiàn),這才是一個(gè)合格的游戲程序員應(yīng)有的素質(zhì),吃過(guò)了五***料理,雖然未必能總結(jié)出什么理論,但直覺(jué)會(huì)讓你明白什么是一定會(huì)被策劃打回來(lái)的狗屎,所以這就是我會(huì)去花時(shí)間玩大量不同類型游戲的主要原因(終于成功為自己玩游戲找到借口,噢耶~),
熟悉業(yè)務(wù)是解決問(wèn)題一方面,另一方面就是技術(shù)水平。雖然大部分情況下不需要非常高深的技術(shù),但如果牽涉到了一些關(guān)鍵的核心算法,或是性能調(diào)優(yōu)、架構(gòu)設(shè)計(jì),技術(shù)水平就顯得尤為重要。這就一定會(huì)牽涉到學(xué)習(xí)能力的問(wèn)題。不可否認(rèn)的是,技術(shù)積累非常重要,但同一個(gè)方向上的積累同樣會(huì)造成思維定勢(shì),從而不愿主動(dòng)走出自己的舒適區(qū)。光從解決問(wèn)題的角度而言,在碰到難題時(shí),首先需要嘗試相對(duì)穩(wěn)定和成熟的解決方案,但同時(shí)也不能排斥在必要的時(shí)候使用一些比較“古怪” 的方法。保持開(kāi)放的心態(tài)(keep an open mind)在解決問(wèn)題時(shí)同樣也很重要。
在來(lái)公司以后,我參與的***個(gè)項(xiàng)目是一款和《百戰(zhàn)天蟲(chóng)》相近的回合制射擊類游戲。當(dāng)時(shí)剛進(jìn)入項(xiàng)目,聽(tīng)了策劃介紹后我就把戰(zhàn)斗場(chǎng)景按難度分成了四個(gè)主要部分:1. 人物移動(dòng)等基本操作 2. 場(chǎng)景視角縮放 3. 炮彈飛行軌跡 4. 地形破壞。實(shí)際上前三個(gè)部分在技術(shù)上沒(méi)有太大的難度,主要還是跟著策劃的思路走,但第四個(gè)問(wèn)題在當(dāng)時(shí)確實(shí)把我給難住了,因?yàn)樵谶@方面沒(méi)有技術(shù)積累,根本連如何解決的思路都沒(méi)有。之后用過(guò)了兩個(gè)方案,一是用物理引擎來(lái)實(shí)現(xiàn)炮彈飛行和破壞,這個(gè)方案確實(shí)可行,但與游戲的整體風(fēng)格不符,而且物理引擎本身也會(huì)有一定限制,在不熟悉的情況下適得其反。第二個(gè)方案是用openGL提供的一些接口,通過(guò)遮罩圖來(lái)實(shí)現(xiàn)破壞。這個(gè)方案在應(yīng)用中發(fā)現(xiàn)效率太低,炮彈落地時(shí)會(huì)需要將近一秒才能重繪完成,之后發(fā)現(xiàn)是openGL的運(yùn)算接口占用了大部分時(shí)間,這也是很難進(jìn)行調(diào)優(yōu)的。當(dāng)時(shí)沈晟給了一個(gè)解決方案,概括起來(lái)就是自己實(shí)現(xiàn)一套相關(guān)算法,然后重載材質(zhì)。當(dāng)然這套算法比較hack,需要直接操作內(nèi)存中的圖片數(shù)據(jù),當(dāng)時(shí)因?yàn)閷?duì)引擎和圖片格式不熟結(jié)果我沒(méi)有看懂沈晟給的示例….后來(lái)又去調(diào)視角縮放花了很長(zhǎng)時(shí)間,在將近一個(gè)月后某個(gè)周末的早上突然開(kāi)了竅最終把這個(gè)問(wèn)題搞定了。實(shí)際花了一個(gè)多星期的時(shí)間寫(xiě)出了***的解決方案,只需要0.1 秒就可以完成地形破壞的運(yùn)算與重繪,順便還解決了人物移動(dòng)和碰撞檢測(cè)的問(wèn)題。當(dāng)然那套算法在實(shí)現(xiàn)時(shí)很丑陋,因?yàn)槭褂昧朔浅5讓拥姆绞剑€存在一些溢出的 bug需要調(diào)整。不過(guò)這個(gè)解決這個(gè)問(wèn)題的過(guò)程給了我很大的啟示:學(xué)習(xí)能力,特別是底層的基礎(chǔ)知識(shí)非常非常之重要。現(xiàn)在想來(lái),如果之前的一份工作不是寫(xiě)C語(yǔ)言而是隱藏了太多底層實(shí)現(xiàn)的JAVA,恐怕就幾乎不可能解決這個(gè)問(wèn)題。
學(xué)習(xí)能力:重視基礎(chǔ),不糾結(jié)于細(xì)節(jié)
在上一篇文章中,我提到了程序員能力的兩方面——解決問(wèn)題的能力與學(xué)習(xí)能力。這兩點(diǎn)可以說(shuō)是相輔相成的。而在學(xué)習(xí)能力中,基礎(chǔ)又是必不可少的一條。下面就來(lái)說(shuō)說(shuō)我對(duì)基礎(chǔ)的理解。
當(dāng)我還在大學(xué)的時(shí)候,我的數(shù)學(xué)成績(jī)一直不太好。有一個(gè)同學(xué)在其他方面毫不出眾,但他所有和數(shù)學(xué)相關(guān)的學(xué)科都學(xué)得非常好,考試前也只是翻翻書(shū),并沒(méi)有付出相當(dāng)大的精力和時(shí)間。我始終以為他天賦異稟,但后來(lái)才發(fā)現(xiàn),無(wú)論學(xué)到什么新的東西,他總是能用非常簡(jiǎn)潔的語(yǔ)言解釋這個(gè)概念的本質(zhì)。換而言之,在絕大多數(shù)人還在死記硬背的時(shí)候,他已經(jīng)了解到了一些本質(zhì)性的東西——這些東西可以把所有和數(shù)學(xué)這門(mén)學(xué)科相關(guān)的知識(shí)串聯(lián)到一起,對(duì)他而言,看問(wèn)題的視角也和絕大多數(shù)人不同了。
什么是“基礎(chǔ)”?我認(rèn)為這是對(duì)一門(mén)學(xué)科本質(zhì)的理解。什么是計(jì)算機(jī)科學(xué)的基礎(chǔ)?計(jì)算機(jī)架構(gòu),計(jì)算機(jī)程序的構(gòu)造,編譯原理。幾乎所有的現(xiàn)代計(jì)算機(jī)都基于馮諾伊曼架構(gòu),為何這一架構(gòu)會(huì)成為現(xiàn)代計(jì)算機(jī)的主流?它又是如何設(shè)計(jì)出來(lái)的?我們都知道一個(gè)程序的地址空間包含堆區(qū)、靜態(tài)區(qū)和棧區(qū),那么為何要將其分開(kāi)設(shè)計(jì)?為何在預(yù)編譯時(shí)需要進(jìn)行詞法和語(yǔ)義分析?能回答出這些問(wèn)題中哪怕一個(gè),就說(shuō)明對(duì)這些本質(zhì)性的問(wèn)題已經(jīng)有了較深的了解。
最近我一直在看王垠的博客 ,其中提到了很多關(guān)于程序設(shè)計(jì)方面的知識(shí)。此人讀過(guò)三個(gè)博士學(xué)位均未畢業(yè),但不可否認(rèn)的確是個(gè)大牛。他在文章中提到的很多東西,感覺(jué)就讓人上升到了一個(gè)新的層次。雖然計(jì)算機(jī)語(yǔ)言層出不窮,但是歸根結(jié)底,其本源都是相同的。有經(jīng)驗(yàn)的程序員可以很快地學(xué)習(xí)一門(mén)新語(yǔ)言,更多地是因?yàn)閷?duì)程序語(yǔ)言本身的了解,所以一通百通;至于一些技術(shù)細(xì)節(jié),大部分時(shí)候通過(guò)查資料就可以解決問(wèn)題。遺憾的是,在中國(guó)很多招聘者與應(yīng)聘者都沒(méi)有意識(shí)到這一點(diǎn),于是就出現(xiàn)了“程序員干到30歲就得轉(zhuǎn)行”這種錯(cuò)誤的趨勢(shì)。很多人并不明白他們應(yīng)該用什么方法來(lái)積累經(jīng)驗(yàn),編程本身對(duì)他們而言也許只是種維生手段。而雇主也用應(yīng)試教育的思維去挑選應(yīng)聘者,在這樣的前提下挑選出來(lái)的往往只是一些代碼機(jī)器。當(dāng)然代碼機(jī)器在外包公司這種勞動(dòng)力密集的地方還是大有用處的,誰(shuí)叫我們國(guó)家人口眾多,勞動(dòng)力從來(lái)不缺呢,呵呵。
廢話講了一大段,接下來(lái)還是講講關(guān)于如何招聘吧。
首先需要聲明的一點(diǎn)是,以下這些建議,不適合外包公司、國(guó)有企事業(yè)單位,只適合100人以下,團(tuán)隊(duì)和人事關(guān)系相對(duì)簡(jiǎn)單的中小型公司及創(chuàng)業(yè)型團(tuán)隊(duì)。當(dāng)然,如果是大公司下,團(tuán)隊(duì)leader比較強(qiáng)勢(shì)和開(kāi)明,有較大的資源調(diào)配及話語(yǔ)權(quán),也是可以一試的。
在我看來(lái),要招聘到一個(gè)“能干活”的程序員,有以下幾條原則:
1. 此人是否和團(tuán)隊(duì)有著相近的價(jià)值觀,作為一個(gè)團(tuán)隊(duì)的leader,是否愿意能夠留住這名員工?
之所以把這一條放在***位,是因?yàn)閲?guó)內(nèi)現(xiàn)在IT行業(yè)人員的流動(dòng)性實(shí)在是太離譜了,干個(gè)一年拿了年終獎(jiǎng)就跳槽的事情比比皆是。在IT這個(gè)行業(yè),新員工加入任何公司都至少需要半年左右的磨合期才能發(fā)揮出其應(yīng)有的水準(zhǔn),相當(dāng)于一半的時(shí)間都在磨合中渡過(guò),對(duì)于自己和整個(gè)團(tuán)隊(duì)都不是件好事。
尋找價(jià)值觀相近的人共事,首先就可以確保這個(gè)人對(duì)團(tuán)隊(duì)所從事的事業(yè)和目標(biāo)有著相當(dāng)?shù)呐d趣和動(dòng)力。這些興趣和動(dòng)力,可以轉(zhuǎn)化成額外的工作成果,這也是優(yōu)秀程序員和碼農(nóng)之間最本質(zhì)的區(qū)別。
2. 注重細(xì)節(jié),但不拘泥于細(xì)節(jié)
把這一條放在第二位,是因?yàn)槲铱吹搅诉@么一道題:
- int a=2; a+=a-=a*a; a=?
首先我要聲明的是,如果在任何面試中面試官給我出類似的題目,即便我沒(méi)有立刻走人,這家公司在我心目中的地位也會(huì)一落千丈。在實(shí)際編程中,最重要的是代碼的可讀性和非二義性。在 不同環(huán)境 下,由于編譯器的實(shí)現(xiàn)不同,這道題的答案是不唯一的。何況這樣的寫(xiě)法在實(shí)際工程中除了造成其他同事的困惑和可移植性降低之外,一無(wú)是處。
前兩天我還碰到了一個(gè)類似的問(wèn)題(寫(xiě)得不太嚴(yán)謹(jǐn),各位包涵):
- string text = "123";
- this->methodA(text, text.append("456"));
- void methodA(string textA, string textB)
- {
- string textC = textA;
- }
問(wèn) textC 的值是多少?
很多人***反應(yīng),textC的值當(dāng)然就是123。對(duì)函數(shù)的壓棧順序有一些了解的人會(huì)認(rèn)為是123456,因?yàn)閰?shù)從右至左壓棧,會(huì)先執(zhí)行append方法將text值擴(kuò)展為123456。但在實(shí)際應(yīng)用中,ios平臺(tái)上的執(zhí)行結(jié)果是123,安卓平臺(tái)編譯后的執(zhí)行結(jié)果是1230。是不是很奇怪?其實(shí)這是一道不錯(cuò)的面試題,但不應(yīng)該直接問(wèn)面試者執(zhí)行結(jié)果,而應(yīng)該問(wèn)這段程序中可能存在的問(wèn)題,以及改進(jìn)方法。最簡(jiǎn)單的方法就是加一行string text2 = text.append(“456″),這樣就不存在壓棧順序不同導(dǎo)致不同平臺(tái)下結(jié)果無(wú)法預(yù)期的問(wèn)題,代碼的移植性也就更好了。如果拘泥于一個(gè)“正確”答案,那就陷入了應(yīng)試教育的泥潭。我們要招的是一個(gè)能夠解決問(wèn)題的人,而不是糾結(jié)于茴字有幾種寫(xiě)法的書(shū)***。
當(dāng)然,這些細(xì)節(jié)問(wèn)題可以體現(xiàn)出一個(gè)人的功力,但不能本末倒置,以了解所有的細(xì)節(jié)為目標(biāo)。在面試中,我還是主張這些問(wèn)題盡量少問(wèn),如果面試者無(wú)法回答,可以用探討的方法給出一些提示,主要還是觀察其思路和態(tài)度為主,不宜過(guò)分糾結(jié)。我曾經(jīng)經(jīng)歷過(guò)國(guó)內(nèi)某規(guī)模不小的公司一場(chǎng)很不愉快的電話面試,面試我的人聽(tīng)語(yǔ)氣應(yīng)該也不是個(gè)等閑之輩,遺憾的是他在20多分鐘的時(shí)間里有15分鐘都在一些細(xì)節(jié)問(wèn)題上面糾纏不休。他問(wèn)了我在之前工作中碰到多線程問(wèn)題的解決方案,我當(dāng)時(shí)回答他在某某地方使用了讀寫(xiě)鎖,之后他就開(kāi)始不停詢問(wèn)為什么要用讀寫(xiě)鎖等等等等。其實(shí)理由很簡(jiǎn)單,因?yàn)樵谀莻€(gè)特定條件下讀操作次數(shù)遠(yuǎn)遠(yuǎn)多于寫(xiě)操作,所以讀寫(xiě)鎖是***解決方案(事實(shí)上我在設(shè)計(jì)時(shí)也是這么想的)。他可能是要問(wèn)如何盡量避免加鎖達(dá)到性能優(yōu)化,但是首先性能優(yōu)化必須在有充足證據(jù)證明效率低下的情況下才有必要進(jìn)行,而我當(dāng)時(shí)并沒(méi)有碰到這種情況,所以沒(méi)有必要為了一個(gè)可能的性能問(wèn)題大費(fèi)周章。我當(dāng)然也不能對(duì)他說(shuō)“你這個(gè)臆想癥患者給老子閉嘴”,于是只能在尷尬中渡過(guò)這個(gè)問(wèn)題。后來(lái)他問(wèn)了我一個(gè)gdb的使用問(wèn)題,我想他的本意應(yīng)該是看看我調(diào)試程序的功力怎樣,沒(méi)想到他開(kāi)始問(wèn)我gdb的常用命令有多少多少個(gè),條件斷點(diǎn)該如何設(shè)置等等等等。對(duì)于這些問(wèn)題,我完全可以找一本gdb使用手冊(cè)扔在他面前。經(jīng)過(guò)了這場(chǎng)面試,不管對(duì)方的態(tài)度如何,這家公司的技術(shù)實(shí)力在我的心中也已經(jīng)打了一個(gè)大大的問(wèn)號(hào)。
在面試中,一個(gè)面試官應(yīng)該盡可能地去了解并引導(dǎo)對(duì)方解決問(wèn)題的思路,而不是拿一些細(xì)節(jié)問(wèn)題是否答出了“標(biāo)準(zhǔn)”答案來(lái)評(píng)判一個(gè)人水平的高下。畢竟,細(xì)節(jié)知識(shí)上的欠缺很容易彌補(bǔ),良好的思維習(xí)慣卻是無(wú)法在一朝一夕養(yǎng)成的,這一點(diǎn)對(duì)于評(píng)判那些應(yīng)屆畢業(yè)生尤為重要。
順便多提一句,很多公司的招聘啟事在應(yīng)聘者要求中往往會(huì)不小心寫(xiě)錯(cuò)一些技術(shù)的名稱,或是犯一些低級(jí)錯(cuò)誤,這會(huì)讓?xiě)?yīng)聘者對(duì)這家公司的專業(yè)性產(chǎn)生懷疑,反之亦然。在簡(jiǎn)歷和招聘啟事上,還是多注意一些細(xì)節(jié)吧~
3. 良好的編碼風(fēng)格
在編程中,最困難的事情莫過(guò)于起變量和函數(shù)名。好的變量和函數(shù)名能讓人一眼就看出這段程序的功能,而糟糕的名字(沒(méi)錯(cuò)!就是我上面寫(xiě)的textA這種玩意,所以我也是個(gè)爛程序員)往往讓人摸不著頭腦。由于迄今為止還沒(méi)有任何一種主流編程語(yǔ)言支持英文以外的字符,所以使用標(biāo)準(zhǔn)的英語(yǔ)起名應(yīng)該成為共識(shí)。這里我要吐個(gè)槽,我在代碼中發(fā)現(xiàn)了一個(gè)叫“Supersport”的玩意,光看這名字還以為是什么比賽,一問(wèn)才知道是“競(jìng)技場(chǎng)”,實(shí)在想不通為什么不用”Arena”。還有像強(qiáng)化裝備翻譯成“upgrade”也容易造成歧義,國(guó)外一般都用 “enhance”特指裝備強(qiáng)化。還有像“baoxiang”,“yamede”,”yikuyiku”這種變量名真是讓我淚流滿面….(后面兩個(gè)是我杜撰出來(lái)的,LOL)。所以,要辨別一個(gè)程序員的水平,***的辦法就是看看他的代碼變量名是否清晰,換行縮進(jìn)的格式是否嚴(yán)格,會(huì)不會(huì)寫(xiě)一個(gè)幾百行的函數(shù)不知道把其中的功能塊進(jìn)行封裝….
4. 是否有個(gè)人博客網(wǎng)站、GitHub、stackoverflow
是的,如果一個(gè)應(yīng)聘者有以上這些內(nèi)容,我一定會(huì)考慮優(yōu)先面試及錄用他。
以上這些內(nèi)容都需要在平時(shí)擠出業(yè)余時(shí)間來(lái)完成。架設(shè)網(wǎng)站,給開(kāi)源軟件和社區(qū)作出貢獻(xiàn),在專業(yè)性上肯定不如嚴(yán)謹(jǐn)?shù)娜粘9ぷ鳎瑯有枰冻鼍蜁r(shí)間。如果一個(gè)人愿意在業(yè)余時(shí)間做一些和技術(shù)相關(guān)的事,至少能說(shuō)明這個(gè)人不僅僅是想混口飯吃,而是將其作為一種愛(ài)好,這樣的人假以時(shí)日必有所長(zhǎng)。這些公開(kāi)資料同樣可以檢驗(yàn)應(yīng)聘者的真實(shí)水平:個(gè)人網(wǎng)站可以看出一個(gè)人的品味及價(jià)值觀;github上的代碼可以看出編碼風(fēng)格;StackOverflow上的活動(dòng)可以了解他的表達(dá)能力和英語(yǔ)水平。能做到這些的應(yīng)聘者在國(guó)外較多,但在中國(guó)并不多見(jiàn)。當(dāng)然,還是以興趣和實(shí)際能力為主,做不到也無(wú)需強(qiáng)求。
前前后后花了快一個(gè)月總算把這篇文章寫(xiě)完了!我寫(xiě)文章的速度的確不容樂(lè)觀啊…..總算是堅(jiān)持到***一刻了!
原文鏈接:如何招聘一個(gè)能干活的程序員



















