Das erneute Auslösen einer Ausnahme nur, weil Sie beschlossen haben, sie mit einem catch-Block zu protokollieren (was bedeutet, dass sich die Ausnahme überhaupt nicht geändert hat), ist eine schlechte Idee.
Einer der Gründe, warum wir Ausnahmen, Ausnahmemeldungen und deren Behandlung verwenden, ist, dass wir wissen, was schief gelaufen ist, und dass geschickt geschriebene Ausnahmen das Auffinden des Fehlers erheblich beschleunigen können.
Denken Sie auch daran, dass das Behandeln von Ausnahmen weitaus mehr Ressourcen kostet, als wir vielleicht haben. if
Sie sollten sie also nicht allzu oft behandeln, nur weil Sie Lust dazu haben. Dies hat Auswirkungen auf die Leistung Ihrer Anwendung.
Es ist jedoch ein guter Ansatz, Ausnahme als Mittelwert zu verwenden, um die Anwendungsschicht zu markieren, in der der Fehler aufgetreten ist.
Betrachten Sie den folgenden Halbpseudocode:
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
}
}
Nehmen wir an, jemand hat den angerufen GetNumberAndReturnCode
und den 500
Code erhalten, was auf einen Fehler hinweist . Er würde den Support anrufen, der die Protokolldatei öffnen und Folgendes sehen würde:
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
Der Entwickler weiß dann sofort, auf welcher Ebene der Software der Prozess abgebrochen wurde, und kann das Problem auf einfache Weise identifizieren. In diesem Fall ist es wichtig, da Redis Timeout niemals eintreten sollte.
Möglicherweise würde ein anderer Benutzer dieselbe Methode aufrufen und auch den 500
Code erhalten, das Protokoll würde jedoch Folgendes anzeigen :
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.
In diesem Fall kann der Support dem Benutzer einfach antworten, dass die Anforderung ungültig ist, weil er einen Wert für eine nicht vorhandene ID anfordert.
Zusammenfassung
Wenn Sie mit Ausnahmen umgehen, stellen Sie sicher, dass Sie sie richtig behandeln. Stellen Sie außerdem sicher, dass Ihre Ausnahmen in erster Linie die richtigen Daten / Nachrichten enthalten, die Ihren Architekturebenen folgen, damit Sie anhand der Nachrichten ein Problem identifizieren können, das möglicherweise auftritt.