Tuyển được lập trình viên giỏi không hề dễ. CV có thể rất đẹp, bài test kỹ thuật có thể trông ổn, nhưng buổi phỏng vấn vẫn có thể chưa cho thấy ứng viên có thật sự phù hợp với đội ngũ hay không.
Tại HDWEBSOFT, chúng tôi xem phỏng vấn lập trình viên là một cuộc trao đổi, không phải một kỳ thi. Chúng tôi vẫn kiểm tra kỹ năng kỹ thuật một cách nghiêm túc, nhưng cũng quan sát rất kỹ cách ứng viên giải thích, đặt câu hỏi, tiếp nhận gợi ý và biến một vấn đề còn mơ hồ thành giải pháp thực tế.
Bài viết này chia sẻ cách chúng tôi phỏng vấn kỹ sư phần mềm. Nội dung phù hợp nhất với người phỏng vấn có nền tảng kỹ thuật, nhưng HR, team lead hoặc founder cũng có thể dùng để hiểu một buổi phỏng vấn lập trình viên tốt nên đánh giá những gì.
Bạn cũng có thể tham khảo thêm Chuck Groom’s Software Engineer’s Guide to Interviewing Software Engineers và Developer Job Interview Questions. Hai bài viết này có nhiều góc nhìn hữu ích để phỏng vấn hiệu quả hơn và tôn trọng ứng viên hơn.
Đối tượng phù hợp
Bài viết này hữu ích nhất cho người phỏng vấn kỹ thuật, đặc biệt là những người có thể trao đổi trực tiếp với ứng viên qua các tình huống thực tế. Một số ví dụ có thể hơi khó với người không chuyên kỹ thuật, nhưng ý chính rất đơn giản: một buổi phỏng vấn tốt phải cho thấy lập trình viên tư duy, giao tiếp và phát triển như thế nào.
Xác định tiêu chí trước khi phỏng vấn
Trước khi đặt câu hỏi, hãy xác định rõ bạn muốn đánh giá điều gì. Mỗi công ty có tiêu chí tuyển dụng riêng, nhưng theo kinh nghiệm của chúng tôi, ba tiêu chí quan trọng nhất là:
- Giao tiếp: Ứng viên có giải thích rõ ràng, đặt câu hỏi hữu ích và phối hợp tốt với người khác không?
- Năng lực hiện tại: Hiện tại ứng viên có thể làm được gì?
- Tiềm năng: Ứng viên có thể trở thành ai trong tháng tới, năm tới, hoặc trong 5 đến 10 năm tới?
Với HDWEBSOFT, giao tiếp là tiêu chí đầu tiên. Chúng tôi là công ty phát triển phần mềm offshore, làm việc với khách hàng ở nhiều quốc gia khác nhau, nên ngay cả một lập trình viên giỏi cũng sẽ gặp khó khăn nếu không thể giao tiếp rõ ràng.
Bắt đầu bằng một cách tiếp cận cởi mở
Trước khi vào phần kỹ thuật, chúng tôi thường nói rõ tinh thần của buổi phỏng vấn. Đại ý như sau:
Đừng căng thẳng. Không ai biết mọi thứ. Mục đích của buổi phỏng vấn không phải là chứng minh bạn biết tất cả câu trả lời. Chúng tôi muốn xem liệu hai bên có thể cùng trao đổi, cùng suy nghĩ qua vấn đề và tìm ra giải pháp tốt hay không.
Thông điệp đơn giản này giúp ứng viên bình tĩnh hơn. Nó cũng đặt đúng kỳ vọng: chúng tôi không chỉ kiểm tra trí nhớ, mà quan sát cách ứng viên làm việc.
Kiểm tra giao tiếp trong toàn bộ buổi phỏng vấn
Cách phỏng vấn lập trình viên hiệu quả là đánh giá kỹ năng giao tiếp xuyên suốt buổi phỏng vấn, thay vì tách nó thành một phần riêng.
Giao tiếp thể hiện khi ứng viên mô tả dự án cũ, làm rõ yêu cầu, giải thích một quyết định kỹ thuật hoặc thừa nhận điều mình chưa biết. Những khoảnh khắc này đôi khi giá trị hơn một câu trả lời đúng theo sách vở.
Ứng viên có giải thích rõ những gì mình từng làm không?
Một câu hỏi hữu ích là yêu cầu ứng viên mô tả một dự án họ từng tham gia. Ví dụ:
- Dự án bạn thích nhất là gì?
- Ai sử dụng sản phẩm đó, và sản phẩm mang lại giá trị gì cho họ?
- Những điểm kỹ thuật quan trọng nhất trong dự án là gì?
- Đóng góp thực tế của bạn là gì?
Câu trả lời tốt không phải là một bài nói dài với mọi chi tiết kỹ thuật. Câu trả lời tốt nên ngắn gọn, rõ ý và tập trung vào điểm quan trọng.
Cách hỏi này giúp đánh giá hai điều:
- Ứng viên có hiểu dự án như một tổng thể không?
- Ứng viên có chọn được điểm chính, thay vì bị cuốn vào chi tiết vụn vặt không?
Nếu một lập trình viên không có cảm nhận rõ ràng về thứ mình từng xây dựng, rất khó tin rằng họ thật sự hiểu công việc đó. Ngược lại, người có thể tóm tắt tốt một dự án cũ thường có tiềm năng hiểu nhanh các dự án tiếp theo.
Ứng viên có thể biến phần giải thích thành đặc tả kỹ thuật không?
Một phương pháp khác là đưa cho ứng viên một yêu cầu nhỏ, rồi cùng họ đi tới giải pháp. Độ khó nên phù hợp với cấp độ và kinh nghiệm của ứng viên.
Mục tiêu không phải lúc nào cũng là xem họ có trả lời ngay được hay không. Đôi khi tín hiệu tốt hơn là họ có biết đặt câu hỏi, hiểu gợi ý và điều chỉnh cách suy nghĩ không.
Dưới đây là một vài ví dụ.
Ví dụ 1: Câu hỏi đơn giản cho fresher
Câu hỏi: Bây giờ là 1 giờ sáng ở New York. Vậy ở Việt Nam là mấy giờ?
Nếu ứng viên không trả lời ngay được, tôi cho phép họ đặt câu hỏi. Một câu hỏi tốt có thể là: “Múi giờ của New York là gì?”
Nếu ứng viên không biết công thức, tôi có thể giải thích Việt Nam là UTC+7, còn New York có múi giờ riêng tùy thời điểm trong năm. Sau đó, tôi quan sát xem họ có dùng thông tin mới đó để tính ra câu trả lời không.
Trọng tâm không phải là địa lý. Trọng tâm là ứng viên có biết hỏi đúng và sử dụng thông tin mới không.
Ví dụ 2: Kết hợp với một thuật toán phổ biến
Câu hỏi: Tôi có một mảng đã sắp xếp gồm 1.000 phần tử. Tôi muốn kiểm tra một giá trị có tồn tại trong mảng đó không. Trong trường hợp xấu nhất của thuật toán binary search, cần bao nhiêu lần kiểm tra?
Nếu ứng viên quên binary search, tôi sẽ giải thích cách thuật toán hoạt động. Nếu họ theo được phần giải thích và tính ra đáp án, đó vẫn là tín hiệu tốt.
Câu hỏi này không chỉ kiểm tra trí nhớ. Nó kiểm tra khả năng hiểu nhanh một khái niệm và áp dụng khái niệm đó.
Ví dụ 3: Cho PHP developer, backend developer hoặc full-stack developer
Câu hỏi: Tạm quên PHP Session đi. Nếu bạn phải tự viết một thư viện có chức năng tương tự, bạn sẽ xây dựng như thế nào?
Câu hỏi này có thể khó ngay cả với PHP developer đã có vài năm kinh nghiệm. Nếu ứng viên không chắc, tôi giải thích PHP Session hoạt động ra sao rồi quan sát cách họ suy luận tiếp.
Nhiều lập trình viên chủ yếu làm việc với framework cấp cao như CakePHP, Laravel, Symfony hoặc các công cụ tương tự. Điều đó hoàn toàn bình thường, nhưng đôi khi khiến họ đánh giá thấp các nền tảng quan trọng. Câu hỏi này giúp xem ứng viên có hiểu điều gì đang diễn ra bên dưới framework hay không.
Ví dụ 4: Cho full-stack developer
Câu hỏi: Bạn sẽ xây dựng giỏ hàng và luồng checkout thông thường cho một website thương mại điện tử như thế nào?
Nếu ứng viên xử lý tốt luồng cơ bản, tôi mở rộng câu hỏi: Giả sử một sản phẩm có số lượng tồn kho giới hạn. Làm sao để đảm bảo số lượng mua không bao giờ vượt quá giới hạn đó?
Đây là chủ đề tốt cho phỏng vấn backend và full-stack vì nó có thể mở rộng tự nhiên. Một lập trình viên junior có thể nói về hành vi cơ bản của giỏ hàng. Ứng viên mạnh hơn có thể bàn đến validation, transaction, locking, race condition, trạng thái thanh toán và rollback đơn hàng.
Cách họ khai thác vấn đề cho thấy rất nhiều về năng lực thực tế.
Ví dụ 5: Một vấn đề kỹ thuật ít gặp nhưng thú vị
Câu hỏi: Tôi có một trang admin hiển thị danh sách sản phẩm. Khi một người mở trang chỉnh sửa sản phẩm, làm sao để đảm bảo không ai khác có thể chỉnh sửa cùng sản phẩm đó cùng lúc?
Vấn đề này chủ yếu liên quan đến resource locking. Một số ứng viên có thể trả lời ngay. Nếu không, tôi dẫn họ về một tình huống quen thuộc hơn: chức năng đăng ký người dùng, nơi hệ thống phải tránh tạo hai tài khoản có cùng email tại cùng một thời điểm.
Sau đó tôi hỏi: “Cách làm tương tự có áp dụng được ở đây không?”
Câu hỏi này hữu ích vì nó cho thấy ứng viên có thể chuyển kiến thức từ một bài toán sang bài toán khác hay không.
Những câu hỏi này cho thấy điều gì?
Từ các ví dụ trên, buổi phỏng vấn thường dẫn đến hai tình huống:
- Ứng viên trả lời trôi chảy vì đã hiểu rõ chủ đề đó.
- Ứng viên chưa biết ngay câu trả lời, nên hai bên cùng phân tích từng bước.
Trường hợp thứ hai thường thú vị hơn. Trong quá trình đó, chúng ta thấy được ứng viên có đặt câu hỏi hữu ích, hiểu phần làm rõ, suy luận logic và tiến dần tới giải pháp hay không.
Cách này giúp đánh giá nhiều yếu tố cùng lúc:
- Giao tiếp: Ứng viên có hỏi và giải thích rõ không?
- Năng lực hiện tại: Ứng viên đã từng xử lý loại vấn đề nào?
- Tiềm năng: Ứng viên có thể trở thành người giải quyết vấn đề, hay chỉ phù hợp với công việc lặp lại?
Đó là lý do thảo luận theo tình huống là một trong những cách tốt nhất để phỏng vấn lập trình viên. Nó gom nhiều tín hiệu quan trọng vào cùng một cuộc trao đổi.
Kiểm tra năng lực hiện tại của ứng viên
Tôi sẽ không nói quá nhiều về phần này vì trên internet đã có rất nhiều danh sách câu hỏi kỹ thuật. Java có bộ câu hỏi riêng. .NET, Python, iOS, Android, React Native, Node.js, React, Vue, JavaScript, CSS và nhiều mảng khác cũng vậy.
Những câu hỏi đó vẫn hữu ích. Bạn cần biết ứng viên có thể làm được việc hôm nay hay không. Nhưng danh sách câu hỏi framework không nên là toàn bộ buổi phỏng vấn.
Hãy dùng chúng để kiểm tra năng lực kỹ thuật hiện tại, rồi dùng các tình huống thực tế để hiểu cách ứng viên suy nghĩ.
Kiểm tra tiềm năng của ứng viên
Năng lực hiện tại quan trọng, nhưng tiềm năng còn quan trọng hơn. Nếu năng lực hiện tại có trọng số là 1, tiềm năng có thể có trọng số là 10.
Vì sao? Vì phát triển phần mềm thay đổi rất nhanh. Một lập trình viên chỉ biết công cụ hôm nay có thể ngừng phát triển. Một người có nền tảng tốt, sự tò mò và khả năng giải quyết vấn đề có thể tiếp tục tiến bộ trong nhiều năm.
Nền tảng giáo dục tốt có thể giúp ích, nhưng không phải tất cả
Một lập trình viên giỏi không nhất thiết phải tốt nghiệp từ một trường đại học nổi tiếng. Rất nhiều kỹ sư xuất sắc là người tự học hoặc đến từ những trường bình thường.
Tuy vậy, nền tảng giáo dục tốt có thể tạo ra cơ sở vững hơn. Lợi thế đó có thể chưa rõ ngay hôm nay, nhưng về lâu dài, một nền tảng chắc giúp lập trình viên học nhanh hơn và đi xa hơn.
Kiến thức nền càng vững, tiềm năng càng cao
Giáo dục chỉ là một tín hiệu. Kiến thức nền mới quan trọng hơn. Chúng tôi đánh giá cao những ứng viên hiểu sâu các nền tảng kỹ thuật.
Cấu trúc dữ liệu và giải thuật
Về kiến thức nền, cấu trúc dữ liệu và giải thuật vẫn rất quan trọng.
Nhiều lập trình viên ứng dụng chỉ tập trung vào phát triển ở tầng framework: Java Spring, .NET Framework, Node.js, Python, PHP, React, Vue, v.v. Điều này dễ hiểu vì đó là các công cụ họ dùng hằng ngày.
Tuy nhiên, lập trình viên hiểu cấu trúc dữ liệu và giải thuật thường có nền tảng tốt hơn cho giải quyết vấn đề, tư duy hiệu năng và thiết kế hệ thống.
Kỹ thuật lập trình
Các kỹ thuật lập trình cơ bản cũng rất quan trọng. Tại HDWEBSOFT, chúng tôi kỳ vọng lập trình viên hiểu clean code và nguyên lý SOLID, chứ không chỉ lặp lại định nghĩa.
OOP, design patterns và UML
Hầu hết lập trình viên đều nói mình dùng lập trình hướng đối tượng. Nhưng để tìm được người có tư duy OOP thật sự vững thì vẫn khó.
Nhiều người có thể giải thích abstraction, inheritance và polymorphism. Ít người hơn có thể chỉ vào một dòng code của chính mình và giải thích dòng đó thể hiện nguyên lý nào.
Tôi cũng ấn tượng với những lập trình viên nắm được nhiều design pattern và biết khi nào không nên dùng chúng. Design pattern không chỉ là công thức giải quyết vấn đề. Chúng là một ngôn ngữ chung để hiểu cấu trúc, ý đồ thiết kế và code của người khác.
Kết luận: cách phỏng vấn lập trình viên hiệu quả
Vậy cách tốt nhất để phỏng vấn lập trình viên là gì?
Không có một câu hỏi thần kỳ nào. Một buổi phỏng vấn tốt cần kết hợp nhiều loại câu hỏi. Dùng câu hỏi kỹ thuật để kiểm tra năng lực hiện tại. Dùng câu hỏi nền tảng để kiểm tra kiến thức gốc. Dùng tình huống thực tế để đánh giá giao tiếp, khả năng giải quyết vấn đề, sự thích nghi và tiềm năng.
Tại HDWEBSOFT, cách tiếp cận này giúp chúng tôi tuyển được những kỹ sư có thể đóng góp ngay và tiếp tục phát triển cùng các thử thách trong tương lai. Nó cũng khiến buổi phỏng vấn nhân văn hơn: bớt giống một bài kiểm tra, và giống một cuộc làm việc thật hơn.