Showing posts with label Java; Interview Question. Show all posts
Showing posts with label Java; Interview Question. Show all posts

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

Tôi đã phỏng vấn Java Developer ở Sillicon Valley như thế nào?

Image result for Java
Trước đây, mình hay đi phỏng vấn ứng viên, làm đề bài test để kiểm tra năng lực ứng viên. Nhưng giờ cũng đến lúc phải lên thớt, trở thành candidate, để người khác check hàng. Tuy nhiên, lần này là người check là một công ty ở Sillicon Valley.
Khách hàng là một unicorn (công ty vốn hóa tỉ đô) ở Sillicon Valley, vị trí cần tuyển là Back End engineer, ngôn ngữ lập trình là Java. Được biết phỏng vấn sẽ gồm 3 vòng. Vòng 1 làm bài Test, vòng 2 kiểm tra communication skill, khả năng leader ship, hiểu biết về process Scrum, vòng 3 check kiến thức kĩ thuật, khả năng design, problem solving.
Vì đã có 1 vài thanh niên tạch luôn từ vòng gửi xe, nên mình quyết định xin được thử, coi như là một cơ hội học hỏi và thử thách bản thân.
Mấy năm roài không còn sờ tới Java, chủ yếu làm mảng DevOps, Blockchain toàn code python, nodeJS là chính. Cái cert Java professional thi xong vứt xó, nên mấy ngày phải giở sách ra ôn lại, y chang như thi đại học.
Vòng 1 làm bài Test
Bài Test là một list câu hỏi về lập trình Java, SQL, thuật toán yêu cầu trả lời dưới hình thức tự luận ví dụ như:
– Trình bày sự khác nhau giữa StringBuilder và StringBuffer
– Nếu như table trong database mà sử dụng nhiều indexes quá thì chú xử lý như thế nào?
– Xử lý Garbage Collector trong Java
– Java collision object
– Volatile vấn đề cpu cache và main memory
– SQL query mà chậm thì check gì đầu tiên?
Thực tế thì mình nhận thấy bài Test cũng không đến nỗi quá khó, nếu như có kiến thức tương đối vững về Java, SQL database thì có thể vượt qua. Ví dụ như StringBuilder và StringBuffer thì sự khác biệt rõ nhất là StringBuffer là thread safe và synchronized còn StringBuilder thì không.
Anyway, vòng gửi xe qua được.
Vòng 2 phỏng vấn leadership
Vòng 2 mục đích chính là muốn kiểm tra khả năng communication, leadership, biết cách xử lý tình huống. Hình thức phỏng vấn online qua Google Hangout. Haizzz, từ xưa tới giờ toàn coding, có bao giờ làm quản lý lãnh đạo đâu, nhưng thôi cố tra Google thuộc sẵn mấy câu interview rồi tùy cơ ứng biến vậy.
Người phỏng vấn là một bác người Anh, Senior manager, qua giao tiếp thì nhận thấy bác này không phải chuyên về tech mà thiên về quản lý hơn. Rất may mắn là người Anh, nên phát âm khá chuẩn, không gặp khó khăn gì trong vấn đề nghe hiểu.
Cố thuộc sẵn mấy câu interview trong bộ đề nhưng đến lúc interview chả trúng cái nào, được duy nhất trúng tủ là các câu hỏi về Scrum process, Extreme programming (mô tả quy trình làm việc, các thuật ngữ trong Scrum như Restros, Grooming…) các câu hỏi khá ngẫu nhiên kiểu như:
– Nếu ý kiến của bạn bị team phản đối thì bạn làm thế nào?
– Nếu phải tuyển dụng 1 ứng viên cho team, bạn chọn tiêu chí nào?
– Dự án đang trong critical situation, xử lý ra sao?
Cơ bản những câu hỏi này đòi hỏi khả năng chém gió “hươu viện”, ứng biến nhanh của ứng viên, nếu trả lời ngập ngừng, luống cuống là xác định tạch.
Cũng may do đã chinh chiến nhiều năm lại cũng gặp nhiều tính huống tương tự nên basic thì cũng pass được.
Vòng 3 phỏng vấn kĩ thuật
Đây là vòng quyết định. Trong vòng này, ứng viên sẽ phải trả lời các câu hỏi kiếm tra kiến thức kĩ thuật, viết code lập trình để xử lý thuật toán nào đó trên Google Doc. Người phỏng vấn sẽ quan sát cách ứng viên viết code để đánh giá năng lực. Nó cũng tương tự như kiểu viết code trên bảng trắng, run và debug bằng niềm tin.
Người phỏng vấn là 1 bác Director of Software engineering người Ấn, nói tiếng Anh dập như máy khâu, giọng lơ lớ, nghe đúng là khốn khổ, xem CV LinkedIn của bác thì tí ngất, với trên 20 năm kinh nghiệm lâp trình đa luồng, chuyên về machine learning, extensive experience working with concurrency primitives such as atomic reference, read write lock, countdownlatch. Bác còn tự build một mạng xã hội khoảng mấy trăm nghìn user truy cập mỗi ngày. Xem thông tin biết lần này là gặp trùm cuối Thanos rồi, nhưng thôi đành nhắm mắt đưa chân vậy.
Sau màn chào hỏi, giới thiệu bản thân xong thì bắt đâu nhào vô code.
Viết code mô tả singleton class
Mừng như bắt được vàng, món này code suốt rồi. Thế rồi mồm chém tay code, kinh nghiệm là tuyệt đối không được im lặng ngồi code, cần trình bày ý tưởng trước rồi mới code, code đến line nào trình bày line đấy.
Cụ xem xong cười “Cái này chả phải singleton”.
À cụ muốn hỏi đến chỗ đa luồng, code này single thread thì OK, gặp multi-thread thì tạch ok để em sửa code tí.
Có 2 cách sửa thêm synchronized vào method
Hoặc kiểu lazy như dưới:
Rồi, OK, sau một vài câu hỏi như bỏ synchronized ở method với block code có gì khác nhau… thêm cụ chốt:
– Có trường hợp nào mà Singleton lại tạo ra nhiều instance không?.
– Dạ không anh
– Có đấy, giải thích vì sao có đi.
Chết, căng rồi, confuse quá, mục đính Singleton là để tạo ra 1 object, sao lại ra lắm instance được. Hay là cụ cố bẫy mình chăng? Sau một hồi cắn bật máu môi đành chốt:
– Nếu mà tạo ra nhiều instance thì không còn là Singleton nữa ạ. Thật sự là không có.
Cụ phán:
– Thôi next sang câu thứ 2, viết code xử lý thuật toán. Bài 1: Viết code đảo ngược mảng array kí tự, yêu cầu phải optimize nhất, cấm chú chơi kiểu for loop cả mảng.
– Dạ, có thể dùng thuật toán đổi chỗ phần tử đầu với cuối là đảo ngược được.
Sau đó là lạch cạch lọc cọc một lúc thì xong.
– Độ phức tạp thuật toán là bao nhiêu, chơi for-loop cả mảng thì thế nào?
– Dạ O(n/2) vì em duyệt có nửa mảng, còn cái kia duyệt cả mảng nên O(n).
Rồi sang bài 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)
Hừm, mấy cái này cho mấy chú sinh viên thi CodeWar làm thì thần sầu rồi, mình già đầu óc chậm chạp.
Sau một hồi lọ mọ thì cũng nghĩ ra cách kiểu brute force, 5 vòng lặp duyệt từng thứ tự để ra kết quả, chắc có nhiều cách hay hơn nhưng bí quá rồi.
Thực tế trong tình huống chỉ có vài phút để suy nghĩ giải pháp và viết code, cộng thêm 1 ông còn đang soi code của mình, thì chọn quick dirty solutions mà vẫn work còn hơn là không có solutions nào.
5 vòng lặp nên độ phức tạp là O(n^5)
– Còn cách nào optimize hơn không, chú lặp nhiều quá.
– Lạy anh, em tắc rồi ạ
– OK, thôi xong phần coding, đến phần câu hỏi Design. Anh có hệ thống mà lượng read data chiếm 99% write data 1℅ thì chọn là dữ liệu nào?
– Em cho rằng dùng ArrayList là ổn, vì ArrayList sử dụng index, tốc độ truy cập nhanh hơn nhưng loại LinkedList chỉ phù hợp write data.
– Ờ, thế hệ thống này dùng Multi-thread thì sao?
– Thế chơi Vector vì nó thread safed. – Tôi dõng dạc trả lời.
– Vector có throughtput không?
– Ôi chết, throughtput là gì ta, chưa nghe bao giờ, giá như có cái Google ở đây thì ngon biết mấy.
Tắc tịt…
– Thế em xài HashTable, vì HashTable là thread-safed. – Tôi lại nói.
– Rồi, nhưng anh muốn dùng List cơ.
Khóc ra tiếng Mán, lại tịt, giờ chắc mỗi anh Google mới biết. Cụ hỏi tiếp:
– Rồi, câu cuối cùng, 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?
Ờ may, câu này thì biết.
– Theo em thì data parameters trong GET URL sẽ được encrypted trong HTTPs nên nếu hacker có capture được data thì cũng không view được. Tuy nhiên, một số server có thể lưu log có chứa data parameters trong GET request trên dạng plan-text, nên khuyến cáo là không nên dùng GET với sensitive data.
Rồi, kết thúc phỏng vấn.
Ngày sau nhận kết quả phỏng vấn: Not Good, tạch

Kết luận
Sau cuộc phỏng vấn, mình mới nhận thấy, kiến thức thực sự là bao la, trình độ của mình còn quá non kém so với kĩ sư của Sillicon Valley. Ngay cả một ngôn ngữ lập trình như Java, gần như các thanh niên Dev Vietnam ai cũng biết, nhưng để hiểu hết, hiểu sâu là gần như là impossible. Nhất là kiểu làm việc outsourcing công nghệ gì cũng mó một tí, chưa vững đã phải sang cái khác.

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...