Xử lý lỗi (exception) tốt: những nguyên tắc ai cũng nên biết

  • author-image

    Nguyễn Đình Cường

  • blog-tag
  • blog-comment 0 comment
  • created-date 09 Nov, 2026
blog-thumbnail

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

1. Đừng nuốt lỗi một cách im lặ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.

2. Chỉ bắt lỗi khi bạn biết xử lý

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

3. Bắt đúng loại lỗi, tránh bắt quá rộng

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

4. Phân biệt lỗi mong đợi và lỗi bất ngờ

  • Lỗi mong đợi (có thể phục hồi): người dùng nhập sai định dạng, file chưa tồn tại, kết nối mạng timeout. Xử lý bằng thông báo thân thiện, thử lại hoặc giá trị mặc định.
  • Lỗi bất ngờ (bug): null không lường trước, lỗi logic. Nên cho chương trình thất bại rõ ràng (fail fast), ghi log đầy đủ để dev sửa, và hiển thị thông báo chung cho người dùng.

5. Thông báo lỗi hữu ích cho cả hai phía

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"

6. Giữ lại nguyên nhân gốc khi bọc lỗi

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 e

7. Luôn dọn dẹp tài nguyên

File, 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ỗi

8. Kiểm tra đầu vào sớm

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

9. Thử lại có kiểm soát với lỗi tạm thời

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.

10. Test cả đường lỗ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.

Kết luận

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.

author_photo
Nguyễn Đình Cường

0 comment