Viết mã chỉ là một phần của quá trình phỏng vấn.
Trên thực tế giải quyết vấn đề logic chỉ là một phần của nhiệm vụ viết mã.
Người phỏng vấn muốn chắc chắn rằng:
Bạn có thể viết mã. Nhiều ứng viên có mười năm kinh nghiệm chuyên môn về ngôn ngữ không thể viết bất kỳ mã nào cả, và bài kiểm tra này nhằm từ chối những ứng cử viên đó.
Bạn nghĩ về một vấn đề trước khi bạn viết mã. Nhiều người sẽ nhảy vào bàn phím của họ, viết hàng chục dòng mã, sau đó thấy rằng họ đã hiểu sai vấn đề ban đầu, vì họ không mất thời gian nghĩ về nó.
Bạn có thể tự thích nghi khi viết mã. Giả sử bạn đã tìm thấy một giải pháp, nhưng khi bạn bắt đầu thực hiện nó, có vẻ như ý tưởng đầu tiên của bạn không phải là ý tưởng tốt nhất; bạn có thể nhanh chóng chuyển sang một cái tốt hơn, cuối cùng tái cấu trúc mã bạn đã viết không?
Điều này cũng có nghĩa là các cuộc phỏng vấn như vậy nên có nhiều tương tác . Thay vì gõ bằng một tay, hãy mua bộ rảnh tay hoặc gọi qua Skype và sử dụng tai nghe. Gõ như bạn đang gõ tại nơi làm việc, trong khi bình luận và giải thích những gì bạn làm: nó sẽ đột nhiên trở nên ít khó xử hơn nhiều.
Bạn đã thực hiện lập trình cặp? Nếu có, tình huống phỏng vấn rất giống nhau, ngoại trừ việc người phỏng vấn có thể không đưa ra ý kiến của bạn và bạn không yêu cầu anh ấy đổi bàn phím với bạn khi bạn kết thúc.
Dưới đây là một vài ví dụ về một vấn đề toán học thuần túy và cách nó thể hiện các kỹ năng phi toán học của một nhà phát triển.
Ví dụ 1: bài tập mã hóa đơn giản
Bạn cần triển khai máy tính số Fibonacci trong JavaScript. Bạn sẽ có thể thay đổi chỉ số. Chuỗi Fibonacci tuân theo các quy tắc sau:
- Hai số đầu tiên của dãy là 0 và 1,
- Mỗi số tiếp theo là tổng của hai số trước.
Ví dụ: F 0 = 0, F 1 = 1, F 2 = 1, F 3 = 2, F 10 = 55.
Bạn có ba phút.
Ở đây, người phỏng vấn muốn bạn suy nghĩ nhanh nhất có thể, tìm giải pháp và nhanh chóng thực hiện nó. Bài tập như vậy không liên quan đến những gì các nhà phát triển thực tế làm và gần hơn với những gì bạn có thể tìm thấy khi làm bằng CS, nhưng những người phỏng vấn thích những thứ này, vì vậy hãy làm điều đó. Ngoài ra, hạn chế về thời gian khiến bạn không thể thực hiện bất kỳ thử nghiệm tự động nào, vì vậy người phỏng vấn có thể không mong đợi điều này từ bạn.
Phần mô tả thuật toán làm tôi suy nghĩ về đệ quy. Quy tắc thứ hai dẫn đến chức năng đệ quy sau.
var fibonacci = function (n) {
return fibonacci(n - 2) + fibonacci(n - 1);
};
console.log(fibonacci(10));
Để kết thúc đệ quy, chúng tôi sẽ thêm các trường hợp đặc biệt bằng cách thay thế phần thân của fibonacci
hàm.
switch (n) {
case 0: return 0;
case 1: return 1;
default: return fibonacci(n - 2) + fibonacci(n - 1);
}
"Làm xong."
Phần kết luận
Như tôi đã nói, bài tập như vậy hoàn toàn không liên quan đến một công việc thực tế của một nhà phát triển. Liệu nó làm cho nó vô nghĩa? Không thực sự, bởi vì ít nhất, nó cho thấy rằng người đó:
Có thể nghĩ về một vấn đề. Một số ứng viên sẽ hoàn toàn bị mất, và bị căng thẳng, sẽ mất nhiều thời gian hơn để chỉ nghĩ về một cách có thể để tiếp cận vấn đề.
Biết đệ quy hoặc có thể tránh được đệ quy thông qua một vòng lặp thông thường. Sau đó, người phỏng vấn có thể hỏi liệu có cách nào để sử dụng / không sử dụng đệ quy không, và lợi ích / hạn chế của đệ quy là gì.
Biết những điều cơ bản của ngôn ngữ lập trình. Không có vấn đề gì nếu người được sử dụng switch
, một điều khoản bảo vệ, một điều kiện hoặc một từ điển : tùy thuộc vào nền tảng, các ứng cử viên khác nhau sẽ chọn các công cụ khác nhau để thực hiện cùng một điều.
Giữ tập trung vào vấn đề, mà không mang lại những thứ như kiểm tra đơn vị, khả năng mở rộng hoặc hiệu suất. Người phỏng vấn sau đó có thể hỏi tại sao hiệu suất khôn ngoan, chức năng trên là khủng khiếp, mong muốn ứng viên giải thích những gì nên làm để đưa hiệu suất đến mức hợp lý.
Ví dụ 2: câu hỏi khó
Bạn cần triển khai máy tính số Fibonacci trong JavaScript. Nó nên càng nhanh càng tốt. Bạn sẽ có thể thay đổi chỉ số trong khoảng từ 0 đến 100. Trình tự Fibonacci tuân theo các quy tắc sau:
- Hai số đầu tiên của dãy là 0 và 1,
- Mỗi số tiếp theo là tổng của hai số trước.
Ví dụ: F 0 = 0, F 1 = 1, F 2 = 1, F 3 = 2, F 10 = 55.
Bạn có ba phút.
Bây giờ, chúng ta có một ràng buộc thú vị cho thấy người phỏng vấn không thực sự quan tâm đến khả năng giải quyết vấn đề của ứng viên, mà là về khả năng đoán những cách nào nhanh hơn những cách khác.
Những câu hỏi khó thường mời những câu trả lời khó. Ở đây, với sự hạn chế về thời gian, không có cách nào để thực hiện nhiều triển khai, đánh giá chúng, lập hồ sơ nhanh nhất và đưa ra một giải pháp tối ưu.
Thay vào đó, những gì về:
Hãy để tôi Google "Số Fibonacci đầu tiên" ... Điều này có vẻ đầy hứa hẹn. Với một biểu thức chính quy đơn giản (đó sẽ là một oxymoron), chúng ta có thể xây dựng một danh sách các giá trị được phân tách bằng dấu phẩy.
sed -e "s;\([0-9]*\) \([0-9]*\);'\2',;g" fbncc10.txt | tr '\n' ' '
Cuối cùng, chương trình.
var map = ['0', '1', '1', '2', '3', '5', '8', '13', '21', '34', '55', '89', '144', '233', '377', '610', '987', '1597', '2584', '4181', '6765', '10946', '17711', '28657', '46368', '75025', '121393', '196418', '317811', '514229', '832040', '1346269', '2178309', '3524578', '5702887', '9227465', '14930352', '24157817', '39088169', '63245986', '102334155', '165580141', '267914296', '433494437', '701408733', '1134903170', '1836311903', '2971215073', '4807526976', '7778742049', '12586269025', '20365011074', '32951280099', '53316291173', '86267571272', '139583862445', '225851433717', '365435296162', '591286729879', '956722026041', '1548008755920', '2504730781961', '4052739537881', '6557470319842', '10610209857723', '17167680177565', '27777890035288', '44945570212853', '72723460248141', '117669030460994', '190392490709135', '308061521170129', '498454011879264', '806515533049393', '1304969544928657', '2111485077978050', '3416454622906707', '5527939700884757', '8944394323791464', '14472334024676221', '23416728348467685', '37889062373143906', '61305790721611591', '99194853094755497', '160500643816367088', '259695496911122585', '420196140727489673', '679891637638612258', '1100087778366101931', '1779979416004714189', '2880067194370816120', '4660046610375530309', '7540113804746346429', '12200160415121876738', '19740274219868223167', '31940434634990099905', '51680708854858323072', '83621143489848422977', '135301852344706746049', '218922995834555169026', '354224848179261915075'];
var fibonacci = function (n) {
return map[n];
};
console.log(fibonacci(10));
Phần kết luận
Câu hỏi khó khăn mời câu trả lời khó khăn. Đừng là anh hùng, và đừng bắt đầu điểm chuẩn và hồ sơ khi bạn chỉ có ba phút. Hãy nghĩ về những cách thông minh để giải quyết vấn đề trong khi sử dụng kinh nghiệm của bạn. Kinh nghiệm của tôi cho tôi một gợi ý rằng sử dụng bản đồ có thể nhanh hơn so với tính toán số. Nó có thể sai, nhưng nỗ lực này nên được dự kiến với sự hạn chế về thời gian.
Biết các công cụ của bạn cũng giúp ích và là một phần thiết yếu của các kỹ năng dành cho nhà phát triển: không biết các biểu thức thông thường, tôi sẽ dành ba phút để phân bổ cho một danh sách được phân tách bằng dấu phẩy hoặc sẽ bắt đầu viết một trình phân tích cú pháp sẽ xây dựng mảng tôi cần.
Hãy nhớ rằng, một nhà phát triển giỏi không phải là người bắt đầu viết mã ngay lập tức, mà là người biết cách tránh mã hóa khi có cơ hội tốt hơn. Một số người phỏng vấn sẽ không ngần ngại giao cho bạn các bài tập giống như mã hóa, nhưng hầu như không yêu cầu mã nào cả.
Ví dụ 3: phát triển ứng dụng hoàn chỉnh
Bạn cần phải thực hiện chuỗi Fibonacci trong JavaScript. Độ dài của chuỗi được xác định trong quá trình thực hiện chương trình. Trình tự tuân theo các quy tắc:
- Hai số đầu tiên của dãy là 0 và 1,
- Mỗi số tiếp theo là tổng của hai số trước.
Ví dụ: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89.
Ứng dụng nên được trình bày dưới dạng một trang web, cho phép người dùng chỉ định độ dài của chuỗi thông qua một trường đầu vào.
Bạn có một giờ.
Hãy bắt đầu.
Trình tự ví dụ rất hữu ích, vì nó sẽ cho phép tôi có một loạt các bài kiểm tra đơn vị để đảm bảo việc thực hiện của tôi không hoàn toàn sai. Nói chung, tôi sử dụng Mocha cho node.js hoặc QUnit cho JavaScript phía máy khách, nhưng ở đây, để đơn giản, tôi sẽ chỉ ném một loạt các hàm kiểm tra.
Tôi bắt đầu bằng cách tạo index.htm
và fib.js
tập tin. Sau đó, tôi điền mã index.htm
thực sự tối giản và không tuân thủ W3C (chúng ta có thể quay lại vấn đề này sau nếu bạn cũng quan tâm đến các kỹ năng HTML của tôi).
<label>Length</label> <input id="length" value="15" />
<input id="compute" type="button" value="Compute" />
<div id="result" style="font-weight:bold;"></div>
<div id="tests"></div>
<script src="fib.js"></script>
Bây giờ, hãy viết một số mã sẽ gọi hàm tạo Fibonacci và hiển thị kết quả.
fibonacci = (function () {
var compute,
init;
compute = function (length) {
// TODO: Implement Fibonacci sequence.
return [1, 2, 3];
};
init = function () {
var button = document.getElementById('compute');
button.addEventListener('onclick', function () {
var length = parseInt(document.getElementById('length').value, 10),
result;
console.log(
'Computing Fibonacci sequence of length ' + length + '.'
);
result = compute(length);
document.getElementById('result').innerText = result.join(', ');
});
};
return {
compute: compute,
init: init
};
}());
Đây là thời gian để chạy mã lần đầu tiên và ... nó không hoạt động. Chẳng có gì xảy ra. Tại sao?"
fibonacci.init();
Cuối cùng , tôi đã quên mất . Tôi đã thêm nó, và vẫn không có gì xảy ra, trong khi ít nhất nó sẽ hiển thị thông báo trong bảng điều khiển. Đợi, đúng, không phải onclick
, nhưng click
; Tôi sử dụng JQuery thường xuyên đến nỗi tôi bắt đầu quên tên của các sự kiện trong JavaScript đơn giản.
Hãy để chúng tôi thêm một số bài kiểm tra.
ensureAreEqual = function (expected, actual) {
var testResultsContainer = document.getElementById('tests');
testResultsContainer.innerText += (expected.equals(actual) ?
'.' :
('Actual [' + actual.join(', ') + '] is different from ' +
'expected [' + expected.join(', ') + '].'));
};
test = function () {
ensureAreEqual([0], compute(1));
};
Mảng so sánh mảng có thể khó, vì vậy tôi chỉ cần sao chép-dán Array.prototype.equals
mã từ câu trả lời này .
Bây giờ chúng tôi chạy ứng dụng, nó hiển thị:
Thực tế [1, 2, 3] khác với dự kiến [0].
Thử nghiệm thất bại, rất được mong đợi, do triển khai thực tế ( return [1, 2, 3];
) của chuỗi Fibonacci của chúng tôi . Đã đến lúc thay đổi điều này.
Từ câu lệnh gốc, chuỗi Fibonacci bắt đầu bằng [0, 1]
, nên compute
trở thành:
compute = function (length) {
var fib = [0];
return fib;
};
Điều này làm cho nó có thể vượt qua bài kiểm tra đầu tiên, và bây giờ chúng tôi có thể viết bài kiểm tra thứ hai của chúng tôi.
ensureAreEqual([0, 1], compute(2));
Không thành công, vì vậy chúng tôi quay lại compute
và sửa đổi nó.
compute = function (length) {
var fib = [0, 1];
return length === 1 ? [0] : fib;
};
Bây giờ, cả hai bài kiểm tra đều vượt qua và đã đến lúc chuyển sang các trường hợp không có cạnh.
compute = function (length) {
var fib = [0, 1],
i,
next,
current = 1,
previous = 0;
for (i = 2; i < length; i += 1) {
next = current + previous;
previous = current;
current = next;
fib.push(next);
}
return length === 1 ? [0] : fib;
};
Hiện tại cả ba bài kiểm tra đều vượt qua, ngoại trừ kết quả không phù hợp với độ dài lớn hơn như 100. Để có được kết quả đúng, chúng ta nên sử dụng một thư viện chính xác tùy ý . Cũng có những điều cần cải thiện. Ví dụ, quy ước đặt tên đôi khi quá tệ (cái gì fib
?). Mã JavaScript liên quan đến HTML cũng nên chuyển đến một đối tượng khác, cũng như mã thử nghiệm. Ngoài ra, tôi chưa kiểm tra compute(0)
và chưa kiểm tra đầu vào.
Phần kết luận
Bằng cách xem qua ví dụ, bạn có thể thấy sự tương tác được mong đợi trong một cuộc phỏng vấn. Không phải mọi thứ đều suôn sẻ (lúc đầu tôi đã mắc một số lỗi dẫn đến một tình huống xấu hổ khi không có gì xảy ra khi tôi chạy ứng dụng), và cách tiếp cận ban đầu là khập khiễng nếu chúng tôi phải hỗ trợ một chuỗi dài, nhưng tôi đã đạt được để cho thấy rằng:
- Tôi có thể xử lý các vấn đề khác nhau,
- Tôi sử dụng phát triển theo hướng thử nghiệm, chuỗi Fibonacci là một cơ hội tuyệt vời cho việc này,
- Tôi sao chép-dán mã khi nguồn đáng tin cậy và viết nó từ đầu có vẻ rất phức tạp và dễ bị lỗi,
- Tôi không quá tin tưởng vào các thư viện như JQuery,
- Tôi đã chọn đúng phạm vi: vì người phỏng vấn muốn kiểm tra các kỹ năng JavaScript của tôi, tôi sẽ không lãng phí thời gian để viết HTML hoàn hảo và sạch sẽ: không dành thời gian ở đây khiến bạn có thể dành nhiều thời gian hơn để viết bài kiểm tra đơn vị,
- Tôi biết khi nào nên hoàn thành và nói rằng tôi đã hoàn thành, trong khi hãy nhớ rằng một loạt những thứ không hoàn hảo (như thế
compute(0)
sẽ thất bại, nhưng nó không quan trọng đối với bản demo).
Đây chính xác là những gì một người phỏng vấn nên mong đợi từ bạn.