復盤|一次失敗的技術面試:看人家是怎么拿到了 5 個offer

3 評論 8896 瀏覽 34 收藏 29 分鐘

編者按:對于開發者來說,找工作最難的莫過于技術面試。Fredrik Strand Oseberg在freeCodeCamp上發表了一篇文章,介紹了自己學習編程6個月后找工作獲得5個offer的經歷。

我先給大家介紹一下我的工作背景。

在過去的6個月里,我一直在孜孜不倦地研究我的投資組合和個人項目。最值得注意的是,我創建了CryptoDasher,這是一種能夠實時跟蹤加密貨幣和投資組合價值的工具。我還參加了一家名為Loopring的中國區塊鏈公司舉辦的設計競賽。

我覺得已經準備好了。我向挪威一家大型咨詢公司投了簡歷,應聘其前端開發人員的工作,并引起了他們的注意——至少我是這么認為的。

通過筆試和第一輪面試后,我被邀請參加技術面試。這是最重要的一個環節。

我很緊張。

“你應該怎們準備這個技術面試呢?”我問自己。我四處詢問,瘋狂地在互聯網上搜索相關資料。并在YouTube上看了一些模擬面試。以下是我使用的一些資源:

我在這些材料上花了好幾個小時的時間,盡力為即將到來的面試做好準備。如果我在面試前沒有盡最大的努力,我會感到很不舒服,我相信你明白那種感受。

面試的那天到了。我早上4點就醒了。

很害怕,很好奇,也很興奮。

我在公司的大廳里遇到了面試官,和他一起去了他們的辦公室。

我們之間的交談很愉快,并相互交換了聯系方式。我比較擅長軟技能,所以我希望能早點展示這種能力。很快,我又見到了另一位面試官,然后去了會議室。

面試剛開始很順利。我們每個人都進行了自我介紹,他們開始問我一些關于我的背景的問題。

他們問我,開始學習編程時,最困難的部分是什么,我想學習什么樣的技術,我想要教別人什么技術,以及我覺得令人興奮的東西。

在這一點上,我覺得面試很順利。我很想知道更多關于這家公司的信息,我覺得已經與面試官在某些方面有了共鳴。

然后技術部分開始了。

首先,我被要求解釋我在筆試中的代碼。是一個為數據集創建分頁,并將其顯示在列表中的任務。我用React編寫了它,然后我開始檢查代碼。當我們瀏覽這些代碼時,我的面試官會問我一些問題。我將試著把他們提出的問題列出來,以及給出我認為的面試官想要的答案。

你知道單元測試是什么嗎?代碼的哪一部分可以進行單元測試?

說實話,我想我回答錯了。單元測試是一段代碼,用于驗證一個單元或源代碼的特定部分是否執行了它的預期目的,而不會產生不必要的副作用。我不記得我說了什么,但我可能把它和集成測試混在一起了。在面試之前,我確實對單元測試和TDD有一定的了解,但在這種程度上,可能已經超出了我的理解范疇。

在進行了一些討論之后,我得出結論:我可以對分頁函數進行測試,因為它對程序中的大部分邏輯負責。

你將如何改進這個項目?

我發現這個問題有點令人困惑。當我完成筆試(幾周前)時,我就被要求列出一份關于該項目的改進清單。假設面試官已經知道了這些,我就很難找到什么改進空間了。

我很快就明白了,面試官對我在電子郵件中提到的事情很感興趣,于是我開始提到這些點——錯誤處理、移動優化、Ajax調用加載時的用戶反饋、以及大型數據集的頁面管理。

你知道BEM是什么嗎?你在代碼中使用的是BEM嗎?

我回答說我知道BEM是什么。這是一個用于CSS項目的命名約定,代表Block、Element、Modifier。我還回答說,在我的CSS類命名中,我受到了BEM的啟發,但它并不完全是BEM,因為它沒有遵循所有的BEM規則。

你如何使這個網站更具移動友好度?

CSS媒體查詢。這是最主要的一個。他們想知道,我是否知道如何利用媒體查詢來讓網站做出響應。

到目前為止。面試進展很好。我覺得我很完整地回答了這些問題,盡管我需要在了解面試官的具體想問什么之前,先討論一下這些問題。

編程挑戰

然后他們要求我擴展功能。我被要求實現一種排序機制,該機制將采用分頁數據集,并根據名稱和編號對它們進行重新排列。我有幾分鐘時間來思考這個問題。

