2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

JavaScriptにおける例外設計とエラーハンドリング戦略:try-catchの越境と責務分離

Posted at

概要

例外処理は「エラーを捕まえるため」だけにあるのではない。
それは**“失敗する可能性を前提とした制御構造”であり、アプリケーションの堅牢性を支える設計要素**である。

JavaScriptの try-catch はシンプルだが、適用範囲や粒度を誤ると、本来の責務が不明瞭になり、デバッグ困難なコードを生む
本稿では、例外設計の粒度、責任の分離、伝播戦略、ドメインとUI層での分担を含め、エラーハンドリングを構造的に整理する。


1. try-catch の構文と基本原則

try {
  const data = JSON.parse(jsonStr);
} catch (err) {
  console.error('JSON parsing failed:', err);
}
  • ✅ 失敗が「予想される」コードブロックにのみ適用
  • ❌ すべての処理を try に包むのはアンチパターン

2. 層ごとのエラーハンドリング戦略

❖ ドメイン層(ビジネスロジック)

  • ✅ 原因に応じた具体的な例外クラスを throw
  • ✅ 曖昧な throw 'error' は避ける。Errorオブジェクトを必ず使用
class ValidationError extends Error {}

function validate(user) {
  if (!user.email) throw new ValidationError('Email is required');
}

❖ アプリケーション層(呼び出し元)

  • ✅ try-catch で受け止め、ログやUI通知に変換
  • ✅ 原則として「処理と通知の責務を分離」する
try {
  validate(input);
} catch (err) {
  if (err instanceof ValidationError) {
    showToast(err.message);
  } else {
    throw err; // 上位に再スロー
  }
}

3. 非同期処理での try-catch

async function fetchData() {
  try {
    const res = await fetch('/api/data');
    const json = await res.json();
    return json;
  } catch (err) {
    console.error('Fetch failed:', err);
    throw err;
  }
}
  • ✅ async/await でも通常の try-catch を適用
  • .catch() のみで副作用的に扱うのは構造的に脆い

4. 共通エラーハンドラの抽象化

function handleError(err: unknown) {
  if (err instanceof NetworkError) {
    logNetwork(err);
  } else if (err instanceof ValidationError) {
    notifyUser(err.message);
  } else {
    reportCritical(err);
  }
}
  • エラーごとに分岐を整理し、設計として定義
  • ✅ 呼び出し元では handleError() という責務のみに集中できる

5. 設計粒度の指針:どこで try-catch を置くべきか

処理範囲 例外処理設計
小さすぎる try が乱立し、構造が煩雑になる
大きすぎる 何が失敗したか分からなくなる
責務単位で配置する ✅ ロジック単位ごとに try を設ける

設計判断フロー

① 例外は予期された失敗か? → ifによるバリデーションが適切では?

② どの層で try-catch を置くべきか?(UI/ドメイン/インフラ)

③ エラー種別は Errorクラスで定義されているか?

④ 処理と通知の責務は分離されているか?

⑤ エラーが再スロー or 回収で明示的に扱われているか?

よくあるミスと対策

❌ catch ですべてを握りつぶしてログだけ吐く

→ ✅ 処理責任に応じて通知 / 再スローの判断を明示


throw 'string' のような雑な例外投げ

→ ✅ 必ず new Error() or カスタムエラーを使用


❌ 非同期関数内で try-catch を使わず .catch() に処理を書きすぎる

→ ✅ await + try-catch で構造を明確化


結語

例外処理は「失敗を捕まえるもの」ではない。
それは**“期待される制御フローの逸脱を、設計的に扱うための構造要素”**である。

  • try-catch の配置には戦略が必要
  • 失敗は「例外」ではなく「分岐条件」として設計すべき場合もある
  • 責務の分離こそが、例外処理を「デザイン」に変える鍵

JavaScriptにおけるエラーハンドリングとは、
“失敗の発生を想定し、制御下に置くための設計戦略である。”

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?