catchブロックを使用してログに記録することを決定した(例外がまったく変更されていないことを意味する)ためだけに例外を再スローすることは、悪い考えです。
例外、例外メッセージ、およびその処理を使用する理由の1つは、何が悪かったのか、巧妙に書かれた例外を知って、バグの発見を大幅にスピードアップできるようにするためです。
また、例外を処理するとif
、たとえばを持っているよりも多くのリソースが必要になるので、気が付いたという理由だけで例外をすべて処理することは避けてください。アプリケーションのパフォーマンスに影響を与えます。
ただし、エラーが発生したアプリケーション層をマークする手段として例外を使用することは良いアプローチです。
次の準擬似コードを検討してください。
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
}
}
誰かがコードを呼び出しGetNumberAndReturnCode
て500
コードを受け取り、エラーを通知したと仮定しましょう。彼はサポートに電話し、ログファイルを開いてこれを確認します。
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
その後、開発者は、ソフトウェアのどの層がプロセスを中断させたかをすぐに把握し、問題を簡単に特定できます。この場合、Redisのタイムアウトが発生することはないため、重要です。
別のユーザーが同じメソッドを呼び出して500
コードを受け取ることもありますが、ログには次のように表示されます。
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.
この場合、サポートはユーザーが存在しないIDの値を要求しているため、要求が無効であるとユーザーに単純に応答できます。
概要
例外を処理している場合は、必ず正しい方法で処理してください。また、例外には、アーキテクチャレイヤーに続く正しいデータ/メッセージが含まれていることを確認してください。メッセージは、発生する可能性のある問題を特定するのに役立ちます。