我問了一些問題,比如我是否應該使用內置的JavaScript排序函數,或者構建自己的函數(稍后我們會看到,這是一個很大的錯誤)。分頁數據以對象數組的形式存在,其中每個對象都有一個包含20個對象的數據數組,這些對象代表列表中的每一個項目。我提出了以下的算法:

  1. 將每個分頁對象數據數組合并到一個新的數組中;
  2. 對新數組進行排序;
  3. 對排序后的數組進行分頁,并將組件的狀態設置為新近排序的數組。

這是一個很好的算法。我很快就知道該怎么做了?,F在唯一的問題是實施它。這就是我犯錯的地方。

首先,我花了很長時間來找出如何組合這些數組。我承認,這種情況給我帶來了一些壓力。因為我本可以用一個簡單的reduce來解決它的時候,我做了各種奇怪的事情。公平地說,我當時并不像現在這樣熟悉reduce。

//我應該做的

const pageData = pages.reduce((startingValue,page)=> startingValue.concat(page.data),[])

//我最終做的

const pages = this.state.pages;
const pageData = [];pages.forEach(page => pageData = pageData.concat(page.data));

現在我有了一個包含所有數據的數組,我需要編寫邏輯來對其進行排序。由于我在編程方面的經驗,在很大程度上是基于我自己構建的項目,所以我花了很長時間來處理JavaScript排序函數。我必須要查資料,所以,我花了一些時間來檢查MDN和stack overflow上的例子,以便我在實現它之前真正理解它。

我只是部分地完成了分揀工作,我被困在這里好一段時間。數組中的大多數名稱都是正確排序的,但是在頂部有一些名稱是無序的。在這個時候上,我試圖保持冷靜,但在我的腦海里,已經崩潰了。我想要知道為什么它沒有正確排序。我被困在這里的時間比我想承認的要長。

經過面試官的討論和督促。我最終想起來了字符串是按照它們的ASCII值排序的。大寫字母的值是65-90,小寫字母的值是97-122。沒有正確排序的結果有一個大寫的首字母,它具有先排序的效果,因為它們的ASCII值比小寫字母要低。這是一個我永遠不會再犯的錯誤。

當找到問題后,我立即用用.toLowerCase()解決了這個問題。

現在只剩下一件事了。

將已排序的數據傳遞到分頁函數中。

在這里,我遇到了一個麻煩。

分頁函數需要一個Ajax響應,并將每一項傳遞給一個formatData函數,該函數提取相關片段并返回一個新對象。然而,當我試圖傳遞被排序的數據到這個函數的新數組時,它將不再具有原來的屬性名,并且函數會給出一個錯誤。

我花了一些時間研究這個問題,然后我才發現我必須將formatData從分頁函數中移出,并在數據傳遞給分頁函數之前在響應數據上執行它。

完成了這些工作,并進行了一些更小的修改,代碼終于可以工作了。雖然花了一些時間,但最終我解決了。

此時,技術面試的編程部分結束了。

我感到精疲力竭。

我們最后又聊了一會兒,然后結束了面試。在結束之前,我問題一些問題,他們告訴了我更多關于他們公司的事情。

然而,面試并沒有就此止步。

我仔細復盤了這次面試,琢磨我做錯了什么。

第二天,我花了三個小時來改進解決方案,然后我發了這封郵件:

嗨,面試X和面試官y。

我想感謝你們昨天同意和我交流。我已經思考了很多關于這個問題的解決方案,我決定今天就改進它。我提供了我們昨天工作的增強版本的代碼。這是我所做的:

我擴展了排序功能,以便能夠在第二次按下時逆轉結果。

我將分類功能擴展到所有的titles。

我添加了一些圖標來對titles進行排序。

我重構了分頁函數,學習了單元測試的基礎知識,并使用Jest來測試它的功能。

我增加了對分頁的查詢字符串支持,這樣重載和鏈接就會在訪問不同的頁面時顯示正確的數據。

我添加了媒體查詢樣式,使組件更具移動友好度。

在API調用發生時,我添加了一個加載器。

我添加了錯誤處理,讓用戶有機會重新啟動API調用。

我在移動設備上改變了排序功能,并使用了一個選擇框。

……

這可能有點矯枉過正,但我很受啟發,我想要改進解決方案。

最好的問候,

Fredrik Strand Oseberg

這還不夠。但至少我盡了最大的努力。過了一段時間,我收到了這封郵件:

