Memikirkan kembali pengecualian hanya karena Anda memutuskan untuk mencatatnya menggunakan blok tangkap (artinya pengecualian tidak berubah sama sekali) adalah ide yang buruk.
Salah satu alasan kami menggunakan pengecualian, pesan pengecualian dan penanganannya adalah agar kami tahu apa yang salah dan pengecualian yang ditulis dengan cerdik dapat mempercepat menemukan bug dengan margin yang besar.
Juga ingat, menangani pengecualian membutuhkan sumber daya yang jauh lebih banyak daripada katakan saja if
, jadi Anda tidak boleh menangani semuanya terlalu sering hanya karena Anda menginginkannya. Ini berdampak pada kinerja aplikasi Anda.
Namun pendekatan yang baik untuk menggunakan pengecualian sebagai cara untuk menandai lapisan aplikasi di mana kesalahan muncul.
Pertimbangkan kode semi-pseudo berikut:
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
}
}
Mari kita asumsikan seseorang telah memanggil GetNumberAndReturnCode
dan menerima 500
kode, menandakan kesalahan. Dia akan memanggil dukungan, siapa yang akan membuka file log dan melihat ini:
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
Pengembang kemudian segera mengetahui lapisan perangkat lunak mana yang menyebabkan proses untuk dibatalkan dan memiliki cara mudah untuk mengidentifikasi masalah. Dalam hal ini sangat penting, karena Redis tidak boleh mundur.
Mungkin pengguna lain akan memanggil metode yang sama, juga menerima 500
kode, tetapi log akan menunjukkan yang berikut:
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.
Dalam hal ini dukungan hanya dapat menanggapi pengguna bahwa permintaan itu tidak valid karena ia meminta nilai untuk ID yang tidak ada.
Ringkasan
Jika Anda menangani pengecualian, pastikan untuk menanganinya dengan cara yang benar. Pastikan juga pengecualian Anda menyertakan data / pesan yang benar di tempat pertama, mengikuti lapisan arsitektur Anda, sehingga pesan akan membantu Anda mengidentifikasi masalah yang mungkin terjadi.