Trong phát triển web/app, lỗi là chuyện chắc chắn xảy ra: mạng chập chờn, API trả về sai trạng thái, người dùng nhập thiếu dữ liệu, token hết hạn, thanh toán thất bại, hoặc hệ thống bên thứ ba tạm ngưng. Vấn đề không phải là làm sao để không bao giờ có lỗi, mà là thiết kế cách xử lý lỗi sao cho người dùng hiểu chuyện gì đang xảy ra, còn đội kỹ thuật có đủ thông tin để sửa. Một lỗi thường gặp là gom mọi trường hợp vào một thông báo chung chung như “Có lỗi xảy ra, vui lòng thử lại”. Câu này đôi khi chấp nhận được, nhưng nếu dùng cho mọi tình huống thì rất thiếu hữu ích. Người dùng không biết có nên nhập lại, chờ thêm, tải lại trang, hay liên hệ hỗ trợ. Nên phân loại lỗi ngay từ đầu Có thể chia lỗi thành vài nhóm thực tế: - Lỗi nhập liệu: email sai định dạng, mật khẩu quá ngắn, thiếu trường bắt buộc. Loại này nên hiển thị gần ô nhập tương ứng. - Lỗi xác thực/phân quyền: chưa đăng nhập, phiên đăng nhập hết hạn, không có quyền truy cập. Nên hướng người dùng đăng nhập lại hoặc quay về khu vực phù hợp. - Lỗi mạng hoặc timeout: thiết bị mất kết nối, server phản hồi quá lâu. Nên cho phép thử lại. - Lỗi nghiệp vụ: mã giảm giá hết hạn, sản phẩm đã hết hàng, số dư không đủ. Thông báo cần rõ lý do và bước tiếp theo. - Lỗi hệ thống: server lỗi, dịch vụ phụ thuộc bị lỗi. Nên xin lỗi ngắn gọn, tránh lộ chi tiết kỹ thuật, đồng thời ghi log đầy đủ. Ví dụ: khi người dùng bấm “Đặt hàng” Thay vì chỉ báo “Đặt hàng thất bại”, có thể xử lý theo từng trường hợp: - Nếu giỏ hàng có sản phẩm vừa hết hàng: “Sản phẩm A hiện đã hết hàng. Vui lòng xoá sản phẩm này hoặc chọn sản phẩm khác.” - Nếu địa chỉ giao hàng thiếu số điện thoại: “Vui lòng bổ sung số điện thoại nhận hàng.” - Nếu thanh toán qua cổng bên ngoài thất bại: “Thanh toán chưa hoàn tất. Bạn có thể thử lại hoặc chọn phương thức thanh toán khác.” - Nếu server lỗi không xác định: “Chúng tôi chưa thể tạo đơn hàng lúc này. Vui lòng thử lại sau ít phút.” Những thông báo này giúp người dùng biết phải làm gì, giảm số lượt liên hệ hỗ trợ và giảm cảm giác khó chịu. Thiết kế phản hồi lỗi ở giao diện Một số lời khuyên có thể áp dụng ngay: - Đặt thông báo lỗi gần nơi phát sinh lỗi. Lỗi của ô email nên nằm gần ô email, không nên chỉ hiện ở đầu trang. - Giữ nội dung ngắn, rõ, tránh đổ lỗi cho người dùng. Nên viết “Mật khẩu cần ít nhất 8 ký tự” thay vì “Bạn nhập mật khẩu không hợp lệ”. - Với thao tác quan trọng, đừng để người dùng bấm nhiều lần trong lúc đang xử lý. Hãy disable nút và hiển thị trạng thái loading. - Cho phép thử lại với lỗi tạm thời như timeout, mất mạng, API 503. - Không hiển thị stack trace, tên bảng database, query hoặc thông tin nội bộ ra frontend. Chuẩn hóa lỗi từ backend Backend nên trả lỗi có cấu trúc nhất quán. Ví dụ một phản hồi lỗi có thể gồm: mã lỗi nội bộ, thông điệp phù hợp cho người dùng, chi tiết theo từng trường, và request id để tra cứu log. Frontend không nên phải đoán lỗi bằng cách đọc chuỗi thông báo tuỳ tiện. Ví dụ về tư duy thiết kế: backend trả mã “COUPON_EXPIRED”, frontend hiển thị “Mã giảm giá đã hết hạn”. Nếu sau này muốn đổi câu chữ, frontend có thể xử lý theo mã lỗi mà không phụ thuộc vào text từ server. Đừng quên trạng thái rỗng và trạng thái phục hồi Xử lý lỗi không chỉ là hiện hộp thoại màu đỏ. Một app tốt cần nghĩ đến cách phục hồi: - Mất mạng: lưu nháp cục bộ nếu người dùng đang nhập biểu mẫu dài. - Upload thất bại: cho phép upload lại file đó, không bắt chọn lại từ đầu nếu có thể. - Danh sách tải lỗi: giữ dữ liệu cũ trên màn hình nếu phù hợp, kèm nút “Thử lại”. - Form submit lỗi: không xoá dữ liệu người dùng đã nhập. Kết luận Xử lý lỗi tốt là một phần của trải nghiệm sản phẩm, không chỉ là việc kỹ thuật. Một hệ thống trưởng thành nên có phân loại lỗi rõ ràng, thông báo dễ hiểu, cơ chế thử lại hợp lý, log đủ để điều tra và tuyệt đối không làm người dùng mất công vô ích. Nếu đang phát triển một tính năng mới, hãy tự hỏi: “Khi API này lỗi, người dùng sẽ thấy gì và họ có biết bước tiếp theo là gì không?” Câu hỏi đơn giản này thường giúp tránh rất nhiều trải nghiệm tệ sau khi sản phẩm đi vào sử dụng.