一般的なアプリケーションでは、例外が発生すると大きく2つの選択を迫られる。
1つ目は、例外を再上位まで伝播させる方法。try-catchを極力書かず、全ての例外を最上位まで伝播させる。コードは綺麗になるだろう。 ログ、通知、監視も一箇所に集約できる、ある種理想的な構成だ。
しかし、その方法では局所的な復旧が出来ない。異常系はアプリケーションが停止するか、エンドポイントに到達するまで継続してしまう。正常系に戻さなければならない要件と衝突することもある。そのため、多くの業務システムでは各所で例外を捕捉する方法が取られる。try-catchによる居所的復旧、場当たり的な回復手段だ。
当然ながら、その場合「ログを残す」 「メトリクスを送る」 「通知する」 「監査証跡を残す」といった、本来の業務処理とは関係のない責務をcatchブロックに忘れずに網羅する必要がある。処理内容をストラテジーパターン等で集約したとして、それを「呼び出す」責任からは逃れられない。
誰かが処理を書くことを忘れる可能性もあれば、メッセージのIDを打ち間違える可能性もある。万一テストをすり抜ければ障害の特定を困難にする。
つまり従来の例外処理は、この横断的関心事へのアプローチが適切でない。
さて、では適切なアプローチとは何だろうか。
結論から言えば、例外によるアプリケーションイベント(.NETならFirstChanceException)を引き金に、主たる処理とは全く別の処理経路を並列・非同期で用意するのが一つの解だ。
参考実装および.NETライブラリを用意したので、ぜひ試してみてほしい。