HÀNH TRÌNH 18 THÁNG ĐI PHỎNG VẤN MẢNG LẬP TRÌNH GAME

Bối cảnh:

Trong khoảng 18 tháng qua, tôi đã trải qua một số lượng lớn các cuộc phỏng vấn và tôi nghĩ tôi sẽ chia sẻ một số điều tôi học được trong suốt chặng đường ấy. Sơ lược về kỹ năng của tôi trước khi bắt đầu:

  • Tôi có bằng cử nhân Khoa Học Máy Tính và đi làm lập trình chuyên nghiệp được khoảng 9 năm. Hầu hết kinh nghiệm của tôi là phát triển ứng dụng trong một ngành công nghiệp tương tự như ngành công nghiệp game.
  • Tôi là một lập trình viên mạnh C++ với một ít kinh nghiệm về các ngôn ngữ khác ngoài Python.
  • Trong vài năm qua, tôi đã làm vài dự án game theo sở thích trong thời gian rảnh, mặc dù không có gì ngoài bản prototype từng được phát hành.
  • Hầu hết các vị trí tôi ứng tuyển là phát triển tool ở mức độ mid-level, cùng với một số vị trí lập trình UI và gameplay.

Thống kê:

Đây là danh sách các công ty mà tôi đã tham gia phỏng vấn: Bethesda, Blind Squirrel Games, Blizzard, Bungie, Epic Games, Infinity Ward, King, Naughty Dog, Respawn, Riot, Santa Monica Studios, Survios, Turtle Rock Studios, Unity

Nhìn chung, tôi đã phỏng vấn 16 lần. Tôi đã nhận được 2 offers và tôi đã trượt 6 cuộc phỏng vấn qua điện thoại, 8 cuộc phỏng vấn trực tiếp và 0 bài kiểm tra lập trình. Nếu bạn đang tự hỏi tại sao những con số đó không khớp với các công ty, thì đó là vì tôi đã phỏng vấn ở một công ty nhiều lần. Trong 6 trên 7 cuộc phỏng vấn đầu tiên, tôi không vượt qua được cuộc phỏng vấn qua điện thoại và 9 cuộc phỏng vấn cuối cùng của tôi đều là trực tiếp. Đơn đăng ký của tôi: tỷ lệ phỏng vấn là 94% – tất cả các đơn tôi gửi đi đều dẫn đến phỏng vấn ngoại trừ DICE ở Thụy Điển. Nói một cách dễ hiểu, khi mới tốt nghiệp đại học, tôi đã nộp đơn vào khoảng 30 công ty game và chỉ có 1 người phỏng vấn tôi.

Cấu trúc của một cuộc phỏng vấn:

Gần như tất cả các cuộc phỏng vấn với các công ty game đều theo cùng một khuôn mẫu: phỏng vấn online, kiểm tra lập trình tại nhà, phỏng vấn tại văn phòng. Nhìn chung thì dường như có hai kiểu phỏng vấn online: một kiểu là người phỏng vấn hỏi nhanh về các câu hỏi lập trình cơ bản, kiểu còn lại là một cuộc nói chuyện bình thường hơn về kinh nghiệm làm việc trong quá khứ. Các câu hỏi kiểm tra tại nhà có xu hướng cùng trình độ với các câu hỏi trên HackerRank và sẽ mất từ ​​2-4 giờ để làm. Nếu tốn hơn 4 giờ tại bất kỳ công ty nào ngoài Bungie (người đặt hai câu hỏi dài 4 tiếng), đó là một dấu hiệu mạnh mẽ cho thấy bạn không đủ tiêu chuẩn cho vị trí này. Phỏng vấn tại văn phòng thì sẽ thay đổi nhiều tùy theo từng công ty, nhưng hầu hết bạn có thể gặp 4 nhóm 2 người, 2 nhóm sẽ hỏi bạn kỹ thuật, yêu cầu bạn viết code trên bảng trắng và giải thích các ví dụ cụ thể về những việc bạn đã làm trong quá khứ. 2 nhóm còn lại sẽ hỏi về cách bạn hòa hợp với những người khác, cách bạn tương tác với quản lý và artist, và các câu hỏi khác về văn hóa/đạo đức làm việc. Hầu như tất cả các cuộc phỏng vấn sẽ mặc định bạn có kiến thức chuyên môn về C++. Trong trường hợp phát triển tool dựa trên WPF hoặc làm game bằng Unity, bạn có thể nhận được những câu hỏi thay thế bằng C#; tuy nhiên, trong trường hợp công việc yêu cầu C#, hầu hết các công ty vẫn sẽ phỏng vấn bạn bằng C++ nếu bạn thích.

