Phỏng vấn ở Sillicon Valley phần 2

Kết quả hình ảnh cho Silicon Valley
Tiếp theo phần 1, mình xin kể tiếp câu chuyện phỏng vấn ở Silicon Valley. Sau lần thất bại đó, đơn vị tiếp tục đưa ứng viên thứ 2 ra phỏng vấn. Thật bất ngờ, khi bác Director of Software engineer lại sử dụng y chang bộ câu hỏi lần trước. Đó là tình huống không được tính đến, vì ai cũng nghĩ rằng cụ sẽ hỏi câu hỏi khác. Kết quả thì ai cũng biết, lại tạch.
Tuy nhiên, với phương châm không bỏ cuộc, never give up, vì nếu fail phỏng vấn đồng nghĩa là lost dự án, ảnh hưởng đến business của công ty. Theo chỉ thị của lãnh đạo, các ban bệ vào cuộc, toàn bộ record của phỏng vấn được nghe lại, mổ xẻ như phân tích băng ghi hình trận đá bóng. Câu hỏi phỏng vấn được Google search, gửi tới các chuyên gia để được tư vấn. Thậm chí còn được post lên diễn đàn công nghệ để tham khảo (bà con cũng nhảy vô cãi nhau ỏm tỏi, mỗi người 1 đáp án, gạch đá ném đủ xây nhà). Bản thân mình cũng phải cố gắng tìm hiểu Google, tham khảo ý kiến của nhiều người để tìm câu trả lời đúng nhất.
Sau hàng loạt các phân tích bình luận của các chuyên gia thì đã tìm ra câu trả lời có thể nói là chính xác nhất.
Câu 1) Viết code ví dụ về Singleton class
Thật ra có đến mấy kiểu viết code về Singleton class trong Java trong đó có 2 kiểu thông dụng là:
Early Instantiation: Tạo instance tại thời điểm class loade time.
Kiểu Lazy Loading: Instance được tạo khi Singleton class được dùng lần đầu tiên, như code đã trình bày ở phần 1
Cần phải trình bày cả trường hợp đa luồng như phần 1 nữa. Túm váy phải phân tích từng trường hợp, đánh giá ưu nhược điểm
Và 1 Singleton có thể tạm gọi là chuẩn man là như sau:
Quan trọng nhất là câu hỏi này, quyết định việc fail hay pass
Có trường hợp nào Singleton có tạo nhiều instance không?
Câu trả lời đúng ở đây là YES.
Java có một khái niệm là Reflection, API cho phép kiểm tra và modify behavior của methods, class at runtime.
Reflection này có thể gây ra việc destroy singleton property của singleton class.
Dẫn tới việc singleton bị destroy và tạo 2 object khác nhau thuộc sample class
Output:-
instance1.hashCode():- 366712642
instance2.hashCode():- 1829164700
Ngoài ra còn có trường hợp serialize/desterilize object cũng xảy ra:

Trích dẫn nguyên văn câu trong Head First Design Patterns: Be careful if you are using multiple class loaders; this could defeat Singleton implementation and result in multiple instances.
Câu 2: Coding
Viết chuỗi đảo ngược kí tự
Ngoài việc dùng vòng lặp đảo vị trí phần tử như phần 1, thì có thể sử dụng thuật toán đệ quy.
Code đơn giản hơn không phải lặp, nhưng mình không nghĩ đệ quy là tối ưu nhất vì trong đệ quy hàm sẽ được gọi nhiều lần và bộ nhớ stack sẽ bị chồng thêm dữ liệu dễ gây issue về bộ nhớ.
Bài code số 2:
Cho số dương integer n, tìm số cách để để chia n thành 5 số dương nhỏ hơn sao cho cộng lại thì vẫn là n
Ví dụ n = 5 thì output 1 vì chỉ có 1 case (1, 1, 1, 1, 1)
N = 12 thì có 7 cách
https://www.mathpages.com/home/kmath556/kmath556_files/image001.gif
Nhờ sự trợ giúp của anh Guc Gồ thì đã phát hiện ra đằng sau bài toán này là cả 1 bầu trời kiến thức về toán học
Đọc xong cảm thấy ngu người luôn.
Đại loại công thức để tìm số cách thế này. N là số dương cần chia, K là số lượng số dương < N
Tạm tóm lược thay kiểu nông dân như thế này:
Phát biểu tổng quát: cho n viên kẹo chia cho k em bé, hỏi có bao nhiêu cách? (n, k nguyên dương)
Tóm tắt cách giải:
  • Trải đều n viên kẹo ra bàn, nhận thấy có n – 1 chỗ trống giữa các viên kẹo
  • Ta có k em bé -> cần nhét k-1 vách ngăn để ra k khoảng trống -> đáp án là tổ hợp chập (k-1) của (n-1), hay (n-1)C(k-1)