嗨!

我們想感謝你的面試,但我們必須得出這樣的結論:我們不能給你這個職位的offer,因為你在技術方面沒有達到我們的期望。

我們喜歡你的背景,相信你能很好地融入我們的社區,所以我們在你的技術面試中給了你一份詳細的反饋,希望你能在獲得更多編程經驗后再申請我們的職位。

我在哪里出錯了?

幸運的是,我得到了一份詳細的反饋報告。讓我們來看看吧,我將和你們討論其中的內容。

反饋1:“花費太多的時間來了解如何組合數組。首先在互聯網上搜索,而不是檢查JavaScript文檔(例如:“js array doc”將提供w3schools或MDN,其中列出了函數),并錯誤地使用了這些示例(array.concat返回一個新數組)。沒有人會記住API中的所有內容,所以能夠很好地使用JS或庫的文檔是很重要的?!?/p>

要點:面試官希望你首先接觸到MDN(或其他相關文檔)。他們希望看到你能夠找到并閱讀文檔,并根據發現的信息來實施它。

反饋2:“在排序分配中,候選人首先提出了一個奇怪的手動算法。幸運的是,他選擇在JavaScript中使用內置的排序功能,但是不確定它是如何工作的,并且必須反復檢查文檔?!?/p>

要點:在交流中要絕對清楚。在這種情況下,我詢問了面試官關于我是否應該使用內置的JavaScript排序功能,以搞清楚手頭上任務的界限和限制。不幸的是,我認為這被誤解為我建議自己使用的排序算法。

這最終產生了和我想要傳達的相反的效果。確保你清楚地表達出你的問題想要澄清的東西。因為它們可能對你來說很有意義,但你的面試官可能會對此有所察覺。

反饋3:“當代碼運行時,文本被排序為“區分大小寫”。不幸的是,候選人花了很長時間才明白這個問題,但一旦被發現,就立即改了過來?!?/p>

要點:速度是最重要的。在編寫程序時,總是會出現bug,但是要盡可能快地解決它們。找到問題的根源,如果你不知道,就迅速地去查文檔。

反饋4:“花了一些時間來理解為什么要在重構的時候將formatData移出分頁?!?/p>

再說一遍,速度是最重要的。

反饋5:“許多foreach循環,其中可以用數組.map或array.reduce來解決。了解更多函數式編程將是有益的?!?/p>

要點:學習數組.map、array.filter和array.reduce,并熟練地掌握它們。我一直在鉆研函數式編程,這是一項艱巨的任務。但是你現在不需要完全精通這些知識,只要確保你能掌握了基礎知識就行。

反饋6:“我希望候選人對單元測試有更多的了解?!?/p>

要點:這似乎是顯而易見的,但重要的問題要多說幾遍:測試很重要。測試很重要。測試很重要。學習它。使用它。

這份文件的其余部分都是贊揚。我不會說太多細節,因為它沒那么重要。要點是:

  • 他很好地使用了編輯器
  • 他在Chrome中使用調試器(了解高級調試工具很重要)
  • 在繼續工作之前,他會檢查這些東西是否正常工作(使用console.log)
  • 他試圖將代碼分成更小的邏輯部分
  • 他使用變量名而不是注釋,這使得代碼可讀性更好
  • 他很了解React
  • 之前的項目令人印象深刻
  • 擁有編程之外(設計/視覺)其他積極的品質

在準備過程中,我還能做些什么?

當你被拒絕的時候,你將不可避免地花費一些時間來思考你可以做些什么不同的事情。

更徹底地檢查筆試代碼

我花了太多時間研究我的JavaScript知識。我應該更了解我自己的代碼。盡管我寫了這篇文章,但在寫作和面試之間的幾周時間里,你需要回顧一下。我希望我在這上面花的時間比在模糊的JavaScript問題上更多。

做更多實操性的JavaScript任務

在面試前我做了很多理論工作。我現在希望我能夠花更多的時間做更多的實際工作,或者至少是混合了一些實際的工作,或者構建一些常見的前端組件,比如排序列表、下拉菜單、分頁等等。

面試結束

在第一次技術面試結束后我感覺如何?老實說,這是一次很棒的經歷。我非常感謝面試官,他們給了我如此詳細的反饋,讓我能夠在下一次面試前糾正我的錯誤。盡管我沒有得到這份工作,但我離成為第一個前端開發者的工作又近了一步。

