07/09/2018, 09:30

Câu chuyện về exception

Exception là một khái niệm không hề xa lạ với một lập trình viên. Nó là thứ xảy ra hằng ngày hằng giờ. Việc nắm bắt được exception luôn là một thử thách đối với bất cứ ai khi bắt đầu tiếp xúc với lập trình. Và để cho thử thách đó trở nên dễ dàng hơn, mình sẽ đưa nó về những câu chuyện để cho bạn có ...

Exception là một khái niệm không hề xa lạ với một lập trình viên. Nó là thứ xảy ra hằng ngày hằng giờ. Việc nắm bắt được exception luôn là một thử thách đối với bất cứ ai khi bắt đầu tiếp xúc với lập trình. Và để cho thử thách đó trở nên dễ dàng hơn, mình sẽ đưa nó về những câu chuyện để cho bạn có thể hình dung và nhớ được.

Đó là câu chuyện về hai người chở nhau đi trên một chiếc xe. Bỗng từ đâu có một hòn đá bay thẳng đến phía hai người. Hãy tưởng tượng trong tình huống này hòn đá chính là một exception phát sinh trong chương trình “đạp xe” của bạn. Vậy tình huống nào sẽ xảy ra.

Người lái xe chắn ở phía trước nhận lấy hòn đá ném vào mình nhưng lại chẳng cho người ngồi sau biết. Một cử chỉ cảm động nhưng có vẻ là hơi ngu ngốc. Đến đây bạn đã có thể hình dung exception được xử lý trong trường hợp này chưa (?) Đây là trường hợp handle exception điển hình bằng try...catch. Mọi exception xảy ra khi thực hiện ở try đều được catch và sau đó thì không có gì phát sinh thêm. Ví dụ:

public void doNotIgnoreExceptions() {
	try {
		// do something
	} catch (NumberFormatException e) {
		// don’t do anything
	}
}
  • Ưu điểm: Kiểm soát được các lỗi phát sinh để chương trình luôn available.
  • Nhược điểm: Một hình thức dấu lỗi, những xử lý (ở phương thức khác) khi dùng phương thức đó sẽ không biết được lỗi phát sinh từ đâu và lỗi như thế nào.

Thân mình là trên hết, người ngồi trước thấy đá là né. Người ngồi sau không hiểu chuyện gì xảy ra chỉ thấy đá văng thẳng mặt. Trường hợp này cũng là trường hợp kinh điển khi bạn phát triển một chức năng nào đấy mà có thể phát sinh exception nhưng bạn không muốn giải quyết chúng. Chỉ cần thêm các exception sau từ khóa throws, không phải try...catch gì nữa. Ví dụ:

/**
* This method does something extremely useful ...
*
* @param input
* @throws MyBusinessException if ... happens
*/
public void doSomething(String input) throws MyBusinessException {
	// do something with throw MyBusinessException 
}
  • Ưu điểm: Người lập trình không cần chú ý đến các lỗi phát sinh trong phương thức mình đang xây dựng vì sẽ có người sau đó (cùng những phương thức sau đó) xử lý.
  • Nhược điểm: Nếu lạm dụng, chỉ biết ném exception từ phương thức này sang phương thức khác thì ai sẽ là người giải quyết cuối cùng (?)

Đúng như tên gọi, người lái xe sau khi bị dính đá lại ném nó cho người ngồi sau. Tình cảm thì ném cái mảnh vụn, không tình cảm thì ném nguyên hòn đá đã văng vào mình. Các bạn có thể xem đây là sự kết hợp giữa hai tình huống trên. Bạn vẫn xử lý những exception có thể phát sinh đồng thời thông báo cho người sau biết là cái gì đang xảy ra. Ví dụ:

try {
	new Long("xyz");
} catch (NumberFormatException e) {
	log.error(e);
	throw e;
}

Ở ví dụ trên có thể xem là một cách khôn khéo để xử lý exception. Log error khi nó diễn ra và rethrow để người gọi nó có thể xử lý một cách thích hợp. Tuy nhiên với cùng một exception thì việc xử lý ghi log chẳng hạn sẽ ghi lại cùng một lỗi nhiều lần. Message lặp lại không mang lại bất kì lợi ích nào thậm chí còn gây khó khăn trong việc debug. Vì vậy nếu bạn có ném lại exception thì nên ném lại nó nhè nhẹ thôi. Đừng nên ác ý quá mà ném y nguyên lại cái exception đó cho người sau nhé. Và tất nhiên với ví dụ trên, chúng ta nên chuyển thành như sau:

public void wrapException(String input) throws MyBusinessException {
	try {
		new Long("xyz");
	} catch (NumberFormatException e) {
		throw new MyBusinessException("String can’t input.", e);
	}
}
  • Ưu điểm: Mọi chuyện đều diễn ra tường mình, người lập trình sau cũng nhưng như những phương thức sau đó đều biết chuyện gì đang xảy ra, lỗi phát sinh ở đâu và như thế nào. Các bạn thử nghĩ xem, đã có người đằng trước hứng đá thì người đằng sau hẳn là sẽ chịu ít sát thương hơn rồi. Có khi nó tình cảm quăng hòn đá nhè nhẹ hoặc quăng cho cái mảnh vụn vụn             </div>
            
            <div class=
0