Bàn luận về Exception và Custom Exception
Xin chào các anh hùng hảo hán gần xa. Mình là một thằng Dev vô danh tiểu tốt.
Hôm nay mình xin (múa rìu qua mắt thợ) cùng mọi người bàn một chút về Custom Exception nói chung trong các ngôn ngữ lập trình. Mọi sai sót mong các anh hùng giơ thấp đánh khẽ.
Exception nói chung là một thế lực đông đảo và đáng sợ, dù chưa bằng hội “Thánh Đức Chúa Bug” (và trẻ trâu). Nó thể xuất hiện ở khắp mọi nơi và trong bất kỳ thời điểm nào. Nó thậm chỉ có thể xuất hiện trên đường về nhà, trong tolet, cả trên giường và trong các hoạt động giao lưu kết hợp thể dục thể thao.
Mọi chương trình nói chung đều (gần như) sẽ xảy ra các “ngoại lệ” không mong muốn, làm ngừng lại sự sung sướng của chúng ta.Vào khoảnh khắc thay vì xuất ra “kết quả”, thì sự sung sướng nó lại xuất ra Exception.
I. Ý Tưởng
Exception xuất hiện ở khắp mọi nẻo đường, nhưng mình quan tâm nhất là về việc quản lý nó trong mô hình 3 lớp.
Đầu tiên ta nói về mô hình 3 lớp. Trong đó mình đọc về một ý tưởng là:
"Một khi gặp lỗi (các trường hợp không đúng dữ liệu) thì đang ở layer nào thì quăng lên trên layer cao hơn nó 1 bậc cho tới GUI thì sẽ quăng ra cho người dùng biết "
Source
Vấn đề là mình quăng rất nhiều loại lỗi, nhưng lớp Exception mặc định không thể hiện được hết các lỗi đó (VD IOException, SQLException, FormatException…).
Làm sao các Layer phía trên nó biết sẽ catch ra được loại Exception gì để mà xử lý cho phù hợp.
Đầu tiên mình nghĩ đến Custom Exception.
II. Cở Sở
Các ngôn ngữ lập trình cấp cao (có lẽ) hầu hết đều cho phép người dùng tự định nghĩa các Custom Exeption. Các Custom Exception này thừa kế từ lớp cha là Exception, nó giúp chúng ta tạo ra các Exception mới dùng cho mục đích xác định lỗi văng ra là gì, từ đó xác địch nguyên nhân lỗi để xử lý.
Ví dụ như java
package com.mkyong.examples.exception;
public class NameNotFoundException extends Exception {
public NameNotFoundException(String message) {
super(message);
}
}
Source
Dựa vào ý tưởng và cơ sở trên, mình lên kế hoạch xây dựng các Custom Exception cần thiết cho nhu cầu bắt Exception để xử lý trước khi sử dụng hạ sách cuối cùng (trong nhiều trường hợp) là show messenge cho người dùng xem để họ tự xử lý.
III. Ví dụ về ứng dụng.
Mình thử xây dựng một class có method throws nhiều kiểu Custom Exception
static class FirstException extends Exception { }
static class SecondException extends Exception { }
public void rethrowException(String exceptionName) throws Exception {
try {
if (exceptionName.equals("First")) {
throw new FirstException();
} else {
throw new SecondException();
}
} catch (Exception e) {
throw e;
}
}
Source
Sử dụng try catch để bắt Exception
Kết luận:
Áp dụng Custom Exception vào mô hình 3 lớp ở trên, mình có thể kiểm soát được tốt hơn các lỗi có thể xảy ra cũng như có biện pháp quởn với nó hiệu quả.
Nhưng liệu còn có những cách khác hay ho và xinh đẹp hơn để xử lý việc quăng lỗi lên Layer trên.
Hay là những ứng dụng khác của Custom Exception.
Xin phép mời các bằng hữu đồng râm gần xa cùng ngồi xuống uống miếng nước, ăn miếng bánh rồi cùng bàn luận.
Nguồn tham khảo:
mkyong.com
o7planning.org
docs.oracle.com
Đọc mãi mà chưa hiểu cái CustomException này để làm gì a?
Btw, ngoài ra khi throws một exception lên các lớp trên, không hẳn các lớp trên sẽ không biết Exception gì. Nên nhớ là mặc dù catch(Exception ex) thì cái ex này vẫn là instance của lỗi được quăng ra.
Vd: ở lớp dưới quăng lên NullPointerException thì ở lớp trên mặc dù là catch(Exception ex) nhưng ex lúc này vẫn là NullPointerException khi runtime. Nên check name class cũng không khác gì getClass().
Ngoài ra có rất nhiều công việc phải làm khi exception quăng ra, đặc biệt là các transaction process, nên dù là Custom đi nữa thì vẫn phải viết lại phần xử lý khi có exception quăng ra, mà việc xử lý này lại tuỳ thuộc vào business nó đang xử lý.
Khi truyền error giữa các boundary context thì nên wrap error lại trong Interface trước khi truyền ra ngoài boundary.
Trong Java, boundary context là layer, error là exception, wrap error là nested exception - một trong các cách rethrow.
Bạn có thể search từ khoá là Domain Driven Design để biết thêm chi tiết
Custom Exception mình có ghi rõ là định nghĩa 1 loại Exeption mới để lớp trên khi catch sẽ biết là nó catch được lỗi gì (vì nguyên nhân gì) nha. Bình thường quăng ra Exception ex không thì chỉ biết in ra chứ chẳng làm gì được