N = 7, k = 5 theo cách tính tổ hợp chập thì có 15 cách cụ thể là:
{2, 2, 1, 1, 1}
{2, 1, 2, 1, 1}
{2, 1, 1, 2, 1}
{2, 1, 1, 1, 2}
{1, 2, 2, 1, 1}
{1, 2, 1, 2, 1}
{1, 2, 1, 1, 2}
{1, 1, 2, 2, 1}
{1, 1, 2, 1, 2}
{1, 1, 1, 2, 2}
(Thực ra chỉ có 1 cách là 2 số 2 và 3 số 1)
{3, 1, 1, 1, 1}
{1, 3, 1, 1, 1}
{1, 1, 3, 1, 1}
{1, 1, 1, 3, 1}
{1, 1, 1, 1, 3
(Thực ra chỉ có 1 cách là 1 số 3 và 4 số 1)
Tuy nhiên do bài toán ko care đến order nên cần thêm bước loại trừ những kết quả trùng nhau nữa.
Câu 3: Câu hỏi về vấn đề hệ thống read data 99%, write 1% thì nên chọn loại dữ liệu gì?
Câu trả lời là ArrayList như phần 1, nhưng trường hợp đa luồng thì vẫn có thể dùng ArrayList nhưng không share list này giữa các thread. Tóm lại là handle with care, hàng dễ vỡ xài cẩn thận.
Hoặc 1 câu trả lời khác như sau (Xin tư vấn của 1 cao thủ Java).
Nếu là môi trường single-thread thì dùng ArrayList tốt hơn LinkedList trong trường hợp ở đây (nhất là khi list có kích thước tương đối lớn) là vì ArrayList là random access trong khi LinkedList thì không.
Đổi lại thì thêm, remove phần tử trên ArrayList sẽ kém hơn về performance so với LinkedList (do phải xử lý cái backed array). Tất nhiên là performance của hệ thống thì ko thể dựa hoàn toàn trên tính toán định tính, mà cần dựa trên các công cụ monitor với con số cụ thể.
Nếu là môi trường multi-thread thì nên dùng CopyOnWriteArrayList, lý do là nó đảm bảo thread-safe trong khi implement của hàm read() trong mô hình CopyOnWrite nó ko đòi hỏi phải sử dụng lock.

Tuy nhiên, câu hỏi thế này thì nên hỏi ngược lại vì nó thiếu thông tin cần thiết để có đáp án chính xác.Dẫn chứng nguyên văn của một tiền bối: Read là read kiểu gì, write là write như thế nào, vặn lại luôn là đã có điểm cộng rồi. Đề bài cho thế ko thể đủ dữ kiện phán đoán được. Ví dụ random read thì array hơn, nhưng sequential read như nhau. Write cũng vậy, nếu write vào cuối thì array là nhanh nhất. Chém gió nâng cao thì nếu lượng phần tử cực lớn và sequential read thì array sẽ có ưu thế rõ ràng hơn do memory được allocate contiguous chứ không bị fragment như linked list. Do đó nó fit vào cùng cache line, vì thời buổi này bottle neck chủ yếu ở memory, cứ fragment xong miss cache một phát là bay vài trăm cycle ngay.Câu 4: Anh có service expose API cho client, nếu anh dùng GET api call service qua HTTPS chú thấy có secure không?Trong trường hợp sensitive data phải include trong GET request, nó sẽ vi phạm security best practices. Full URL query parameters (bao gồm query parameters) của GET requess sẽ bị logged trong server logs và có nguy cơ được truy cập trái phép. Trong trường hợp data on the query parameters không nên xuất hiện trong logs, bạn nên sử dụng POST thay cho GET.
OK, vậy là sau collect đủ các thông tin cần thiết, team đã build thành 1 bộ đề phỏng vấn bao gồm câu hỏi và đáp án. Y chang kiểu bộ đề tuyển sinh đại học.
Công việc tiếp theo là trao bộ đề lại cho 1 thanh niên thứ 3 đi phỏng vấn, vào cầu cho ông cụ hỏi đúng câu cũ.
Ứng viên thứ 3 có English khá tốt, bộ đề, đáp án đã được bàn giao và đọc trước. Khác với lần phỏng vấn trước, lần này có đầy đủ ban bệ lãnh đạo có mặt. Vì xác định lần này tạch thì coi như mất dự án, anh em treo niêu.
Anh e đã làm hết sức mình, còn lại trông chờ vào kĩ năng chém gió của candidate. Nghe nói em manager tối còn phát đốt hương khấn vái.
Đồng hồ dịch chuyển dần đến giờ interview 9:30, mọi người hồi hộp chờ đợi…
Lại bác Director of Software engineering xuất hiện, nụ cười hiền từ.
Câu hỏi thứ nhất
Câu 1) Viết code ví dụ về Singleton class
Câu 2) Viết code đảo chiều chuỗi…
Câu 3)….
Trời. Đúng là kiếp trước ăn ở tốt, trời phật phù hộ độ trì, các câu hỏi y chang. Kết quả thế nào đã rõ…
Cảm xúc vỡ òa, đúng là bạc già không bằng gà son. Lần này đã bắt bài được cách interview, cụ không lừa em được nữa nhá
Nhưng giờ vẫn nghĩ không thông được vì sao cụ lại dùng chung 1 bộ câu hỏi để interview?
Kết luận
Các cụ ngày xưa đã nói rằng “Người thất bại là người bỏ cuộc”, người chiến thắng là người không từ bỏ. Đôi khi thành công đến được còn cần 1 chút may mắn. Nhưng may mắn chỉ có được khi bạn đã cố gắng hết sức của mình. Thành công của người này có được có thể phải đánh đổi bằng sự đóng góp, hi sinh của tập thể, nhưng đều dành cho mục đích chung.
Đỗ Trọng Nguyên

No comments:

Post a Comment

The Ultimate XP Project

  (Bài chia sẻ của tác giả  Ryo Amano ) Trong  bài viết  số này, tôi muốn viết về dự án phát triển phần mềm có áp dụng nguyên tắc phát triển...