Những gì bạn cần biết:

Trong một công ty hầu hết các phần kỹ thuật và các bài kiểm tra lập trình đều giống nhau bất kể bạn đang ứng tuyển vào vị trí nào. Tôi không thể liệt kê mọi điều có thể xảy ra mà tôi buộc phải biết, nhưng đây là tổng quan về một số điều phổ biến và những vấn đề mà tôi vấp phải:

  • Độ phức tạp của thuật toán khi chương trình chạy (the big O runtime) của TẤT CẢ các cấu trúc dữ liệu, bao gồm map, unordered map/hashmap, set, array, list, vector và bất kỳ cấu trúc dữ liệu nào khác. Bạn cũng sẽ cần biết thời gian chạy của các thuật toán phổ biến như tìm kiếm nhị phân (binary searching) một mảng. Cái quan trọng nhất có lẽ là, bạn sẽ cần phải biết khi nào dùng cấu trúc dữ liệu nào – chỉ vì một cấu trúc dữ liệu về mặt lý thuyết nhanh hơn một cấu trúc dữ liệu khác không có nghĩa rằng nó là sự lựa chọn tốt hơn. Hãy hỏi dữ liệu nào đang được sử dụng để làm gì và cách mà nó được đưa đến cho bạn sử dụng ra sao, xem liệu nó có thể được sắp xếp hay không và nếu điều đó có ích, hãy kiểm tra xem bạn có thể cache kết quả bằng cách nào đó không, hãy xem xét trường hợp 1 lượt tra cứu so với 1000 lượt tra cứu. Ngoài ra, tôi chưa bao giờ nghe thấy thuật ngữ này trước đây, nhưng hãy biết thế nào là “cây cân bằng” (balanced tree) và ưu/nhược điểm so với cây không cân bằng. Hãy chuẩn bị để biết cách một hashmap hoạt động cụ thể ra sao. Biết cách hiện thực thuật toán tìm kiếm theo chiều sâu (depth-first search) và tìm kiếm theo chiều rộng (breadth-first search) (sử dụng ngăn xếp (stack)/hàng đợi (queue) thay vì gọi hàm đệ quy) và cách thực hiện tìm kiếm nhị phân (binary search).
  • Cụ thể, dot product và cross product đại diện cho điều gì và tất cả các cách khác nhau mà chúng có thể được sử dụng. Các câu hỏi phổ biến liên quan đến những thứ như ray/sphere intersection, phản xạ vector so với tường và xác định thời điểm một vật thể chuyển động ở gần vật thể khác nhất. Tôi được hỏi về độ lớn của cả dot product và cross product nghĩa là gì. Biết khi nào bạn cần chuẩn hóa (normalize) một vector và khi nào thì không. Chắc chắn phải biết cách tính pháp tuyến và cách tính khoảng cách giữa hai vector. Biết từng giá trị trong ma trận 4×4 đại diện cho điều gì và cách bạn chuyển đổi từ toạ độ thế giới (world space) qua toạ độ màn hình (screen space).
  • Debugging và optimization (gỡ lỗi và tối ưu) đều quan trọng. Bạn sẽ được giao cho các tình huống kỳ lạ và phải nêu ra được tất cả những điều khả thi có thể sai và cách bạn sửa chữa nó. Hãy suy nghĩ về những thứ như cách tái tạo vấn đề (reproduce issue), dù cho nó chỉ xảy ra trên một số máy tính nhất định, cách bạn có thể debug nếu bạn không thể reproduce nó trên máy tính của mình, những công cụ nào có sẵn trong trình gỡ lỗi (debugger) (break points tại dòng code, break points vùng nhớ, stack traces, core dumps, v.v.). Có ít nhất 5 câu trả lời cho “tại sao màn hình đen?” Khi tối ưu code, hãy đảm bảo rằng bạn yêu cầu càng nhiều thông tin liên quan về dữ liệu giả định (hypothetical data) càng tốt. Xem xét sự khác biệt giữa tối ưu hóa cho tốc độ so với cho vùng nhớ. Rất có thể bạn sẽ được hỏi về cách phân bổ vùng nhớ để tận dụng kích thước bộ nhớ cache của CPU (CPU cache size). Làm quen với các công cụ phân tích tĩnh và trong runtime như VTune. Có kinh nghiệm với các thư viện như TBB là một điểm cộng.
  • Những thứ khác mà tôi chợt nghĩ ra: struct packing, vấn đề của kế thừa kiểu kim cương (diamond inheritance), shared/weak/unique pointers, std::move, vtable và dynamic_cast hoạt động như thế nào, khi nào sử dụng mutex so với atomic và các loại mutex tồn tại, dịch chuyển bit, object pooling, placement new, reflection.

