Java | 「for-each+例外処理+ログ」のテンプレートをクラス構造で整理(実務クラス設計例)

Java Java
スポンサーリンク

では、次は実務レベルで使えるように改良した、
「for-each+例外処理+ログ」テンプレートの汎用(ジェネリクス対応)版を紹介します。

これは「どんな型のデータでも安全にfor-each処理できる汎用テンプレート」として、
実際の業務システムや共通ユーティリティクラスに組み込みやすい構造です。


【実務テンプレート:汎用 for-each 処理+例外+ログ+再利用設計】

import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

// =============================================
// ✅ 汎用処理クラス(再利用可能なテンプレート)
// =============================================
public class SafeForEachProcessor<T> {

    private static final Logger logger = Logger.getLogger(SafeForEachProcessor.class.getName());

    /**
     * for-each 処理を安全に実行する共通メソッド
     *
     * @param items   処理対象のリスト
     * @param handler 各要素の処理を定義するラムダ
     */
    public void process(List<T> items, SafeHandler<T> handler) {
        if (items == null || items.isEmpty()) {
            logger.warning("処理対象リストが空またはnullです。処理をスキップします。");
            return;
        }

        for (T item : items) {
            try {
                handler.handle(item);
            } catch (BusinessException e) {
                logger.warning("業務エラー(スキップ): " + e.getMessage());
            } catch (Exception e) {
                logger.log(Level.SEVERE, "予期せぬエラー発生: " + item, e);
            }
        }
    }
}

// =============================================
// ✅ 各要素処理の関数インターフェース(ラムダで渡す)
// =============================================
@FunctionalInterface
interface SafeHandler<T> {
    void handle(T item) throws Exception;
}

// =============================================
// ✅ 業務例外(想定内のエラー用)
// =============================================
class BusinessException extends Exception {
    public BusinessException(String message) {
        super(message);
    }
}

// =============================================
// ✅ 使用例:顧客データを安全に処理するクラス
// =============================================
class Customer {
    private final String name;
    private final int age;

    public Customer(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public String getName() { return name; }
    public int getAge() { return age; }

    @Override
    public String toString() {
        return name + " (" + age + ")";
    }
}

// =============================================
// ✅ 実行クラス
// =============================================
import java.util.Arrays;

public class ExampleMain {
    public static void main(String[] args) {
        List<Customer> customers = Arrays.asList(
            new Customer("Alice", 25),
            new Customer("Bob", -1),      // 無効データ
            new Customer("Charlie", 30)
        );

        SafeForEachProcessor<Customer> processor = new SafeForEachProcessor<>();

        processor.process(customers, customer -> {
            if (customer.getAge() < 0) {
                throw new BusinessException("年齢が不正です: " + customer);
            }
            System.out.println("処理中: " + customer);
        });
    }
}
Java

クラス設計の概要

クラス名役割
SafeForEachProcessor<T>どんなデータ型でも安全にfor-eachできる汎用テンプレート
SafeHandler<T>各要素の処理内容をラムダ式で渡すためのインターフェース
BusinessException業務的に想定内の例外を区別するクラス
Customer処理対象のドメインモデル(例:顧客データ)
ExampleMain実際の呼び出し例(for-each+例外+ログ)

実務でのベストプラクティス(設計上の工夫)

項目ベストプラクティス解説
共通for-each処理を1か所に集約SafeForEachProcessor重複する例外処理・ログ処理を共通化し、コードの品質を均一化
ラムダで処理内容を注入SafeHandler<T>各業務の「中身」を柔軟に定義できる(Strategyパターン風)
カスタム例外で制御BusinessException想定内エラーとシステム障害を明確に区別できる
for-each内でtry-catchを行う継続可能な処理に必須1件失敗しても全体処理を中断せず続けられる
nullチェック/空チェック処理前にガード条件NPE防止+安全設計
ロガーのレベル設計INFO / WARNING / SEVERE重要度に応じた出力レベル管理

実務応用例(こう発展できる)

  • SafeForEachProcessor に「リトライ機能」や「結果集計(成功・失敗件数)」を追加。
  • Spring Boot環境では @Service クラス内で使い、Slf4j ログ出力に統一。
  • SafeHandler をラムダ式だけでなく「専用クラス」で実装して、テスト容易化。
タイトルとURLをコピーしました