【Salesforce】Apexで書くExceptionクラス

※本サイトにはプロモーション・広告が含まれています。

(最終更新月: 2024年2月)

✔以下の疑問をお持ちの方へ向けた記事です

「Salesforce Apexにおける例外処理クラスとは何か?」
「例外処理クラスを定義し使用するメリットは?」
「Apexでカスタム例外処理クラスを実装する方法は?」

✔当記事を読むことで得られる知識

  • Salesforce Apexにおける例外処理クラスの基本概念
  • カスタム例外処理クラスの定義と使用方法
  • 例外処理クラスを使用したエラーハンドリングのベストプラクティス

例外処理は、プログラムの実行時に予期しないエラーが発生した場合に、それを捕捉し適切に対処するための重要なメカニズムです。

当記事では、標準の例外クラスの使用方法と、特定のエラー条件に対応するためのカスタム例外クラスの定義方法に焦点を当てます。

Salesforceの開発者にとって、エラーハンドリングのスキルを向上させ、ユーザーフレンドリーなアプリケーションを構築するためのガイドとなるでしょう。

ぜひ最後までご覧ください。

Salesforce

定義や属性などは公式ガイドを必ず参考にしましょう。

当記事では、主にその使い方を具体例とともに解説します。

筆者プロフィール

筆者プロフィールアイコン

【現職】プロダクトマネージャー

プロダクトマネージャーとして、Apex・Visualforceの開発エンジニアとして、以下のようなプロジェクトに従事してきました

  • 新規事業の立ち上げに伴うビジネスプロセス構築とSalesforceのカスタマイズ
  • SFDXを活用した大規模リリース
  • Visualforce等による一般ユーザー向けサイト・アプリケーションの構築

相談・業務の依頼も承ります。ご質問・ご希望をお問い合わせください。

Apexにおける例外処理の基礎

ここでは、Apexでの例外処理の基本的な概念と重要性についてご紹介します。

これらの概念を理解することで、頑強なApexコードを書くために必要な基盤を築けるでしょう。

  • 例外処理とは何か
  • 標準例外クラスの概要
  • トライ・キャッチ・ファイナリーブロックの使用

例外処理とは何か

例外処理とは、プログラム実行中に予期しない問題(例外)が発生した場合に、そのエラーを適切に処理する仕組みのこと。

例外が発生すると、通常のプログラムの流れが中断され、例外処理のコードが実行されます。

Apexでは、trycatchfinallyブロックを使用してこの例外処理を実装。

次の例は、単純な例外処理の構文を示しています。

try {
    // 例外が発生する可能性のあるコード
} catch (Exception e) {
    // 例外が発生した場合の処理
} finally {
    // 例外の有無に関わらず実行される処理
}

上記の構文において、tryブロック内で実行されるコードが何らかの理由で失敗し、例外が投げられた場合、制御はcatchブロックに移ります。

ここで、例外オブジェクトを受け取り、エラーの詳細をログに記録したり、ユーザーに通知したりするなどのエラーハンドリング処理が可能。

finallyブロックは、例外の有無にかかわらず必ず実行する必要のあるクリーンアップ処理などを記述するのに適しています。

標準例外クラスの概要

Apexにはいくつかの標準例外クラスがあり、これらはシステムが自動的に例外を発生させる場合に使用されるもの。

例えば、以下のようなものがあります。

  • DmlException
  • QueryException
  • NullPointerException

これらのクラスはExceptionクラスから派生しています。

以下は、DmlExceptionをキャッチする基本的な例です。

try {
    insert new Account(Name='Test Account');
} catch (DmlException e) {
    System.debug('An error occurred on DML operation: ' + e.getMessage());
}

新しいAccountレコードの作成・保存の際に、何らかの理由でDML操作(ここではinsert)に失敗すると、DmlExceptionが発生します。

catchブロックでこの例外を捕捉し、ログにエラーメッセージを記録するというコードです。

トライ・キャッチ・ファイナリーブロックの使用