我也了解到面試是一件反復無常的事情。也許如果我在自己的項目中構建了一個排序機制,或者如果我得到的是一個與我之前完成的任務更接近的任務,面試結果將會有所不同。

我最大的優勢是在過去的一年中我花了很多時間學習JavaScript,現在我能夠很快地學習和采納新的想法。不幸的是,我這次沒有能力證明這一點。

通往成功之路

現在,我很容易對自己說:“我還不夠好。我需要花3-4個月的時間來學習,然后再試一次?!?/p>

但我沒有。

我決定在兩周內盡可能多的申請工作。我向挪威最大的IT公司投遞了簡歷。

兩周后,我完成了幾家公司的初步面試,然后我又接受了技術面試。

第二輪準備

我在第一次技術面試中學到的一件事是,準備工作很關鍵。它可以幫助你把技術面試變成是一場考試,并采取必要的步驟來確保你通過考試。

但將考試比作面試是錯誤的,因為它沒有涵蓋候選人的全部知識范圍。那你能做什么呢?

擴大你的知識范圍。

我使用了先進的記憶策略,在8個小時內記住了超過100個面試問題的答案。這些問題可以在這個數據庫中找到。

此外,我還在在Code WarsHackerrank的實例上花了很多時間。并花了很多時間來構建一些事物。

第二次技術面試

我在上次失敗的面試中吸取了很多教訓,我做了很多的準備。

這次面試的重點是討論前端概念。這是一次全面的面試,我覺得面試官想搞清楚我的知識范圍,并弄清楚我的強項和弱項。

這次面試持續了大約兩個小時。以下是我們所討論的所有主題的列表:

  • JS,CSS和HTML概述
  • 文檔結構
  • 項目結構
  • Git
  • 性能
  • 安全
  • 可訪問性
  • 搜索引擎優化
  • 響應式網頁設計

編程挑戰是基于vanilla Javascript的。我被要求用普通的Javascript將一個簡單的類添加到一個div中?,F在,如果你已經花時間用JS來使用主要的框架,你可能不熟悉classList API。幸運的是,我大部分時間都花在了所有的freeCodeCamp項目上。這就是它的樣子:

const btn = document.querySelector(‘.btn’);
const menu = document.querySelector(‘.menu’);function addClassNameToDiv() {
if (!menu.classList.contains(‘new-class’)) {
menu.classList.add(‘new-class’);
} else {
menu.classList.remove(‘new-class’);
}}
btn.addEventListener(‘click’, addClassNameToDiv)

或者,您可以使用classList.toggle(’new class’)將其轉換為一行程序。如果你點擊下拉菜單,我還被要求將它擴展至關閉菜單:

window.addEventListener(‘click’, () => menu.classList.remove(‘new-class’));

從編程挑戰中獲得的信息是:

  • 越短越好,只要它總是可讀的;
  • 在性能方面,最好將查詢選擇器置于事件監聽器回調函數之外(只調用一次,而不是每次都觸發);
  • 性能方面,getElementById和getElementByClassName比querySelector更好。

第二天,我接到了經理的電話。我通過了面試,他們想給我一個機會。我本可以在這里停下來,不用參加其他的面試了。我可以說:“我已經拿到了一個offer,這已經足夠了?!?/p>

但我做了相反的事情。

我打電話給所有我正在面試的公司,并告訴他們我已經收到了一個offer,并問他們是否可以加快進程,因為我現在有時間限制。

面試,尤其是技術面試,都是很艱難的心理考驗。如果你一直在展示,面試官將期待你的表現能夠超越預期。這很難。那么我為什么要這么做呢?

原因有四個:

  1. 我想向自己證明,這不是運氣。
  2. 我想要尊重每一個給我面試機會的人,給他們一個公平的機會。
  3. 我想確保自己找到了適合自己的公司,讓我成為一名開發人員。
  4. 為了你們,這個社區對我的幫助很大,我想從技術面試中獲得盡可能多的信息,這樣你們就可以從我的錯誤中吸取教訓,并做出相應的準備。

我對我從freeCodeCamp獲得的幫助和支持感到慚愧,我想要回報。

第三次技術面試

在與其他公司取得聯系,并表明我獲得了一家頂級公司的offer后,很多公司都迫不及待地想讓我通過面試。在一周內,我完成了幾次技術面試。

