Lấy lại một ngoại lệ chỉ vì bạn đã quyết định đăng nhập nó bằng cách sử dụng một khối bắt (có nghĩa là ngoại lệ không thay đổi chút nào) là một ý tưởng tồi.
Một trong những lý do chúng tôi sử dụng các ngoại lệ, thông báo ngoại lệ và cách xử lý của nó là để chúng tôi biết những gì đã sai và các ngoại lệ được viết khéo léo có thể tăng tốc độ tìm ra lỗi bằng một biên độ lớn.
Cũng cần nhớ rằng, việc xử lý các trường hợp ngoại lệ tốn nhiều tài nguyên hơn so với giả sử if
, vì vậy bạn không nên xử lý tất cả chúng thường chỉ vì bạn cảm thấy như vậy. Nó có tác động đến hiệu suất của ứng dụng của bạn.
Tuy nhiên, đó là cách tiếp cận tốt để sử dụng ngoại lệ như một phương tiện để đánh dấu lớp ứng dụng trong đó lỗi xuất hiện.
Hãy xem xét mã bán giả sau đây:
interface ICache<T, U>
{
T GetValueByKey(U key); // may throw an CacheException
}
class FileCache<T, U> : ICache<T, U>
{
T GetValueByKey(U key)
{
throw new CacheException("Could not retrieve object from FileCache::getvalueByKey. The File could not be opened. Key: " + key);
}
}
class RedisCache<T, U> : ICache<T, U>
{
T GetValueByKey(U key)
{
throw new CacheException("Could not retrieve object from RedisCache::getvalueByKey. Failed connecting to Redis server. Redis server timed out. Key: " + key);
}
}
class CacheableInt
{
ICache<int, int> cache;
ILogger logger;
public CacheableInt(ICache<int, int> cache, ILogger logger)
{
this.cache = cache;
this.logger = logger;
}
public int GetNumber(int key) // may throw service exception
{
int result;
try {
result = this.cache.GetValueByKey(key);
} catch (Exception e) {
this.logger.Error(e);
throw new ServiceException("CacheableInt::GetNumber failed, because the cache layer could not respond to request. Key: " + key);
}
return result;
}
}
class CacheableIntService
{
CacheableInt cacheableInt;
ILogger logger;
CacheableInt(CacheableInt cacheableInt, ILogger logger)
{
this.cacheableInt = cacheableInt;
this.logger = logger;
}
int GetNumberAndReturnCode(int key)
{
int number;
try {
number = this.cacheableInt.GetNumber(key);
} catch (Exception e) {
this.logger.Error(e);
return 500; // error code
}
return 200; // ok code
}
}
Giả sử ai đó đã gọi GetNumberAndReturnCode
và nhận 500
mã, báo hiệu lỗi. Anh ta sẽ gọi cho bộ phận hỗ trợ, người sẽ mở tệp nhật ký và thấy điều này:
ERROR: 12:23:27 - Could not retrieve object from RedisCache::getvalueByKey. Failed connecting to Redis server. Redis server timed out. Key: 28
ERROR: 12:23:27 - CacheableInt::GetNumber failed, because the cache layer could not respond to request. Key: 28
Sau đó, nhà phát triển biết ngay lớp phần mềm nào đã khiến quá trình hủy bỏ và có một cách dễ dàng để xác định vấn đề. Trong trường hợp này là rất quan trọng, vì Redis hết thời gian nên không bao giờ xảy ra.
Có lẽ một người dùng khác sẽ gọi phương thức tương tự, cũng nhận được 500
mã, nhưng nhật ký sẽ hiển thị như sau:
INFO: 11:11:11- Could not retrieve object from RedisCache::getvalueByKey. Value does not exist for the key 28.
INFO: 11:11:11- CacheableInt::GetNumber failed, because the cache layer could not find any data for the key 28.
Trong trường hợp đó, bộ phận hỗ trợ có thể trả lời đơn giản cho người dùng rằng yêu cầu không hợp lệ vì anh ta đang yêu cầu một giá trị cho ID không tồn tại.
Tóm lược
Nếu bạn đang xử lý các trường hợp ngoại lệ, hãy đảm bảo xử lý chúng theo cách chính xác. Ngoài ra, hãy đảm bảo các ngoại lệ của bạn bao gồm dữ liệu / tin nhắn chính xác ở vị trí đầu tiên, theo sau các lớp kiến trúc của bạn, vì vậy các thông báo sẽ giúp bạn xác định một vấn đề có thể xảy ra.