Thư Viện Câu Hỏi Phỏng Vấn
Tổng hợp các câu hỏi tuyển dụng thực tế theo nhiều cấp độ từ Entry đến Expert để bạn tự tin chinh phục nhà tuyển dụng.
Luyện Tập Phỏng Vấn Thử
Mô phỏng áp lực phỏng vấn thật với đồng hồ đếm ngược từng câu, tự đánh giá phản xạ và đo lường độ sẵn sàng của bạn.
Giữa Delegate Pattern và Closures trong Swift, khi nào nên sử dụng phương án nào để truyền dữ liệu giữa các View Controller?
1. Delegate Pattern
Nội dung chi tiết câu trả lời, phân tích kỹ thuật chuyên sâu, mã nguồn minh họa và các trường hợp ngoại lệ chỉ dành riêng cho học viên Unicode E-learning...
Để mở khóa toàn bộ giải pháp chi tiết và tài liệu hướng dẫn phỏng vấn, vui lòng nâng cấp tài khoản hoặc tham gia gói Learning Pass để truy cập không giới hạn.
// Mã nguồn và kiến trúc giải pháp bị ẩn đối với tài khoản chưa nâng cấp...
Sự khác biệt cốt lõi giữa INNER JOIN và LEFT JOIN trong SQL là gì và lập trình viên cấp độ Junior thường gặp những cạm bẫy nào khi sử dụng chúng?
Bản chất cơ chế hoạt động
- INNER JOIN: Chỉ trả về các bản ghi có sự khớp nhau (matching rows) ở cả hai bảng dựa trên điều kiện kết nối (ON clause). Nếu không có bản ghi tương ứng ở bảng bên phải hoặc bên trái, dữ liệu đó sẽ bị loại bỏ hoàn toàn khỏi kết quả.
- LEFT JOIN: Trả về tất cả các bản ghi từ bảng bên trái (Left Table) và các bản ghi khớp từ bảng bên phải (Right Table). Nếu không tìm thấy bản ghi khớp ở bảng bên phải, các cột tương ứng từ bảng bên phải sẽ nhận giá trị NULL.
Cạm bẫy phổ biến của lập trình viên Junior
- Đặt điều kiện của bảng bên phải vào mệnh đề WHERE thay vì ON: Khi sử dụng LEFT JOIN, nếu bạn đặt bộ lọc
WHERE right_table.status = 'ACTIVE', vô tình điều kiện này sẽ biến LEFT JOIN thành INNER JOIN vì các giá trị NULL được sinh ra từ LEFT JOIN sẽ bị loại bỏ bởi mệnh đề WHERE. - Hiệu năng truy vấn kém do thiếu Index: Khi thực hiện JOIN trên các cột không có Index, Database Engine sẽ phải thực hiện Nested Loops hoặc Hash Match tốn rất nhiều tài nguyên CPU và I/O.
Ví dụ minh họa
-- Sai lầm phổ biến biến LEFT JOIN thành INNER JOIN
SELECT c.customer_name, o.order_id
FROM customers c
LEFT JOIN orders o ON c.id = o.customer_id
WHERE o.status = 'PENDING';
-- Khắc phục đúng bằng cách đưa điều kiện vào mệnh đề ON hoặc xử lý NULL
SELECT c.customer_name, o.order_id
FROM customers c
LEFT JOIN orders o ON c.id = o.customer_id AND o.status = 'PENDING';
Lưu ý kinh nghiệm thực chiến
Luôn xác định rõ chiều dữ liệu chính (Main Entity) trước khi viết câu lệnh JOIN. Đảm bảo các cột tham gia điều kiện ON đã được thiết lập Index đầy đủ để tối ưu hóa Execution Plan.
Tại sao việc sử dụng toán tử LIKE với ký tự đại diện ở đầu chuỗi (như '%abc') lại làm suy giảm hiệu năng nghiêm trọng trong SQL và cách khắc phục?
Bản chất cơ chế hoạt động
Khi bạn thực hiện tìm kiếm với mệnh đề WHERE column_name LIKE 'abc%', Database Engine có thể tận dụng B-Tree Index vì nó biết rõ chuỗi bắt đầu từ đâu và tiến hành Index Seek hiệu quả. Ngược lại, khi sử dụng LIKE '%abc' hoặc LIKE '%abc%', ký tự % ở đầu buộc hệ thống phải quét toàn bộ Index hoặc toàn bộ bảng (Full Table Scan / Index Scan).
Nội dung chi tiết câu trả lời, phân tích kỹ thuật chuyên sâu, mã nguồn minh họa và các trường hợp ngoại lệ chỉ dành riêng cho học viên Unicode E-learning...
Để mở khóa toàn bộ giải pháp chi tiết và tài liệu hướng dẫn phỏng vấn, vui lòng nâng cấp tài khoản hoặc tham gia gói Learning Pass để truy cập không giới hạn.
// Mã nguồn và kiến trúc giải pháp bị ẩn đối với tài khoản chưa nâng cấp...
Sự khác biệt giữa câu lệnh TRUNCATE và DELETE trong SQL là gì? Khi nào lập trình viên nên chọn loại nào trong môi trường sản xuất?
Bản chất cơ chế hoạt động
- DELETE: Là một câu lệnh DML (Data Manipulation Language). Nó xóa dữ liệu từng dòng một và ghi lại từng thao tác vào Transaction Log. Cho phép sử dụng mệnh đề WHERE để xóa có điều kiện, kích hoạt các Trigger liên quan và có thể Rollback nếu nằm trong một Transaction.
- TRUNCATE: Là một câu lệnh DDL (Data Definition Language). Nó hoạt động bằng cách giải phóng các trang dữ liệu (data pages) được cấp phát cho bảng thay vì xóa từng dòng. Không ghi chi tiết từng dòng vào Transaction Log, không kích hoạt Trigger, không thể dùng mệnh đề WHERE và tự động reset lại giá trị Identity (Auto-increment) về ban đầu.
So sánh hiệu năng và an toàn
- Hiệu năng: TRUNCATE nhanh hơn rất nhiều so với DELETE, đặc biệt trên các bảng có hàng triệu bản ghi vì nó ít tốn tài nguyên Log và khóa (locks) hơn.
- An toàn: DELETE an toàn hơn khi cần xóa có chọn lọc và có thể khôi phục dữ liệu nếu có lỗi xảy ra trong Transaction. TRUNCATE cực kỳ nguy hiểm nếu thực hiện nhầm vì dữ liệu bị xóa vĩnh viễn và không thể Rollback trong hầu hết các cấu hình thông thường.
Ví dụ minh họa
-- Xóa toàn bộ dữ liệu bảng logs nhưng giữ lại cấu trúc và reset identity
TRUNCATE TABLE system_logs;
-- Xóa dữ liệu có điều kiện trong bảng orders
DELETE FROM orders WHERE status = 'CANCELLED';
Lưu ý kinh nghiệm thực chiến
Trong môi trường Production, không bao giờ chạy TRUNCATE thủ công mà không có sự đồng ý của quản trị viên hệ thống. Hãy sử dụng DELETE kết hợp với Batching (chia nhỏ số lượng bản ghi xóa mỗi lần) để tránh gây ra hiện tượng Lock Escalation làm treo hệ thống.
Tại sao việc sử dụng hàm trên cột trong mệnh đề WHERE (như YEAR(created_date) = 2023) lại làm mất tác dụng của Index và cách viết lại tối ưu?
Bản chất cơ chế hoạt động
Khi bạn xây dựng một Index trên cột created_date, cấu trúc B-Tree được sắp xếp theo giá trị thời gian thực tế của từng bản ghi. Khi bạn bọc cột đó trong một hàm như YEAR(created_date) hoặc CONVERT(VARCHAR, created_date), Database Engine buộc phải tính toán giá trị của hàm này cho mọi dòng dữ liệu trong bảng trước khi so sánh. Điều này làm cho Index hiện có trở nên vô tác dụng, dẫn đến Full Table Scan.
Nội dung chi tiết câu trả lời, phân tích kỹ thuật chuyên sâu, mã nguồn minh họa và các trường hợp ngoại lệ chỉ dành riêng cho học viên Unicode E-learning...
Để mở khóa toàn bộ giải pháp chi tiết và tài liệu hướng dẫn phỏng vấn, vui lòng nâng cấp tài khoản hoặc tham gia gói Learning Pass để truy cập không giới hạn.
// Mã nguồn và kiến trúc giải pháp bị ẩn đối với tài khoản chưa nâng cấp...
Mục đích và cách sử dụng câu lệnh COALESCE trong SQL là gì? Tại sao nó là lựa chọn tốt hơn so với hàm ISNULL hoặc IFNULL trong các kịch bản thực tế?
Bản chất cơ chế hoạt động
- COALESCE: Là một hàm chuẩn thuộc chuẩn SQL ANSI, nhận vào một danh sách các biểu thức và trả về giá trị khác NULL đầu tiên từ trái sang phải. Nếu tất cả các biểu thức đều là NULL, nó sẽ trả về NULL.
- ISNULL / IFNULL: Thường là các hàm độc quyền (proprietary functions) của từng hệ quản trị cơ sở dữ liệu cụ thể (như ISNULL trong SQL Server hay IFNULL trong MySQL).
Ưu điểm vượt trội của COALESCE
- Tính tương thích cao (Portability): Vì tuân thủ chuẩn ANSI SQL, hàm COALESCE hoạt động nhất quán trên hầu hết các hệ quản trị cơ sở dữ liệu phổ biến như SQL Server, PostgreSQL, MySQL và Oracle.
- Hỗ trợ đa tham số: Bạn có thể truyền vào nhiều hơn hai giá trị để kiểm tra tuần tự.
- Xử lý kiểu dữ liệu chuẩn xác: COALESCE tự động suy diễn kiểu dữ liệu (data type precedence) cho giá trị trả về dựa trên các tham số được truyền vào.
Ví dụ minh họa
-- Sử dụng COALESCE để hiển thị tên thay thế nếu tên chính bị NULL
SELECT employee_id, COALESCE(preferred_name, middle_name, first_name, 'No Name') AS display_name
FROM employees;
Lưu ý kinh nghiệm thực chiến
Khi thiết kế các báo cáo hoặc API trả về dữ liệu cho frontend, việc sử dụng COALESCE giúp giảm thiểu tối đa các lỗi liên quan đến NullPointerException hoặc giá trị undefined ở tầng ứng dụng, đồng thời giúp câu lệnh SQL gọn gàng hơn rất nhiều so với việc lồng nhiều câu lệnh CASE WHEN phức tạp.
Trong quá trình phát triển ứng dụng thời gian thực với WebSockets, tại sao việc theo dõi và quản lý trạng thái kết nối thông qua sự kiện kết nối và ngắt kết nối lại rất quan trọng đối với Junior developer?
Việc quản lý trạng thái kết nối thông qua các sự kiện kết nối và ngắt kết nối là cốt lõi trong lập trình WebSockets. Đối với một lập trình viên cấp độ Junior, việc hiểu rõ vòng đời của một kết nối giúp ngăn chặn các vấn đề nghiêm trọng như rò rỉ bộ nhớ, treo kết nối không hợp lệ và cung cấp trải nghiệm người dùng tốt hơn.
Nội dung chi tiết câu trả lời, phân tích kỹ thuật chuyên sâu, mã nguồn minh họa và các trường hợp ngoại lệ chỉ dành riêng cho học viên Unicode E-learning...
Để mở khóa toàn bộ giải pháp chi tiết và tài liệu hướng dẫn phỏng vấn, vui lòng nâng cấp tài khoản hoặc tham gia gói Learning Pass để truy cập không giới hạn.
// Mã nguồn và kiến trúc giải pháp bị ẩn đối với tài khoản chưa nâng cấp...
Làm thế nào để xử lý việc định dạng và phân tích dữ liệu JSON khi gửi và nhận qua WebSockets một cách an toàn nhằm tránh làm sập ứng dụng?
Giao thức WebSockets truyền tải dữ liệu dưới dạng chuỗi văn bản hoặc mảng byte nhị phân. Dữ liệu JSON là lựa chọn phổ biến, nhưng việc phân tích sai cú pháp JSON có thể gây ra ngoại lệ làm sập toàn bộ tiến trình Node.js của Server.
Nội dung chi tiết câu trả lời, phân tích kỹ thuật chuyên sâu, mã nguồn minh họa và các trường hợp ngoại lệ chỉ dành riêng cho học viên Unicode E-learning...
Để mở khóa toàn bộ giải pháp chi tiết và tài liệu hướng dẫn phỏng vấn, vui lòng nâng cấp tài khoản hoặc tham gia gói Learning Pass để truy cập không giới hạn.
// Mã nguồn và kiến trúc giải pháp bị ẩn đối với tài khoản chưa nâng cấp...
Tại sao các lập trình viên cấp độ Junior cần hiểu rõ về cơ chế đồng bộ hóa luồng sự kiện (Event-driven) khi lập trình ứng dụng WebSocket phía Client?
Mô hình lập trình WebSockets dựa hoàn toàn trên sự kiện (Event-driven). Phía Client phải tương tác với Server thông qua việc lắng nghe các sự kiện đến và gửi đi các hành động khi có sự kiện từ người dùng.
Nội dung chi tiết câu trả lời, phân tích kỹ thuật chuyên sâu, mã nguồn minh họa và các trường hợp ngoại lệ chỉ dành riêng cho học viên Unicode E-learning...
Để mở khóa toàn bộ giải pháp chi tiết và tài liệu hướng dẫn phỏng vấn, vui lòng nâng cấp tài khoản hoặc tham gia gói Learning Pass để truy cập không giới hạn.
// Mã nguồn và kiến trúc giải pháp bị ẩn đối với tài khoản chưa nâng cấp...
Khi kiểm thử (Testing) các tính năng sử dụng WebSockets trong quá trình phát triển, những vấn đề tiềm ẩn nào thường xuất hiện ở môi trường mạng cục bộ mà Junior hay bỏ qua?
Khi kiểm thử ứng dụng WebSockets ở môi trường phát triển cục bộ (Localhost), độ trễ mạng gần như bằng không và kết nối luôn ổn định. Tuy nhiên, khi đưa lên môi trường thực tế, các vấn đề về mạng không ổn định sẽ bộc lộ.
Nội dung chi tiết câu trả lời, phân tích kỹ thuật chuyên sâu, mã nguồn minh họa và các trường hợp ngoại lệ chỉ dành riêng cho học viên Unicode E-learning...
Để mở khóa toàn bộ giải pháp chi tiết và tài liệu hướng dẫn phỏng vấn, vui lòng nâng cấp tài khoản hoặc tham gia gói Learning Pass để truy cập không giới hạn.
// Mã nguồn và kiến trúc giải pháp bị ẩn đối với tài khoản chưa nâng cấp...
Tại sao việc xác thực người dùng (Authentication) ngay trong giai đoạn thiết lập kết nối ban đầu lại quan trọng và làm thế nào để truyền token an toàn trong WebSockets?
Bảo mật là yếu tố tối quan trọng. Một WebSocket server không được bảo vệ sẽ cho phép bất kỳ ai kết nối và gửi nhận tin nhắn, dẫn đến các lỗ hổng nghiêm trọng như giả mạo tin nhắn hoặc tấn công tràn bộ nhớ.
Nội dung chi tiết câu trả lời, phân tích kỹ thuật chuyên sâu, mã nguồn minh họa và các trường hợp ngoại lệ chỉ dành riêng cho học viên Unicode E-learning...
Để mở khóa toàn bộ giải pháp chi tiết và tài liệu hướng dẫn phỏng vấn, vui lòng nâng cấp tài khoản hoặc tham gia gói Learning Pass để truy cập không giới hạn.
// Mã nguồn và kiến trúc giải pháp bị ẩn đối với tài khoản chưa nâng cấp...
Trong Ruby on Rails, sự khác biệt giữa Eager Loading và Lazy Loading là gì và khi nào bạn nên ưu tiên sử dụng từng phương pháp để tối ưu hóa truy vấn cơ sở dữ liệu?
Bản chất cơ chế
- Lazy Loading: Là cơ chế mặc định của Active Record. Dữ liệu chỉ được truy vấn từ cơ sở dữ liệu khi bạn thực sự gọi đến thuộc tính của đối tượng đó. Điều này giúp tiết kiệm bộ nhớ nhưng dễ dẫn đến vấn đề N+1 queries.
- Eager Loading: Là kỹ thuật tải trước các dữ liệu liên quan (associations) ngay từ đầu bằng cách sử dụng các phương thức như
includes,preload, hoặceager_load.
Khi nào nên sử dụng
- Sử dụng Lazy Loading: Khi bạn chỉ cần truy xuất dữ liệu của một đối tượng đơn lẻ hoặc các điều kiện logic phức tạp khiến việc tải trước dữ liệu trở nên lãng phí.
- Sử dụng Eager Loading: Khi bạn hiển thị danh sách (collection) và cần truy cập vào các bảng liên quan (ví dụ:
Usercó nhiềuPosts).
Ví dụ code
# Lazy Loading (Dễ gây N+1)
users = User.limit(10)
users.each { |user| puts user.posts.count }
# Eager Loading (Tối ưu)
users = User.includes(:posts).limit(10)
users.each { |user| puts user.posts.count }
Lưu ý thực chiến
Luôn sử dụng gem bullet trong môi trường phát triển để tự động phát hiện các truy vấn N+1 mà bạn vô tình tạo ra.
Tại sao việc sử dụng Callback trong Active Record quá mức lại được coi là một anti-pattern trong các dự án Enterprise và cách khắc phục?
Tại sao là anti-pattern
- Khó kiểm soát luồng: Các callback như
after_savehoặcbefore_createchạy ngầm, khiến việc debug trở nên khó khăn khi logic nghiệp vụ thay đổi. - Vi phạm nguyên tắc Single Responsibility: Model trở nên quá cồng kềnh (Fat Model) khi chứa quá nhiều logic nghiệp vụ không liên quan trực tiếp đến dữ liệu.
- Khó khăn khi Testing: Các callback chạy tự động mỗi khi lưu dữ liệu, gây khó khăn cho việc cô lập unit test.
Cách khắc phục
- Service Objects: Chuyển logic nghiệp vụ vào các Service Objects để xử lý các tác vụ phức tạp.
- Form Objects: Sử dụng Form Objects để xử lý dữ liệu đầu vào và các logic validation trước khi lưu vào cơ sở dữ liệu.
- Pub/Sub hoặc Observers: Sử dụng các cơ chế sự kiện (Event-driven) để tách biệt các tác vụ phụ (như gửi email, thông báo) ra khỏi luồng lưu dữ liệu chính.
Lưu ý thực chiến
Chỉ nên sử dụng callback cho các logic liên quan trực tiếp đến tính toàn vẹn của dữ liệu trong chính model đó (ví dụ: format lại email trước khi lưu).
Giải thích vai trò của Gemfile và Gemfile.lock trong quản lý phụ thuộc (dependency management) và tại sao phải luôn commit cả hai file này vào hệ thống quản lý phiên bản?
Vai trò của các file
- Gemfile: Định nghĩa danh sách các thư viện (gems) mà ứng dụng cần. Nó cho phép chỉ định phiên bản linh hoạt (ví dụ:
gem 'rails', '~> 7.0'). - Gemfile.lock: Là bản ghi chính xác về phiên bản của tất cả các gem và các gem phụ thuộc (dependencies) đang được sử dụng trong môi trường hiện tại.
Tại sao phải commit cả hai
- Tính nhất quán: Đảm bảo rằng mọi thành viên trong đội ngũ phát triển và môi trường Production đều sử dụng chính xác cùng một phiên bản gem, tránh lỗi 'trên máy tôi chạy được nhưng trên server thì không'.
- Tính tái lập: Giúp việc triển khai (deployment) trở nên tin cậy, vì hệ thống sẽ cài đặt đúng các phiên bản đã được kiểm thử kỹ lưỡng.
Lưu ý thực chiến
Không bao giờ chỉnh sửa trực tiếp Gemfile.lock. Hãy luôn sử dụng lệnh bundle install hoặc bundle update để hệ thống tự động cập nhật file này.
Trong Ruby on Rails, sự khác biệt giữa `find`, `find_by` và `where` là gì? Khi nào nên sử dụng từng phương thức để đảm bảo an toàn và hiệu năng?
Phân tích chi tiết
Nội dung chi tiết câu trả lời, phân tích kỹ thuật chuyên sâu, mã nguồn minh họa và các trường hợp ngoại lệ chỉ dành riêng cho học viên Unicode E-learning...
Để mở khóa toàn bộ giải pháp chi tiết và tài liệu hướng dẫn phỏng vấn, vui lòng nâng cấp tài khoản hoặc tham gia gói Learning Pass để truy cập không giới hạn.
// Mã nguồn và kiến trúc giải pháp bị ẩn đối với tài khoản chưa nâng cấp...
Cần Mentor Phỏng Vấn Thử 1-1 & Tối Ưu CV?
Mô phỏng phỏng vấn kỹ thuật thực tế 1-1 qua Google Meet, nhận xét chi tiết điểm mạnh/yếu và sửa CV trực tiếp cùng giảng viên Unicode.
Kiểm Tra CV Chuẩn ATS Miễn Phí
Tải CV của bạn lên để hệ thống AI rà soát từ khóa kỹ năng, định dạng và tính điểm chuẩn nhà tuyển dụng.


