Explore all courses in this category.
Explore all courses in this category.
Nguyễn Đình Cường
0 comment
09 Nov, 2026
Chương trình nào cũng gặp lỗi: file không tồn tại, mạng chập chờn, người dùng nhập sai. Điều phân biệt phần mềm tốt với phần mềm mong manh là cách nó xử lý những tình huống đó. Dưới đây là các nguyên tắc xử lý lỗi áp dụng được cho hầu hết ngôn ngữ.
Đây là lỗi tệ nhất: bắt exception rồi bỏ qua.
try {saveOrder(order);} catch (e) {// không làm gì cả}Đơn hàng không được lưu mà không ai biết, người dùng tưởng đã thành công. Ít nhất hãy ghi log đầy đủ, và quyết định rõ: thử lại, báo cho người dùng, hay ném lỗi lên tầng trên.
Nhiều người bao bọc mọi thứ trong try/catch cho "an toàn". Thực ra nếu tại điểm đó bạn không biết làm gì có ích, hãy để lỗi đi lên nơi có đủ thông tin để xử lý (ví dụ tầng giao diện hiển thị thông báo, hoặc middleware chung ghi log và trả mã lỗi). Bắt lỗi quá sớm và chỉ để in ra đôi khi chỉ che giấu vấn đề.
# Pythontry:value = int(user_input)except ValueError:print("Vui lòng nhập một số nguyên")Bắt riêng ValueError tốt hơn nhiều so với except Exception hay except: vì bạn sẽ không vô tình nuốt cả lỗi lập trình (bug) mà bạn muốn biết. Hãy bắt loại cụ thể và xử lý phù hợp với từng loại.
Thông điệp cho người dùng cần ngắn gọn, dễ hiểu, gợi ý cách khắc phục, và không lộ thông tin nhạy cảm (đường dẫn, câu lệnh SQL, stack trace). Thông điệp trong log cho lập trình viên cần chi tiết: chuyện gì xảy ra, với dữ liệu nào, ở đâu.
// Cho người dùng"Không thể tải hồ sơ. Vui lòng thử lại sau ít phút."// Trong log"Failed to load profile userId=42: connection timeout after 5000ms"Khi chuyển đổi lỗi tầng thấp thành lỗi nghiệp vụ, đừng làm mất thông tin ban đầu. Hầu hết ngôn ngữ cho phép gắn lỗi gốc (cause):
// JavaScripttry {await db.insert(order);} catch (err) {throw new Error('Không thể lưu đơn hàng', { cause: err });}# Pythontry:save(order)except IOError as e:raise OrderError("Không thể lưu đơn hàng") from eFile, kết nối database, khóa (lock) phải được giải phóng dù có lỗi hay không. Dùng cấu trúc ngôn ngữ cung cấp: finally, with trong Python, using trong C#, try-with-resources trong Java, defer trong Go.
with open("data.txt") as f:content = f.read()# file tự động đóng, kể cả khi đọc bị lỗiNhiều lỗi có thể ngăn chặn từ đầu bằng việc xác thực dữ liệu tại ranh giới hệ thống (form, API, file nhập). Khi dữ liệu đã được kiểm tra, các tầng bên trong có thể tin tưởng nó hơn. Kết hợp với guard clause để thoát sớm khi đầu vào sai.
Lỗi mạng hay timeout có thể tự hết. Hãy thử lại một vài lần với khoảng chờ tăng dần (exponential backoff), giới hạn số lần thử, và chỉ thử lại những thao tác an toàn khi lặp (idempotent). Thử lại vô hạn có thể làm sập hệ thống đang quá tải.
Viết test cho các tình huống thất bại: file không tồn tại, dịch vụ ngoài trả lỗi, dữ liệu sai. Rất nhiều lỗi nghiêm trọng nằm ở nhánh xử lý lỗi vì nó hiếm khi được chạy.
Xử lý lỗi tốt là: không nuốt lỗi, bắt đúng loại và đúng chỗ, giữ thông tin nguyên nhân, dọn dẹp tài nguyên, và luôn có thông điệp hữu ích cho cả người dùng lẫn lập trình viên. Hãy rà soát các khối try/catch trong dự án của bạn và xem có chỗ nào đang "nuốt" lỗi hay không.
Để học cách xây dựng ứng dụng bền vững từ nền tảng, bạn có thể khám phá các khóa học trên codebem.com.
Nguyễn Đình Cường
0 comment