Nhìn nhận lại bản thân và vài suy nghĩ cuối cùng:

Tại sao lại là những công ty đó: Tôi đã cố gắng hết sức có thể chỉ để nộp đơn vào những công ty ổn định với sự cân bằng danh giá giữa công việc và cuộc sống. Điều này khiến việc tìm kiếm của tôi trở nên khó khăn hơn vì những công ty này thường là những công ty bạn chuyển sang làm việc sau 2-5 năm khi làm ở một công ty “tệ hơn”. Tôi thấy Naughty Dog và Infinity Ward là trường hợp đặc biệt cụ thể cho việc bị chèn ép, nhưng phần còn lại của các công ty có vẻ khá hợp lý. Ngay cả trong một công ty, các sub-team khác nhau có thể có những mức độ áp lực khác nhau, vì vậy cách duy nhất để biết chắc chắn là hỏi. Các tool developer thường hạn chế làm việc thêm giờ hơn so với các gameplay programmers.

Điều đáng lẽ tôi nên làm trước tiên: Tôi lẽ ra nên nộp đơn vào một vài công ty mà tôi không hứng thú trước khi nộp đơn vào những công ty mà tôi muốn làm việc. Tôi đã thất bại gần như tất cả các cuộc phỏng vấn đầu tiên mà không phải do tôi là một lập trình viên tồi, mà bởi vì những loại câu hỏi bạn nhận được trong các cuộc phỏng vấn không nhất thiết là những loại vấn đề bạn gặp phải hàng ngày với tư cách là một lập trình viên làm công ăn lương. Trên hết, những thách thức mà ngành công nghiệp game phải đối mặt có xu hướng rất khác biệt so với hầu hết các ngành/lĩnh vực lập trình khác, vì vậy trừ khi bạn đã là một game programmer, nếu không thì sẽ có rất nhiều lần bạn sẽ tự nhủ rằng “làm thế nào họ có thể mong đợi tôi biết điều đó? ai thậm chí còn sử dụng nó cơ chứ?”

Offer đầu tiên: Tôi đã từ chối offer đầu tiên của mình vì một số lý do bao gồm lương, phúc lợi, khối lượng công việc và loại công việc liên quan. Bạn không cần phải nhận một công việc mà bạn sẽ không hài lòng. Điều đó nói lên rằng, một khi bạn đã làm trong ngành thì việc chuyển sang các công ty khác nhau sẽ dễ dàng hơn. Tôi đã mạo hiểm khi nghĩ rằng mình sẽ có thể tìm một công việc khác, thay vì nhận công việc sẽ mang lại kinh nghiệm thực sự vững chắc cho bản thân. Thật khó để nói rằng liệu tôi có quyết định đúng hay không, nhưng may mắn là cuối cùng mọi chuyện đã suôn sẻ.