トライ・キャッチ・ファイナリーブロックは、Apexにおける例外処理を構成する基本的な構文です。

  • tryブロック: 例外が発生する可能性があるコードを包み込む
  • catchブロック: 特定の例外クラスを指定して、それに対応する処理を記述
  • finallyブロック: 例外の有無に関わらず実行したいコードを配置する場所

下記の例では、複数のcatchブロックを使用して異なる種類の例外を捕捉しています。

try {
    // 例外を発生させる可能性のある複雑な処理
} catch (DmlException e) {
    // DML操作関連の例外処理
} catch (QueryException e) {
    // SOQLクエリー関連の例外処理
} finally {
    // 常に実行される処理、例えばリソースの解放等
}

このように、Apexコードを書く際には、予期せぬエラーからアプリケーションを守るために、適切な例外処理の実装が不可欠です。

カスタム例外クラスの作成と利用

こちらでは、カスタム例外クラスを作成し、それを使ってエラーをスロー、キャッチ、処理する方法を見ていきます。

Apexコードでは、標準例外クラスだけでなく、特定のエラー条件に合わせて独自のカスタム例外クラスを定義できます。

  • カスタム例外クラスの定義方法
  • カスタム例外のスロー方法
  • カスタム例外のキャッチと処理

カスタム例外クラスの定義方法

カスタム例外クラスを定義するには、Exceptionクラスを継承し、Exceptionクラスから派生した新しいクラスの作成が必要です。

以下は簡単なカスタム例外クラスを定義する方法を示しています。

public class MyCustomException extends Exception {}

このMyCustomExceptionクラスは、非常に単純ですが、Apexの任意の箇所で使用できます。

通常は、ユーザー定義のプロパティやメソッドを追加して、エラー情報をより詳細に提供できるようにします。

カスタム例外のスロー方法

カスタム例外クラスを定義した後は、コード内の適切な場所でthrowステートメントを使用して、その例外をスローできます。

例外をスローすると、コードの実行が直ちに中断され、最も近いcatchブロックに制御が移されます。

以下がその例です。

if (someCondition) {
    throw new MyCustomException('Custom error message.');
}

このコードスニペットでは、特定の条件someConditionが真である場合に、新たに作成したMyCustomExceptionオブジェクトをスローしています。

カスタムメッセージを例外に渡すことで、エラー発生時により多くのコンテキストを提供することが可能です。

カスタム例外のキャッチと処理

カスタム例外がスローされた後は、catchブロックでそれを捕捉し、必要なエラーハンドリングをおこなえます。

カスタム例外を扱う際は、他の標準例外と同様に、例外オブジェクトからエラーメッセージなどの情報を取得できます。

以下はカスタム例外をキャッチする例です。

try {
    // カスタム例外をスローする可能性のあるコード
} catch (MyCustomException e) {
    // カスタム例外に特化したエラーハンドリング
    System.debug('Custom exception occurred: ' + e.getMessage());
}

この方法で、標準例外クラスだけでなくカスタム例外も適切に処理でき、より柔軟で洗練されたエラーハンドリング体系を構築できます。

例外処理の実践的活用

Apexの例外処理は、エラーハンドリングだけでなく、ユーザーエクスペリエンスの向上や、アプリケーションの信頼性を保つためにも重要です。

こちらでは、実際のアプリケーションにおける例外処理の活用方法を検討します。

  • エラーハンドリング戦略の設計
  • ユーザーフレンドリーなエラーメッセージの表示
  • エラーロギングと監視

エラーハンドリング戦略の設計

エラーハンドリング戦略を設計するときには、まず、どのレベルで例外をキャッチするかといった例外のスコープを決定する必要があります。

また、以下のようなシステム全体での一貫性のあるアプローチが必要です。

  • エラー情報のユーザー
  • ほかのシステムへの通知方法
  • エラーログの保管

以下は、エラーハンドリング戦略の概要を示す偽似コードです。

public void performSomeAction() {
    try {
        // メインの処理
    } catch (CustomException e) {
        // カスタム例外のユーザー向けのエラーメッセージ処理
        handleError(e);
    } catch (Exception e) {
        // その他全ての例外の処理
        logError(e);
        notifySystemAdmin(e);
    }
}

