Reconfigurar uma exceção apenas porque você decidiu registrá-la usando um bloco catch (o que significa que a exceção não foi alterada) é uma má idéia.
Uma das razões pelas quais usamos exceções, mensagens de exceção e seu tratamento é para que saibamos o que deu errado e as exceções escritas com inteligência podem acelerar a localização do bug por uma grande margem.
Lembre-se também de que lidar com exceções custa muito mais recursos do que, digamos, ter if
, portanto, você não deve lidar com todos com frequência, apenas porque lhe apetecer. Isso afeta o desempenho do seu aplicativo.
No entanto, é uma boa abordagem usar a exceção como um meio para marcar a camada de aplicativo na qual o erro apareceu.
Considere o seguinte código semi-pseudo:
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
}
}
Vamos supor que alguém tenha chamado GetNumberAndReturnCode
e recebido o 500
código, sinalizando um erro. Ele ligaria para o suporte, que abriria o arquivo de log e veria isso:
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
O desenvolvedor então sabe imediatamente qual camada do software interrompeu o processo e tem uma maneira fácil de identificar o problema. Nesse caso, é crítico, porque o tempo limite do Redis nunca deve ocorrer.
Talvez outro usuário chame o mesmo método, também receba o 500
código, mas o log mostre o seguinte:
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.
Nesse caso, o suporte pode simplesmente responder ao usuário que a solicitação é inválida porque ele está solicitando um valor para um ID inexistente.
Sumário
Se você estiver lidando com exceções, certifique-se de lidar com elas da maneira correta. Verifique também se suas exceções incluem os dados / mensagens corretos, seguindo as camadas da arquitetura, para que as mensagens o ajudem a identificar um problema que possa ocorrer.