以下是第三次技術面試中的一些問題:

  • 你是如何學習React的?你為什么要學習它?這有什么好處?
  • Redux是如何工作的?這個API由什么組成的?什么是不變性?不變性的好處是什么?
  • 你將如何重新設計我們的網頁?
  • 你如何處理更深層次的應用程序?例如后端?
  • 你自己做測試嗎?什么是單元測試?
  • 對你來說,什么是好的用戶體驗?
  • 如何測試用戶體驗?

這次面試中的編程挑戰是基于CSS的。

我收到了一張紙,上面有一些CSS規則,看起來是這樣的:

<div id=”menu” class=”dropdown-menu”></div> // HTML Element
// CSS Rules
#menu {
color: black;
}.dropdown-menu {
color: green;
}div {
color: blue;
}

我的任務是解釋我所看到的。我立即識別了了HTML Element并告訴面試官,element上的id和class可以在CSS中使用,以選擇HTML Element。在這里,我解釋說CSS是級聯的,這意味著通常最后一條規則將適用。然而,在這種情況下,選擇器有不同的權重。順序如下所示:id> class>element。

這意味著,在上面的示例中,黑色將被應用到HTML Element中。

第四次技術面試

這是我進行的最后一次技術面試。雖然它仍然很傷腦筋,但現在我已經習慣了。下面是我們討論的內容:

  • 建立一個基本的網站。確定其中的組件。
  • 你如何讓它響應?
  • 如何將文本垂直和水平居中?
  • 什么是CSS框模型?內容框和邊框之間的區別是什么?
  • React有什么好處?
  • array.forEach在for循環中的好處是什么?有沒有可能需要使用for循環的情況?

編程挑戰是建立一個不同程度難度的wordwrap函數。想象一下,你只能在屏幕上放20個字符,如果你超過它,你就得從一個新行開始。

我對這個問題的原始解決方案涉及拆分字符串,使用計數器和模數運算符來確定計數是否為20,然后在數組中插入一個換行符并加入字符串。

然后,任務難度增加了,只允許全部單詞排成一行。也就是說,如果一個單詞導致總數超過20,那么需要在單詞前面插入一個換行符。

我在面試中并沒有完全解決這個問題,但我的思路是正確的。在我不確定的時候,我使用了MDN,并且我取得了很好的進展。

這就足夠了。

我不能把它寫下來,如果你感興趣的話,這里有一個解決的版本:

function wordWrap(str) {
let totalCount = 0;
const arr = str.split(‘ ‘), formattedStr = [];

arr.forEach((word, index) => {
totalCount += word.length;
if (totalCount >= 20) {
formattedStr.push(‘\n’, word, ‘ ‘); ? ? totalCount = word.length;
} else {
formattedStr.push(word, ‘ ‘);
}
}); return formattedStr.join(”);
}

結論

如果看到了這里,恭喜你。這是一個漫長的過程。我盡可能提供更多的信息,希望它能幫助像你這樣的人。

這樣做的結果是,我陷入了一個我從未想過的境地。最后,我有5個offer可供選擇。一家大公司甚至給我提供了一個“blind”offer,不管競爭對手給我多少錢,它都能更高。我最終選擇了我第一次通過技術面試的公司,因為我相信這對我來說是最合適的。

技術面試可能是一場艱苦的精神折磨。你會受到挑戰,你會被帶出你的舒適區,這是一件好事。它能幫助你成長。它會讓你變得更好。

如果你準備好了,你就能有所收獲。

所以從我的經驗來看,不要回避技術面試。不要因為你失敗了就放棄。不要認為這是你作為開發者的終極衡量標準。它不是。它只是公司用來衡量你的生產力的最簡單的工具。

申請工作。準備好。參加技術面試。從錯誤中學習。不斷重復這一過程。

如果你這樣做,我保證你會成功。

 

原文鏈接:https://medium.freecodecamp.org/how-i-applied-lessons-learned-from-a-failed-technical-interview-to-get-5-job-offers-656fcf58034d

譯者:chiming,由36氪編譯組出品。編輯:郝鵬程

譯文地址:http://36kr.com/p/5120732.html

本文由 @郝鵬程 授權發布于人人都是產品經理,未經作者許可,禁止轉載。

題圖來自 Pixabay,基于 CC0 協議

更多精彩內容,請關注人人都是產品經理微信公眾號或下載App
評論
評論請登錄
  1. 很強,

    回復
  2. ??

    來自廣東 回復