[Series Phỏng Vấn Backend] #3: Trả Lời Câu Hỏi "Kể Về Một Con Bug Khó Nhất Bạn Từng Gặp?"
Chào mừng anh em quay trở lại với series Giải Mã Phỏng Vấn Backend.
Trong bất kỳ buổi phỏng vấn Mid/Senior nào, chắc chắn bạn sẽ gặp một câu hỏi kinh điển: "Em hãy kể anh nghe về một lần em gặp một con bug khó. Cụ thể là code chạy ngon trên máy local nhưng lên môi trường test/production thì lại lỗi. Em đã phát hiện ra sao, lần theo nó thế nào, và cuối cùng nguyên nhân gốc là gì?"
Nhà tuyển dụng hỏi câu này không phải để nghe xem con bug đó có "khủng" hay không. Cái họ muốn nghe là cách bạn suy nghĩ, cách bạn khoanh vùng vấn đề và thái độ của bạn khi đối mặt với áp lực.
Hôm nay, mình sẽ chia sẻ một "kỷ niệm đau thương" thực tế với Laravel để làm kịch bản mẫu cho câu hỏi này. Một kịch bản hội tụ đủ: Triệu chứng Cách lần vết Nguyên nhân Cách Fix Bài học.
1. Triệu Chứng (Symptoms): Lời Nguyền "Trên Máy Em Chạy Bình Thường"
Hồi đó, mình được giao làm tính năng tích hợp API với một bên thứ 3 (Cổng thanh toán). Khi code và test trên môi trường Local, mọi request đều trả về HTTP 200 OK, luồng chạy cực kỳ mượt mà.
Nhưng ngay sau khi merge code và deploy lên môi trường Production, tính năng đó... chết đứng. Hệ thống liên tục văng ra lỗi HTTP 401 Unauthorized từ phía đối tác, khiến user không thể hoàn tất giao dịch.
2. Truy Vết (Tracing): Bình Tĩnh Khoanh Vùng, Không Đoán Mò
Khi nhận được bug trên Prod, quy tắc số 1 là không được hoảng loạn sửa code mù quáng. Mình bắt đầu lần theo dấu vết:
- Bước 1: Soi Log. Chui vào
storage/logs/laravel.logtrên server mình check chi tiết lỗi 401. Khi dump thử payload gửi đi, mình phát hiện ra chuỗi API Key đính kèm trong Header đang bị rỗng (null). - Bước 2: Kiểm tra môi trường (Environment). Suy nghĩ đầu tiên nảy lên: "Chắc lúc deploy, anh em DevOps quên cấu hình biến môi trường này rồi". Mình lập tức nhờ check lại file .env trên Production. Nhưng bất ngờ thay, file
.envvẫn nằm đó, API Key được điền đầy đủ và hoàn toàn chính xác. - Bước 3: Tái hiện (Reproduce). Cùng một file
.env, sao code lại không nhận? Mình xin phép dùngphp artisan tinkertrên môi trường Staging (có setup giống hệt Prod) để test thử. Khi gõ lệnhenv('THIRD_PARTY_API_KEY'), kết quả trả về đúng lànullthật!
Lúc này, mình lờ mờ nhận ra vấn đề không nằm ở DevOps, mà nằm ở cơ chế của Framework.
3. Nguyên Nhân Gốc Rễ (Root Cause): Khoảnh Khắc "À Há!"
Bình tĩnh xâu chuỗi lại, mình nhớ ra sự khác biệt lớn nhất giữa Local và Production trong Laravel chính là Cơ chế Caching.
Trên Local, chúng ta thường không cache config, nên hàm env() gọi ở đâu cũng lấy được dữ liệu trực tiếp từ file .env. Tuy nhiên, trong pipeline CI/CD deploy lên Production, hệ thống LUÔN chạy lệnh php artisan config:cache để gộp toàn bộ file config lại thành một file duy nhất nhằm tối ưu tốc độ boot của framework.
Và đây là "cú lừa" được ghi rành rành trong Document của Laravel nhưng nhiều anh em bỏ qua: Một khi cấu hình đã được cache, hàm env() nếu được gọi ở bất cứ đâu bên ngoài thư mục config/ sẽ lập tức trả về null. Trong code của mình lúc đó, mình lại lười và gọi trực tiếp env('THIRD_PARTY_API_KEY') ngay bên trong file PaymentService.php. Đó chính là nguyên nhân gốc rễ!
4. Cách Khắc Phục (The Fix): Gọn Gàng Và Chuẩn Chỉ
Giải pháp fix thì rất nhanh và chỉ tốn 2 phút:
- Mình khai báo biến đó vào trong file
config/services.php:'payment_key' => env('THIRD_PARTY_API_KEY') - Trong
PaymentService.php, mình thay thế dòng code cũ thành:$apiKey = config('services.payment_key');
Sau đó push code, chạy lại php artisan config:clear và config:cache trên Prod. Hệ thống lập tức chạy trơn tru, API Key được nhận đầy đủ và lỗi 401 biến mất.
5. Bài Học Rút Ra (The Lesson): Trưởng Thành Từ Những Cú Vấp
Câu trả lời phỏng vấn sẽ không trọn vẹn nếu thiếu đi phần đúc kết. Sau case đó, mình rút ra được 2 nguyên tắc sống còn:
- Về Coding Convention: Tuyệt đối không bao giờ lạm dụng helper
env()rải rác trong các logic code (Controller, Service, Model...). Mọi biến môi trường bắt buộc phải được quy tụ về thư mụcconfig/và gọi ra qua helperconfig(). - Về Tư duy Hệ thống: Phải nắm rất vững vòng đời (Lifecycle) và các cơ chế Optimize của framework ở môi trường Production. Môi trường Dev quá thoải mái đôi khi sẽ che giấu đi những sai sót chí mạng về mặt kiến trúc.
Tổng Kết
Một câu chuyện debug hay không nằm ở việc lỗi đó cao siêu đến mức nào, mà nằm ở việc bạn thể hiện được sự logic, mạch lạc trong quá trình tìm lỗi. Lỗi do env() không mới, nhưng nếu bạn kể lại nó một cách có hệ thống như trên, nhà tuyển dụng chắc chắn sẽ gật gù đánh giá cao sự chuyên nghiệp của bạn.
*** Anh em đã từng có kỷ niệm debug nào "nhớ đời" muốn chia sẻ không? Cùng thả bình luận giao lưu nhé! Nhớ Upvote để series của chúng ta có thêm động lực ra mắt các kỳ tiếp theo!
All rights reserved