Không chỉ là ngoại lệ!

Xuất phát điểm của mình là C/C++ và công việc lập trình đầu tiên của mình cũng là lập trình C/C++ với Cocos2dx trong một năm rưỡi. Khoảng thời gian đó đã giúp mình tích luỹ được rất nhiều kiến thức liên quan đến việc làm game, quản lý bộ nhớ, con trỏ, xử lý logic và designpattern.

Ngày đó khi xử lý logic thật vất vả, để mà biết được 1 lệnh được gọi qua những lớp nào, hàm nào là cứ phải thêm cả 1 lô 1 lốc các dòng log kiểu:

CCLOGINFO("user click to button");
CCLOGINFO("start moving character");
CCLOGINFO("sync character position");

Nếu không có những dòng log quý báu này thì đến khi có lỗi xảy ra thì không biết đâu mà lần, có khi chịu bó tay, mòn mỏi đi tái hiện lại bug, nhưng cũng may mà luồng dữ liệu ở client nó cũng đơn giản nên cũng dễ debug.

Khi có Exception

Nhưng sau này, trở lại với Java mọi thứ đã thay đổi, chúng ta đã có Exception. Exception không chỉ đơn thuần là việc chúng ta ném ra khi xảy ra một lỗi mà nó còn giúp chúng ta thu thập stacktrace, nghĩa là nó ghi lại cả quá trình một lệnh được gọi cho đến khi chúng ta throw Exception. Và khi chúng ta sử dụng các log engine như logback hay log4j12 nó sẽ giúp chúng ta in ra đầy đủ danh sách các lớp, các hàm và ở dòng bao nhiêu lệnh được gọi. Điều này cực kì hữu ích khi có 1 lỗi xảy ra, nó giúp chúng ta nhanh chóng phán đoán tình huống và đưa ra phương án xử lý kịp thời.

Tất nhiên được cái lọ thì mất cái chai, khi xử dụng Exception thì chúng ta cũng phải trả chi phí #performace để Exception đi thu thập #stacktrace từ #stack của #Thread đang thực thi, nhưng nó vẫn quá rẻ cho chi phí phát triển và vận hành phần mềm, thêm vào nữa là tỉ lệ lỗi xảy ra so với các case hoạt động bình thường là rất thấp, nên đừng lo lắng về hiệu năng nhé mọi người.

Ứng dụng trong thực tế

Một ví dụ đơn giản khi chúng ta cần kiểm tra email của khách hàng:

public static void validateEmail(String email) {
    if(!Pattern.compile("^(.+)@(.+)$").matcher(email).matches()) {
        throw new IllegalArgumentException("invalid email: " + email);
    }
}
// main
try {
    validateEmail("dzung@youngmonkeys.org");
    validateEmail("dzung");
}
catch (Exception e) {
    logger.error("validate email failed", e);
}

Nhưng hãy cẩn thận!

Trong message của exception sẽ chứa thông tin khi ném ra exception, chẳng hạn khi bạn ném:

throw new IllegalArgumentException("invalid email: " + email);

Thì các log engine sẽ in ra.

2021-04-28 12:08:30 ERROR ExceptionExample:22 - validate email failed
java.lang.IllegalArgumentException: invalid email: dzung
 at com.tvd12.example.exceptionhandler.ExceptionExample.validateEmail(ExceptionExample.java:11)
 at com.tvd12.example.exceptionhandler.ExceptionExample.main(ExceptionExample.java:19)

Bạn có thể thấy nó có chứa thông tin nhạy cảm là email của khách hàng, nên hãy cân nhắc cẩn thận việc đưa các thông tin vào message nhé.

Tổng kết

Exception là một thành phần vô cùng quan trọng, nó sẽ giúp chúng ta tiết kiệm được rất nhiều thời gian và công sức để phát triển và #maintain hệ thống, đừng vì một chút hiệu năng mà đắn đo. Nếu ngôn ngữ bạn đang sử dụng như #Csharp hay #Kotlin hay bất kì ngôn ngữ nào khác có hỗ trợ Exception, hãy sử dụng nó và bạn sẽ thấy dễ thở hơn rất nhiều đấy.

Exception là một chủ đề hay, và cần thực hành trong một thời gian dài mới có thể hiểu hết được, cá nhân mình cũng phải mất một thời gian dài mới hiểu hết được Exception nó là cái gì, tại sao lại sinh ra nó, làm sao để sử dụng nó, nên mình sẽ có thêm những bài viết khác để mô tả việc sử dụng Exception ở level cao nhất nhé, 🙂

Tham khảo

  1. Wiki
  2. Ví dụ trong bài