例外ハンドリング周りによく悩むので、改めて考え直してみた
ちなみに、例外とエラーは置き換え可能として、区別せず、
try-catch形式を想定してます
全体のイメージ
イメージとしてはこんな感じ
利用者やアプリケーションは、
APIサーバなのか、Web/スマホアプリなのかによって変わるけど、
- アプリケーション ... 作った部分
- 利用者 ... アプリケーションを使うユーザやシステム
- 外部システム ... アプリケーションが利用してる部分
- 実行環境 ... アプリケーションを動かしてる部分
というイメージ
例外のいろんな分類
例外の分類には色んなバリエーションがあるっぽい
組み合わせ的な感じで、
- 業務例外 x 回復可
- 業務例外 x 回復不可
- システム例外 x 回復可
- システム例外 x 回復不可
- システム例外 x 致命的なエラー
のような感じのバリエーションが多い印象
業務例外とシステム例外はどこからくるか
大分類としては、業務例外とシステム例外だけど、 それぞれ色んな場所から発生するイメージ
- アプリの業務ロジック ... 業務例外
- アプリのそれ以外 ... システム例外
- DB
- 業務例外 ... 一意性制約違反など
- システム例外 ... DBダウンなど
- API
- 業務例外 ... 400エラーなど
- システム例外 ... 500エラーなど
どちらも発生する部分は、どう振り分けるかは各々で検討が必要
例外を利用者にどう伝えるか
それぞれでざっくりしたパターンとしては、以下のイメージ 例外が起こった時の挙動は基本プレゼンテーション層/上位層でを決める
- 業務例外 x 回復可
- 利用者にメッセージを表示し、修正&やり直してもらう
- 業務例外 x 回復不可
- 利用者にメッセージを表示する
- システム例外 x 回復可
- アプリ側でリトライし、だめなら利用者にメッセージを表示する
- システム例外 x 回復不可
- 利用者にメッセージを表示する
- システム例外 x 致命的なエラー
- 異常終了する
カスタム例外クラスの階層構造
大枠は3つが識別できれば十分かも
- AppException ... 最上位の例外クラス
- AppLogicException ... 業務例外
- メッセージを表示する
- AppSytemException ... システム例外
- 必要ならリトライし、それでもだめならメッセージを表示
- AppFatalException ... 致命的なエラー
- 異常終了するなど
- AppLogicException ... 業務例外
あとは各々階層化やサブクラスを増やしていく感じ
外部システムの例外をどう扱うか
- DBやORMの例外
- APIのエラーレスポンス
など、SDKやライブラリなどサードパーティの例外を そのまま使ってしまうこともあるがよくない
エセDDDっぽく書くと、こんな感じだと思うけど、
用意したカスタム例外クラスにwarpしてから、 ロジック内で扱う形がよい(インフラ層で吸収する形)
また、デバッグするときに、元の例外やスタックトレースが失われないよう、 カスタム例外クラスに引き継ぐことも大事
以上!ざっくりだけど、だいぶ整理できてきた気がする(*´ω`*)
このあたりの本も参考になった!!
ソフトウェア設計のトレードオフと誤り ―プログラミングの際により良い選択をするには Tomasz Lelek
Good Code Bad ~持続可能な開発のためのソフトウェアエンジニア的思考
達人プログラマー 第2版 熟達に向けたあなたの旅 David Thomas
おまけ: エラーレスポンス形式の標準仕様
Problem JSON
{ "type": "https://example.com/probs/cant-view-account-details", "title": "Not authorized to view account details", "status": 401, "detail": "Due to privacy concerns you are not allowed to view account details of others. Only users with the role administrator are allowed to do this.", "instance": "/account/123456/details" }
参考にしたサイト様
- ちょっと広く例外を学んでみた #error - Qiita
- 例外の設計指針~歴史と分類とトレンド #初心者向け - Qiita
- 【ソフトウェア設計】例外処理を考える
- 例外のデザインのガイドライン - Framework Design Guidelines | Microsoft Learn
- 例外とエラーの違い #プログラミング - Qiita
- その例外、いつキャッチするの?
- 5.7. 例外ハンドリング — TERASOLUNA Global Framework Development Guideline 1.0.0.publicreview documentation
- (1) ビジネス例外 ... ビジネスルールの違反を検知したことを通知する例外
- (2) 正常稼働時に発生するライブラリ例外 ... フレームワーク、およびライブラリ内で発生する例外のうち、システムが、正常稼働している時に発生する可能性のある例外
- (3) システム例外 ...システムが、正常稼働している時に、発生してはいけない状態を検知したことを通知する例外
- (4) 予期しないシステム例外 ... システムが、正常稼働している時には発生しない非検査例外
- (5) 致命的なエラー ... システム(アプリケーション)全体に影響を及ぼす、致命的な問題が発生していることを通知するエラー
- (6) リクエスト不正時に発生するフレームワーク例外 ... フレームワークが、リクエスト内容の不正を検知したことを通知する例外