private void handleError(Exception e) {
    // ユーザー向けエラーメッセージを作成する処理
}

private void logError(Exception e) {
    // エラーログに記録する処理
}

private void notifySystemAdmin(Exception e) {
    // システム管理者に通知する処理
}

このコードは、例外処理を行うために、処理が分岐されることを示しており、エラーハンドリングの責務を適切に分割しています。

メンテナンス性と再利用性が向上し、異なる種類のエラーに対応するための柔軟な戦略を作れます。

ユーザーフレンドリーなエラーメッセージの表示

エラーが発生したときには、技術的な詳細をすべてユーザーに伝えるわけにはいきません。

エラーメッセージはユーザーフレンドリーで、ユーザーが次にどのようなアクションを取ればよいかを明確にすべきです。

例外オブジェクトから必要な情報を取得して、それを分かりやすい言葉に置き換え、ユーザーに提示する関数を作成することが有効です。

public void showFriendlyErrorMessage(Exception e) {
    String userMessage = 'An unexpected error occurred. Please try again later.';
    if (e instanceof CustomException) {
        userMessage = 'Your action could not be completed due to [specific reason].';
    }
    // ユーザーにメッセージを表示するロジック(画面表示やアラートなど)
}

エラーロギングと監視

エラーロギングは、障害発生時の原因究明や将来のエラー予防に不可欠です。

監視ツールと組み合わせることで、システム管理者はリアルタイムで問題を把握し、迅速に対応が可能になります。

エラー情報をロギングする際には、以下などの分析に役立つ十分な情報を含めることが大切です。

  • エラータイプ
  • 発生時刻
  • スタックトレース
  • ユーザー影響範囲
private void logError(Exception e) {
    // エラーの詳細、スタックトレース、発生時刻などをログに記録
    System.debug(LoggingLevel.ERROR, 'Error occurred: ' + e.getStackTraceString());
    // 監視システムへの通知はここで行う
}

例外処理のベストプラクティス

効果的な例外処理を実現するためには、一貫性のあるベストプラクティスに従うことが重要です。

ここでは、堅牢なコードを書くためのガイドラインとテクニックを紹介します。

  • 堅牢なエラーハンドリングコードの作成
  • パフォーマンスへの影響の最小化
  • 再利用可能な例外処理ロジックの開発

堅牢なエラーハンドリングコードの作成

堅牢なエラーハンドリングコードを作成するには、以下が大切。

  • どんなタイプのエラーが発生可能かを理解すること
  • 対応するキャッチブロックを用意すること
  • 例外を処理した後の状態が安全であること
  • 不要な情報公開を防ぐための対策がなされていること

各例外について適切な回復手順があり、それが適切に文書化されていることを確認しましょう。

try {
    // 危険な操作
} catch (CustomException e) {
    // カスタム例外に対する具体的な処理
} catch (Exception e) {
    // 想定外の例外の処理
    rollbackOperation(); // 失敗した操作を元に戻す
    notifyUser(e);       // ユーザーにフレンドリーなメッセージを表示
    logError(e);         // エラーをログに記録
} finally {
    cleanUpResources();  // 必要なリソースの解放
}

上記のスニペットは、さまざまな種類の例外を適切に処理し、最終に必ず実行する状態の確保、必要な情報のログ出力やリソースのクリーンアップをおこなう方法を示しています。

パフォーマンスへの影響の最小化

例外処理を行う際には、アプリケーションのパフォーマンスにも注意を払う必要があります。

例外が頻発するような場所では、例外を使用せずにエラーの条件を確認することでパフォーマンスの低下を防げます。

また、アプリケーションの処理フローを、頻繁に失敗する可能性が低い方法に調整することも重要です。

if (isOperationLikelyToFail()) {
    // 失敗を予測し、例外を使用せずに安全な処理を実行
} else {
    try {
        // 安全性が高いと予測される操作
    } catch (Exception e) {
        // それでも例外が発生した場合のハンドリング
    }
}

可能な場合は例外を使わずにエラー状態を回避し、必要に応じてのみ例外ハンドリングに頼ることを示唆しています。