Tại sao tôi trượt: Tôi đã làm hỏng rất nhiều cuộc phỏng vấn online do không quen với loại câu hỏi được đặt ra. Tại sao tôi trượt nhiều cuộc phỏng vấn tại văn phòng? Tôi không giỏi viết code trên bảng trắng và nghĩ ra mọi thứ ngay tại chỗ. Một lần tôi được yêu cầu hiện thực một cái gì đó bằng C# trên bảng trắng và tôi không cảm thấy thoải mái khi sử dụng C# mà không có code completion, vì vậy tôi đã viết câu trả lời bằng mã giả. Tôi đã rất lo lắng về việc không sử dụng C# đến mức tôi không thể tập trung và hoàn toàn không nắm được câu trả lời. Phong cách lập trình của tôi là code một chút, chạy và kiểm tra kết quả, sau đó sửa/viết thêm một chút. Làm trên bảng trắng thì điều ấy không thể làm được và tôi đã cố gắng viết toàn bộ giải pháp cùng một lúc để rồi không hình dung được bất cứ quá trình nào trong suốt buổi phỏng vấn. Tôi có xu hướng tự đưa cho bản thân lợi ích của sự hoài nghi và tự nhủ rằng mình không phải là một lập trình viên tồi, bởi tôi không gặp bất kỳ vấn đề nào với bài kiểm tra lập trình tại nhà, thứ mà tôi có thể thực hiện trong một môi trường thoải mái và làm việc theo cách mà tôi thường làm. Lưu ý thêm là các bài kiểm tra lập trình của bạn hoàn toàn không liên quan khi bạn làm tại văn phòng. Ở một trường hợp, công ty sẽ thuê tôi cho đến khi họ phỏng vấn một người có nhiều kinh nghiệm hơn với một engine thể mà họ đang sử dụng. Trong một trường hợp khác, tôi được thông báo rằng tôi đã làm tốt nhưng họ muốn một người có nhiều kinh nghiệm hơn với Maya (mặc dù tôi đã nói với họ nhiều lần trước khi phỏng vấn trên văn phòng rằng tôi không có kinh nghiệm về Maya). Tôi sẽ nói rằng tôi biết lý do tại sao tôi trượt trong tất cả các cuộc phỏng vấn ngoại trừ hai cuộc phỏng vấn cuối cùng, những đợt phỏng vấn ấy tôi đã làm rất tốt nhưng các công ty từ chối cho tôi biết lý do tại sao họ lại loại tôi.

Một thời điểm khi…: Tại một thời điểm, tôi đã viết một danh sách tất cả những điều tôi có thể nghĩ đến mà tôi đã làm cho những câu hỏi dạng như “kể cho tôi nghe về một thời điểm khi…”. Hành động này giúp tôi rất nhiều. Hãy ít nhất hai lần thử nghĩ đến các tình huống sau: điều gì đó bạn tự hào, điều gì đó thách thức mà bạn đã làm, khi bạn gặp một lỗi khó giải quyết, khi bạn giúp một thành viên trong team, khi bạn không đồng ý với ai đó, khi bạn có một ý tưởng hay, khi bạn tương tác với người dùng.

Trở thành một ứng viên tồi: Phỏng vấn là một kỹ năng giống như lập trình, và việc bán được bản thân là điều khó đối với một số người và nếu bạn không thực hành. Một trong những lỗi của tôi là tôi rất trung thực và có xu hướng chia sẻ những thông tin có thể không tạo được ấn tượng tốt cho bản thân. Hãy suy nghĩ kỹ về phản ứng của bạn trước khi lên tiếng. Làm nổi bật những kết quả tích cực hơn những kết quả tiêu cực, ngay cả khi vai trò của bạn đúng với bối cảnh. Chả nghĩa lý gì khi bạn là một thành viên tuyệt vời của team nhưng bạn lại không thể thuyết phục được những người phỏng vấn rằng bạn là người như thế.

