我們組的開發人力一直比較緊張,今年春節后,高層終於給了幾個headcount,我們可以開始招人了。從三月初我們就開始找簡歷,渠道有拉鈎,內推,我司自己的招聘網站和智聯等。簡歷篩了很多,也打了很多電話,叫過來面試了很多人,可是到目前為止,已經三個月了,我們只招到了兩個人,這兩個人都是內推來的。
我負責第一次電話面試,如果電話面試覺得可以,我們會叫過來 做一份筆試題,然后我會針對筆試題再進行提問。我們想要招聘的,是一批中級.net開發工程師,工作經驗最好在3到6年,在這三個月的面試過程中,這些候選者鮮有我覺得滿意的。所以我就想,作為工作了3到6年的.NETer,到底應該掌握哪些知識。
我負責的電話面試和筆試,着重考察.NET基本概念和基礎知識,不涉及任何項目經驗。在電話面試時,我問的第一個問題就是介紹一下.NET的類型系統,不過很遺憾的是,很多候選者在聽到“類型系統”這個詞后,完全不知道我的發問點在哪里,他們並不知道“類型系統”指的到底是什么,所以我不得不換個提問方式,轉而問“什么是引用類型什么是值類型,有什么區別“,后者的問法,只是前者的一個子集而已。從.NET類型系統,可以發問.NET如何實現跨語言開發,所有類型的共同父類是什么,為什么要分引用類型和值類型,堆和棧的區別,裝箱拆箱等等一系列問題,遺憾的是到目前為止還沒有人能夠說出我想要的答案。關於引用類型和值類型,候選人的回答也是五花八門的,有些人根本沒聽所過這兩個術語,有些人聽過,但是搞不清楚棧和堆的區別。而大部分的人,則完全不清楚拆箱和裝箱的概念。讓我感到吃驚的是,很多人認為拆箱裝箱就是父類型和子類型之間的類型轉換。最近面試的一個有10年經驗的.net開發者,竟然認為裝箱拆箱與反射有關。
除去考察類型系統,我電話里還會問到泛型,委托,linq,多線程編程,異步。遺憾的是大部分候選者對於這些在.NET編程中經常用到的技術掌握的也並不好,這幾個發問點里,可能多線程和異步編程的問題會有點難度,不過我認為作為一個有五年左右工作經驗的人,理應掌握一些多線程和異步編程的技能。當我問道大部分候選者關於多線程和異步編程的問題時,他們都會回答工作中沒有用到過所以不清楚,在我看來這根本不是理由。而前三個發問點:泛型,委托,linq,則是非常基本的.NET編程技能,但是很多人僅限於用過,但是卻從未進行過一丁點的思考過,為什么.NET要引入泛型,委托和linq,引入它們是為了解決什么樣的問題,關於它們的實現原理大致是什么樣子的。
在筆試題中,我們會考察進程線程的基本概念,ado.net的使用,閉包,簡單的設計模式。遺憾的是,很多人並不能描述清楚進程的概念。在orm大行其道的今天,很多.NETer已經不知道如何使用原始的ADO.NET來訪問數據庫了,有些工作了五年的候選者從未聽說過閉包,有些人無法畫出經典設計模式的uml類圖。在面試了眾多候選者之后我很驚訝,關於這些軟件開發的基本技能,竟然有這么多人已經無法掌握。
我面試的這些候選者,有相當一部分人都有在大公司的工作經歷,包括微軟的,攜程的。簡歷上的title也有不少寫的是開發組長,技術經理,架構師之類。簡歷上的項目經驗列出來有好幾頁,多的我都看不過來。然而他對於基本技能的掌握情況實在令人堪憂。有相當一部分人,滿足於做了一個又一個的項目,沾沾自喜。
我在我上一家公司時,我的直屬leader對我說“我們是軟件工程師,不是碼農,不要滿足於做成了多少個項目,這些項目都大同小異,能做一個就能做一百個。”這個leader對我的影響非常的大,他教會了我思考問題的方式。任何技術的出現,都是為了解決一類實際問題,並且有個逐步完善的過程。當我們在進行軟件開發用到了某種技術手段時,有多少人會去思考一下為什么我要采用這種技術,這種技術解決了什么問題,如果不用會有哪些不便,在這種技術出現之前,是如何解決這類問題的。反過來,能不能自己嘗試造個輪子,簡單實現一下這個技術手段的功能。論語中說“學而不思則罔思而不學則殆”,學與思結合,收獲會有很多。
最后回到題目中來,3到6年的.NETer到底該掌握哪些知識。我認為答案就在clr via c#中。其實我面試時問到的所有問題都可以從這本書中找到答案。c#的經典書籍並不多,如果只看一本的話這一本就夠了,而且要反復看,常常看,每次看可能都有新收獲。
我們人還沒有招滿,如果你覺得自己對.NET的掌握非常好,可以發簡歷到我的郵箱里lukexywang@qq.com。如果你還會c++的話,就更好了。工作地點在深圳南山區。
======================================分割線====================================
昨天發完文之后,有個大學同學到深圳來出差,就出去了,到晚上才回來,文章發出來的時候我就想到可能會引發很多的爭論,大家下面的評論我都看了,談談我的看法。
下面有人說想到了老趙的博文http://blog.zhaojie.me/2011/03/my-interview-questions-for-dotnet-programmers.html,這位同學看起來跟我是同時期混博客園的,七八年前的博客園是非常活躍的,老趙對我的影響比較大。
有人說天天加班沒時間學習的問題,人不想做一件事的時候總是可以找到一萬個借口。
有人說不知曉原理也能做出項目,是這樣子的。就我現在來說,我的數據庫知識非常薄弱,僅限於會寫查詢sql這樣子。索引的原理,存儲過程,數據庫內置函數的使用這些我都不太了解,而且我也認為時間有限了解這些知識的原理還不是目前最重要的,因為我並不是DBA。我要招一個.NET開發人員,.NET作為安身立命的基本技能都還無興趣去了解的話,我不知道還能去了解什么東西。
有人說我面試的這些知識點是考背書,有人說剛畢業時都記得,工作時間長了都忘記了。看起來你們當時確實只是背書而已。
關於小蝶的評論,我司的面試至少有四輪,我第一輪就是考察基礎,項目經驗后面會有人問。基礎知識的學習,一開始可能是背書,但是在后續若干年的工作過程中,在寫代碼時有沒有想過為什么代碼要寫成這樣子。我面試時問會不會用EF,或者會不會用NH,並沒什么用處,因為並不是人人都用過orm,掌握這些工具類庫的用法也並不會花費太多的時間。我第一份工作是winform開發,第二份工作開始asp.net開發,在第二份工作之前我沒有任何web開發的經驗,唯一的web知識就是http協議了解一點點。還是那個對我影響比較大的leader說的,做網站這種東西,做一個和做一百個差距不大,看着demo寫幾次就ok了。關於基礎知識的掌握和理解,是不是可以在日常工作中融入到你的思維里。一個知識你認為你掌握了,那你是不是能給別人說清楚,能給別人說清楚才算你掌握了,並不是背書背會了就行。關於小蝶最后提問的那個問題,非托管數據到托管環境,如何避免裝箱。這個問題我第一次遇到,不過你的非托管數據指的是什么呢?裝箱只會在值類型轉換成引用類型時發生,非托管數據到托管數據映射,就一定發生這種類型轉換?
來自大公司的候選人,我自然對他們的期待也比較高。這里並沒有酸葡萄心里,因為我司也不是個小公司。
有人說“不要用自己掌握的東西來考驗別人,別人深究的技術點你不一定知道“,我要招聘一個.NET開發者,難道我的題目超綱了?問的不是.NET開發應該掌握的技能?
江寧織造的說法很中肯,關於理論和實踐,任何實際應用都是有相應的理論支撐的,在實際操作的過程中,支撐這種具體實踐技能的理論是一定可以提現出來的。我覺得這二者不能割裂開看。確實招一個能干活的人很容易,我也不需要考察這些,直接問有沒有用過ASP.NET MVC ,EF,Redis,ZooKeeper就可以了。但是在寫代碼的時候,由於對基礎的不了解,就會在不經意間埋下一個雷而不自知,這個雷最終可能會體現為一個線上的偶發問題,在業務量較小時,可能通過屢試不爽的“重啟”來解決了,但是當業務量激增百倍時,偶發性問題的嚴重性就出來了,如何去查找原因。有時候線索就在你手邊,但是卻發現不了。
本文是我多年從事.NET開發的一些體會,也並不就是標准答案,因為我水平還不夠給出來我題目中的標准答案。能引發討論就好。我給題目加個問號。
我面試時要問的,就是通用類型系統(CTS),https://msdn.microsoft.com/en-us/library/zcx1eb1e.aspx