Renvoyer une exception uniquement parce que vous avez décidé de l'enregistrer à l'aide d'un bloc catch (ce qui signifie que l'exception n'a pas changé du tout) est une mauvaise idée.
L'une des raisons pour lesquelles nous utilisons les exceptions, les messages d'exceptions et leur gestion est pour que nous sachions ce qui s'est mal passé et les exceptions intelligemment écrites peuvent accélérer la recherche du bogue par une grande marge.
Rappelez-vous également que la gestion des exceptions coûte beaucoup plus de ressources que disons une if
, donc vous ne devriez pas toutes les gérer trop souvent simplement parce que vous en avez envie. Cela a un impact sur les performances de votre application.
Il est toutefois judicieux d'utiliser l'exception comme moyen de marquer la couche d'application dans laquelle l'erreur est apparue.
Considérez le semi-pseudo-code suivant:
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
}
}
Supposons que quelqu'un ait appelé GetNumberAndReturnCode
et reçu le 500
code, signalant une erreur. Il appelait le support, qui ouvrait le fichier journal et voyait ceci:
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
Le développeur sait alors immédiatement quelle couche du logiciel a provoqué l'abandon du processus et a un moyen facile d'identifier le problème. Dans ce cas, c'est critique, car le délai d'expiration de Redis ne devrait jamais arriver.
Peut-être qu'un autre utilisateur appellerait la même méthode, recevrait également le 500
code, mais le journal afficherait ce qui suit:
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.
Dans ce cas, le support pourrait simplement répondre à l'utilisateur que la demande n'était pas valide car il demande une valeur pour un ID inexistant.
Sommaire
Si vous gérez des exceptions, assurez-vous de les gérer correctement. Assurez-vous également que vos exceptions incluent les données / messages corrects en premier lieu, en suivant vos couches d'architecture, afin que les messages vous aident à identifier un problème qui peut se produire.