Cùng một công ty, khác công việc: Đối với việc nộp đơn vào cùng một công ty lần thứ hai, tôi thường được biết rằng 6-12 tháng là khung thời gian chờ đợi tốt. Tại các công ty lớn hơn, bạn có thể nộp đơn vào hai team game riêng biệt và nhà tuyển dụng thậm chí có thể không biết về cuộc phỏng vấn khác của bạn. Tương tự, bản thân các cuộc phỏng vấn có thể rất khác nhau ngay cả trong cùng một công ty. Trong một cuộc phỏng vấn của tôi, tôi đã nói chuyện với một người (không phải lập trình), người này đã phỏng vấn ba lần trong năm năm vào cùng một vị trí cho đến khi người đó được nhận.

Sự kết nối: Tôi không có kết nối với bất kỳ công ty nào khi nộp đơn. Tôi thấy nhiều người nói rằng chúng là một trong những yếu tố quan trọng nhất mà bạn có thể có. Tôi thực sự không biết việc này hiệu quả như thế nào. Tôi có thể nói rằng thứ này hoàn toàn không cần thiết nếu bạn có một cái resume mạnh và kinh nghiệm phù hợp. Tôi cũng không có “portfolio” và tôi chưa bao giờ nghe nói về bất kỳ lập trình viên nào được yêu cầu phải có cái này. Tôi không nghĩ rằng cái này quan trọng ngoài việc liệt kê các dự án của bạn trong resume. Cá nhân tôi cảm thấy việc open source chỉ có thể làm tổn thương bạn mà thôi. Tôi không thể tưởng tượng được một bối cảnh khi mà một quản lý tuyển dụng nhìn vào resume của bạn, chuẩn bị phỏng vấn bạn, nhưng sau đó duyệt qua github của bạn và ngạc nhiên đến mức họ phải gọi cho bạn. Mặt khác, tôi hoàn toàn có thể hình dung ra một bối cảnh khi mà họ đọc code của bạn từ 5 năm trước và đoạn code ấy tệ vl rồi họ loại bạn luôn.

Cách bạn nói bạn giỏi ra sao: Khi ai đó yêu cầu bạn đánh giá trình độ C++ của bản thân trên thang điểm từ 1 đến 10, trong mọi trường hợp, không nên nói 10. Là một người đã code C++ chuyên nghiệp hàng ngày trong hơn 5 năm, tôi sẽ đánh giá bản thân mình đạt 6.5 hoặc 7. Để ghi thêm điểm với người phỏng vấn, hãy nói đùa về cách bạn đưa ra câu trả lời thực tế cho họ thay vì câu trả lời “Tôi vừa tốt nghiệp đại học nên tôi là điểm 10”. Hãy chuẩn bị để giải thích lý do tại sao bạn là 7 bằng cách chọn những thứ thường không được biết đến và khó (Tôi không hiểu đầy đủ về move semantics, tôi không quá quen thuộc với các tính năng của C++ 14 và 17, tôi chưa hiện thực custom allocators bao giờ, v.v…).

Bên tuyển dụng hay phản hồi chậm: Kiểu chậm lắm luôn ấy. Hầu hết các yêu cầu phỏng vấn của tôi là trong vòng 1-2 tuần sau khi gửi đơn ứng tuyển, mặc dù một số ít mất 3 tuần và một số mất hơn một tháng. Tuy nhiên, sau mỗi giai đoạn của cuộc phỏng vấn, họ thường thong thả trong một tuần và không trả lời bất cứ điều gì bất kể bạn đậu hay rớt. Tôi không có bất kỳ lời khuyên nào cho chuyện này đâu, nhưng chắc chắn là tôi thấy khó chịu. Tôi khuyên bạn nên theo dõi email đúng 1 tuần sau lần liên hệ cuối cùng của bạn, mặc dù bạn có thể bỏ qua sau 3-4 ngày tùy thuộc vào cảm nhận của bản thân về tình hình lúc ấy. Khi tôi thấy thực sự tự tin về những gì mình đã làm, tôi sẽ thúc các nhà tuyển dụng gắt hơn một chút để đẩy nhanh tiến độ. Tính đến thời điểm hiện tại thì Riot đang có những nhà tuyển dụng nhạy bén nhất, và tôi đánh giá cao điều đó về họ.

Leave a Reply

Your email address will not be published. Required fields are marked *