📄
概念 📚 software-design-concepts

エラーハンドリング

例外・Result型・エラー境界を用いた堅牢なエラー処理設計と、エラーの分類・伝播・復旧戦略

エラーハンドリングはシステムの堅牢性を左右するにもかかわらず、設計の後回しにされがちな領域だ。エラーは大きく「予期可能なエラー」と「バグ」に分類できる。前者はバリデーション失敗・リソース不存在・外部APIの一時的な失敗など、ビジネスロジックの一部として扱うべきケースだ。後者はNullPointerExceptionや存在しないプロパティへのアクセスなど、プログラムの誤りに起因し、握りつぶさず表面化させるべきものだ。

例外(Exception)は制御フローを非局所的に変化させるため、呼び出し元が明示的にcatchしなければエラーが見えない。Result型(成功値と失敗値をUnion型で返す)はエラーを型として明示し、呼び出し元がエラー処理を強制される。TypeScriptではネイティブなResult型はないが、Effectライブラリや自前実装で実現できる。どちらが適切かはエラーの性質と伝播距離による判断が必要だ。

エラーバウンダリはエラーの影響範囲を限定するための構造だ。ReactのError Boundaryはコンポーネントツリーのクラッシュを局所化し、他の部分の表示を維持する。バックエンドではミドルウェアやグローバルExceptionHandlerがこの役割を担う。エラーの情報量も重要で、スタックトレース・操作ID・コンテキスト情報を含めたログを残すことで、本番環境でのデバッグが可能になる。ユーザー向けのエラーメッセージは、内部のエラー詳細を漏らさず・かつ次のアクションが分かるものにすべきだ。

コードレビューで着目するポイント

  • エラーを握りつぶしていないか(catch節が空・console.logだけで終わる)
  • 予期可能なエラーと予期できないバグが同じcatch節で処理されていないか
  • エラーの型情報が失われていないか(Error型をanyでキャッチ・再スロー時の情報消失)
  • エラーメッセージにスタックトレースや操作IDなどのデバッグ情報が含まれているか
  • ユーザー向けメッセージに内部エラーの詳細が露出していないか(セキュリティ)
  • Resultやエラー型の伝播先でエラーケースが処理されているか(TypeScriptのnever型等で網羅性チェック)
  • 非同期処理においてPromiseのrejectが適切にハンドリングされているか

典型的なアンチパターン

空のcatch: try { ... } catch (e) {} によってエラーが完全に隠蔽される。実行時に何かが失敗しても誰も気づかず、データの不整合が蓄積してから後でサービス障害として表面化する。

エラーメッセージの情報過多(情報漏洩): Stackトレースやデータベーススキーマの詳細をAPIレスポンスに含める。攻撃者に内部構造を開示し、セキュリティインシデントの糸口になる。

try-catchを制御フローとして使う: 例外を予期される状態遷移のトリガーとして使う(例:ユーザー未存在を例外で判定)。例外は高コストで意図が読みにくく、if文またはResult型で表現すべきだ。

参考リソース

  1. 1. 📄アーキテクチャスタイル
  2. 2. 📄ドメインモデリング
  3. 3. 📄モジュール分割と依存管理
  4. 4. 📄データモデリング
  5. 5. 📄API設計
  6. 6. 📄整合性とトランザクション
  7. 7. 📄非同期処理(Queue/Event)
  8. 8. 📄キャッシング
  9. 9. 📄ユーザーリサーチ
  10. 10. 📄情報アーキテクチャ
  11. 11. 📄インタラクションデザイン
  12. 12. 📄UX原則とヒューリスティクス
  13. 13. 📄アクセシビリティ(UX観点)
  14. 14. 📄UXメトリクス
  15. 15. 📄スケーラビリティ
  16. 16. 📄可用性とレジリエンス
  17. 17. 📄オブザーバビリティ
  18. 18. 📄環境・インフラ設計
  19. 19. 📄データマイグレーション
  20. 20. 📄セキュリティ設計原則
  21. 21. 📄データ保護とマルチテナント
  22. 22. 📄LLMセキュリティ
  23. 23. 📄ビジュアルデザイン原則
  24. 24. 📄デザインシステム
  25. 25. 📄コンポーネント設計
  26. 26. 📄スタイリング
  27. 27. 📄設計原則
  28. 28. 📄デザインパターン(GoF)
  29. 29. 📄エンタープライズパターン
  30. 30. 📄クリーンコード
  31. 31. 📄リファクタリング
  32. 32. 📄型設計とコントラクト
  33. 33. 📄関数型プログラミング概念
  34. 34. 📄エラーハンドリング
  35. 35. 📄テスト戦略と哲学
  36. 36. 📄テスト種別(機能テスト)
  37. 37. 📄テスト種別(UI・ビジュアル)
  38. 38. 📄テスト種別(契約・境界)
  39. 39. 📄並行処理・マルチスレッド
  40. 40. 📄パフォーマンス最適化
  41. 41. 📄ドキュメント管理
  42. 42. 📄バージョン管理と開発プロセス
  43. 43. 📄脅威モデリング
  44. 44. 📄通信保護(TLS)
  45. 45. 📄暗号化・機密情報管理
  46. 46. 📄認証・セッション管理
  47. 47. 📄認可・アクセス制御
  48. 48. 📄入力バリデーション
  49. 49. 📄インジェクション攻撃
  50. 50. 📄正規化(データベース正規化)