# 21: Phân biệt Business exception và Technical exception

(Exception không phải là lỗi, nó là những vấn đề xảy ra một cách ngẫu nhiên không được trông đợi trước, ví dụ như khách hàng cố gắng chuyển tiền trong khi không còn đồng nào trong tài khoản ngân hàng)

Có hai lý do cơ bản dẫn đến việc bị exception khi đang runtime (runtime là từ chỉ khoảng thời than chương trình đang biên dịch): đó là lý do kĩ thuật xuất phát từ những dòng code trong ứng dụng của bạn, thường những lỗi này sẽ khiến chương trình bị đứng và không chạy nữa, và lý do về business logic thường xuất phát từ phía người dùng như là dùng sai các chức năng trong ứng dụng. Và trong hầu hết các ngôn ngữ hiện đại ngày nay như là LISP, Java, SmalltalkC#, những ngôn ngữ này dùng exception để thông báo khi có lỗi xảy ra từ hai vấn nhiên, bởi vì hai lý do trên rất khác biệt với nhau, vì vậy chúng ta nên xử lý thật cẩn thận từng vấn đề riêng lẽ với nhau.

Như các bạn biết, một thông báo lỗi sẽ xuất hiện khi chương trình phát hiện một lỗi nào đó khi đang biên dịch. Ví dụ như, nếu bạn truy cập phần tử thứ 83 từ một mảng chỉ có 17 phần từ, khi đó chắc chắc chương trình sẽ dừng lại và một vài exception sẽ được thông báo ra màn hình. Đôi khi, bạn sử dụng thư viện bên ngoài và chúng sẽ gọi những đối số nghịch nhau từ chính những thư viện ấy, và đó là nguyên nhân xảy ra lỗi ngay bên trong thư viện bạn gọi vào.

Và đừng bao giờ cố tự mình giải quyết tất cả những exception này. Thay vào đó chúng ta sẽ để những exception này ở những mức thông báo cao nhất và hãy chắc rằng hệ thống vẫn ở trạng thái an toàn. Ví dụ như quay ngược lại một phiên làm việc, hay là gửi thông báo tới adminnistrator hoặc là gửi báo cáo ngược lại cho user.

Một biến thể khác của trường hợp này được gọi là library situation, và một caller đã làm hỏng contract method (các bạn có thể tìm hiểu thêm với từ khóa ‘contract programming’) ví dụ như khiến cho chương trình gửi đi những argument lạ hoặc tồn tại những đối tượng không được định nghĩa rõ ràng. Ví dụ sẽ có một đoạn text khi bạn cố truy cập phần tử thứ 83 từ mảng có 17 phần tử từ ví dụ trên như sau: ‘the caller should have checked’. Rõ ràng đây không phải là một lỗi từ phía client, mà thường là chúng ta sẽ thrown ra một technical exception.

Một tình huống khác, nhưng vẫn thuộc về technical exception, tình huống khi mà một chương trình nào đó có nảy sinh vấn đề trong môi trường thực thi, ví dụ như database không phản hồi. Trong trường hợp này, bạn phải giả sử rằng các thành phần trong chương trình đã làm mọi thứ để xử lý exception này — ví dụ như repair lại kết nối giữa client và sẻver một số lần hữu hạn — và vẫn thất bại. Thậm chí có cả những nguyên nhân gây ra lỗi khác thì tình huống bạn mắc phải vẫn tương tự nhau: thật ra chúng ta không làm được gì nhiều về việc này. Vì thế, chúng ta gửi những vấn đề phát sinh này thông qua những exception và xử lý chúng.

Ngược lại, chúng ta có tình huống không thể hoàn thành một caller bởi những lý do về domain-logical. Trong trường hợp này chúng ta giải quyết những tình huống trên như một exception. Ví dụ, trông những lỗi này kì lạ và khá phiền phức nhưng không mang tính programming như error. Ví dụ như khi bạn rút nhiều tiền hơn số tiền trong tài khoản của bạn. Mặt khác kiểu trường hợp này chỉ là một phần trong contract, và việc thrown ra một exception cũng chỉ là một cách để cảnh báo người dùng. Với những trường hợp như trên thì thường chúng ta sẽ tạo ra những exception đặc biệt hoặc tạo ra những cấp bậc exception khác nhau và để người dùng có thể tự giải quyết các exception này.

Trộn cả hai technical exception và business exception một cách không rõ ràng và lộn xộn là cách mà method contract hoạt động. Có những điều kiện phải được đáp ứng để đảm bảo trước khi gọi (caller), và lường trước những tình huống exception mà có thể sẽ gặp. Phân chia ra những trường hợp như vậy sẽ khiến cho mọi thứ rõ ràng và tăng cơ hội những technical exception được xử lý bởi application framework, trong khi đó business exception sẽ được xử lý bên phía client.