パフォーマンスと信頼性のバランスを取ることが重要です。

再利用可能な例外処理ロジックの開発

似たような例外処理がプログラム内で繰り返される場合には、再利用可能な例外処理ロジックの開発が有効です。

共通のエラーハンドリングロジックをヘルパークラスやメソッドにまとめることで、コードの重複を避け、メンテナンス性を高められます。

public class ExceptionUtil {
    public static void handleException(Exception e, String context) {
        logError(e, context);  // エラーをログに記録
        notifySupportTeam(e);  // サポートチームに通知
    }

    // エラーロギングの詳細な実装
    private static void logError(Exception e, String context) {
        // エラーとコンテキストを含むログメッセージの生成
    }

    // サポートチーム通知の詳細な実装
    private static void notifySupportTeam(Exception e) {
        // サポートチームに通知するロジック
    }
}

再利用可能な例外処理ロジックによって、異なるユースケースやコードの部分で一貫したエラーハンドリングが可能です。

例外処理に関するトラブルシューティング

例外処理のトラブルシューティングは、アプリケーションの信頼性を高めるために不可欠なプロセスです。

ここでは、一般的な問題の特定と解決、効果的なデバッグのための技術とツール、テストと検証の重要性を見ていきます。

  • よくある例外処理の間違い
  • デバッグテクニックとツール
  • 例外処理のテストと検証

よくある例外処理の間違い

例外処理を実装する際には、一般的な罠に注意することが大切です。

例えば、すべての例外を捕捉することで本来必要な処理がスキップされる、適切なクリーンアップが行われない、ユーザーに対して誤解を招くエラーメッセージが表示される、といった問題があります。

try {
    // リスクのある操作
} catch (Exception e) {
    // 例外の種類にかかわらず全てキャッチする(よくない例)
}

このコードでは、全ての例外を一括でキャッチしているため、エラーの原因を特定しにくくなっています。例外の種類に応じて、適切なキャッチブロックを用意することが推奨されます。

デバッグテクニックとツール

効果的なデバッグには、Apexが提供しているSystem.debugメソッドや開発者コンソール、サードパーティ製のデバッグツールを上手く活用することが重要です。

これらのツールを使用して、アプリケーションの動作中に発生する例外の詳細を追跡し、問題の原因を特定します。

System.debug('Before risky operation');
try {
    // リスクのある操作
} catch (Exception e) {
    System.debug('Exception occurred: ' + e.getMessage());
    // その他のデバッグステートメント
}

ただしエラーメッセージをそのまま表示するのが、リスクとなる場合もあります。

「誰に」「何を」伝えるべきなのかを明確にしましょう。

例外処理のテストと検証

例外処理ロジックは、ほかのコードと同様にテストの対象となります。

ユニットテストを作成し、さまざまなエラーケースが適切にハンドルされることを保証する必要があるのです。

Apexのテストフレームワークを活用して、例外処理が予期した動作をしているかどうかを検証しましょう。

@isTest
private class ExceptionHandlingTest {
    static testMethod void testCustomExceptionHandling() {
        Test.startTest();

        // カスタム例外が適切に処理されることを検証するテストケース
        try {
            // カスタム例外を生成する
            throw new MyCustomException('Test exception');
        } catch (MyCustomException e) {
            // エラーメッセージが正しいかどうかを確認
            System.assertEquals('Test exception', e.getMessage());
        }

        Test.stopTest();
    }
}

このテストケースは、カスタム例外が正しくスローされ、キャッチされることを検証する目的で作成されています。

まとめ

Apexにおける例外処理は、信頼性の高いアプリケーションを構築するための基本です。

当記事を通して重要なポイントと考慮すべき側面を学びました。

  • 例外処理の基礎から実践的な応用
  • ベストプラクティス
  • トラブルシューティング

適切な例外処理により、エラーに迅速かつ効果的に対応し、ユーザーにとってより良い体験を提供することが可能になります。

積極的にテストを行い、一貫したエラーハンドリングロジックを開発して、より堅牢なApexコードを目指しましょう。

タイトルとURLをコピーしました