Kotlinで高階関数を活用したエラーハンドリング入門

Kotlinの高階関数を利用したエラーハンドリングは、ソフトウェアの堅牢性を高め、コードの簡潔性を向上させる強力な手法です。従来のエラーハンドリングでは冗長になりがちなコードを、Kotlinの特性を活かしてより簡潔かつ直感的に記述できます。本記事では、高階関数の基礎から実践的な応用例までを丁寧に解説し、効率的なエラーハンドリング手法を学ぶことで、開発作業の効率化を目指します。

目次
  1. 高階関数とは何か
    1. 高階関数の特徴
    2. 高階関数の例
  2. エラーハンドリングの重要性
    1. エラーハンドリングの役割
    2. Kotlinにおけるエラーハンドリングの課題
    3. 高階関数による解決策
  3. 高階関数を使ったエラーハンドリングのメリット
    1. コードの簡潔化
    2. 可読性の向上
    3. 柔軟なエラーハンドリング戦略
    4. 非同期処理との統合
  4. Try-Catchを高階関数で置き換える方法
    1. 従来のTry-Catch構文
    2. 高階関数による置き換え
    3. エラーメッセージのカスタマイズ
    4. 実践例:データベース操作
  5. Resultクラスの活用方法
    1. Resultクラスの概要
    2. 基本的な使い方
    3. 非同期操作への応用
    4. Resultクラスの拡張
    5. 例外を再スローする方法
    6. 応用例:APIリクエストのハンドリング
  6. 安全なリソース管理と高階関数
    1. リソース管理の課題
    2. 高階関数を使ったリソース管理
    3. use関数の仕組み
    4. データベース接続の管理例
    5. カスタムリソースでの応用
    6. 高階関数で独自のリソース管理を実装する
  7. 実践演習:ファイル操作でのエラーハンドリング
    1. 従来のファイル操作と課題
    2. 高階関数を使ったファイル操作
    3. 高階関数でエラーハンドリングを抽象化
    4. 実践例:複数行のファイル読み込み
    5. 応用:ファイル書き込み
    6. エラーハンドリングの拡張
    7. まとめ
  8. 応用例:APIリクエストとエラーハンドリング
    1. 従来のエラーハンドリング
    2. 高階関数を使った改善
    3. 非同期APIリクエストへの応用
    4. Resultクラスとの統合
    5. 実践例:複数APIリクエストの統合
    6. 例外の再スロー
    7. まとめ
  9. まとめ

高階関数とは何か


Kotlinにおける高階関数とは、他の関数を引数として受け取ったり、結果として関数を返したりする関数のことを指します。この機能により、コードの再利用性が高まり、柔軟で簡潔なプログラムを構築することが可能になります。

高階関数の特徴


Kotlinでは関数がファーストクラスの市民として扱われるため、高階関数を自然に利用できます。以下は主な特徴です:

  • 関数を引数として渡せる
  • 関数を戻り値として返せる
  • ラムダ式や無名関数と組み合わせて簡潔に記述可能

高階関数の例


以下は、数値リストを操作する高階関数の例です:

fun <T> List<T>.customFilter(predicate: (T) -> Boolean): List<T> {
    val result = mutableListOf<T>()
    for (item in this) {
        if (predicate(item)) {
            result.add(item)
        }
    }
    return result
}

val numbers = listOf(1, 2, 3, 4, 5)
val evenNumbers = numbers.customFilter { it % 2 == 0 }
println(evenNumbers) // 出力: [2, 4]

この例では、customFilter関数が引数として渡された条件(predicate関数)に基づいてリストをフィルタリングしています。高階関数を使用することで、コードを柔軟に再利用できることがわかります。

高階関数は、エラーハンドリングやリソース管理など、さまざまな場面で応用可能です。次のセクションでは、エラーハンドリングの重要性について掘り下げます。

エラーハンドリングの重要性

ソフトウェア開発においてエラーハンドリングは、アプリケーションの安定性と信頼性を確保するために欠かせない要素です。予期しないエラーが発生した場合でも適切に対処することで、ユーザー体験を損なわず、システム全体の堅牢性を向上させることができます。

エラーハンドリングの役割


エラーハンドリングには以下のような役割があります:

  • 予期しないエラーへの対応:プログラムの実行時に発生する例外やエラーを適切に処理し、アプリケーションのクラッシュを防ぎます。
  • ユーザーへの通知:エラー内容を適切に通知することで、ユーザーに次のアクションを明示します。
  • システムの安定性向上:エラーが発生しても適切に処理することで、システム全体の安定性を保ちます。

Kotlinにおけるエラーハンドリングの課題


従来のエラーハンドリングでは、try-catchブロックが多用されることが一般的ですが、これによりコードが冗長になりがちです。例えば、以下のようなコードを考えます:

try {
    val result = performOperation()
    println("Result: $result")
} catch (e: Exception) {
    println("Error: ${e.message}")
}

このようなコードは小規模であれば問題ありませんが、複雑なロジックや複数のエラーパターンを扱う場合、ネストが深くなり読みづらくなることがあります。

高階関数による解決策


Kotlinの高階関数を用いることで、エラーハンドリングをより簡潔かつ効率的に行うことが可能です。次のセクションでは、高階関数を活用したエラーハンドリングのメリットについて具体的に解説します。

高階関数を使ったエラーハンドリングのメリット

Kotlinの高階関数を利用したエラーハンドリングには、従来のtry-catch構文と比べて多くの利点があります。これにより、コードの可読性や保守性が向上し、より効率的なプログラム開発が可能になります。

コードの簡潔化


高階関数を活用することで、冗長になりがちなtry-catch構文を抽象化できます。たとえば、複数箇所で共通するエラーハンドリングの処理を高階関数として定義すれば、繰り返し記述を大幅に削減できます。

例:エラーハンドリングを関数に抽出した場合

fun <T> handleErrors(action: () -> T): T? {
    return try {
        action()
    } catch (e: Exception) {
        println("Error: ${e.message}")
        null
    }
}

val result = handleErrors { performOperation() }
println("Result: $result")

上記のように、高階関数handleErrorsを使用すれば、エラー処理を再利用可能な形で記述できます。

可読性の向上


高階関数はエラーハンドリングロジックを分離するため、メインのロジックがスッキリと読みやすくなります。これにより、コードの意図が明確化し、チームでの開発時にも理解しやすくなります。

柔軟なエラーハンドリング戦略


高階関数を使用すると、エラー発生時の挙動を柔軟にカスタマイズできます。例えば、以下のように、エラー時の処理を呼び出し側で指定することが可能です:

fun <T> handleErrorsWithAction(
    action: () -> T,
    onError: (Exception) -> Unit
): T? {
    return try {
        action()
    } catch (e: Exception) {
        onError(e)
        null
    }
}

handleErrorsWithAction(
    action = { performOperation() },
    onError = { println("Logging error: ${it.message}") }
)

この例では、エラー時のロギング処理をonErrorとして呼び出し側が定義しています。

非同期処理との統合


高階関数を利用すれば、非同期処理(suspend関数など)とも簡単に統合できます。これにより、エラーハンドリングを含めた非同期処理のコードが一貫性を保ちながら簡潔になります。

次のセクションでは、具体的にtry-catch構文を高階関数に置き換える方法について掘り下げていきます。

Try-Catchを高階関数で置き換える方法

Kotlinのtry-catch構文は、エラー処理において基本的な構文ですが、高階関数を利用することで、よりモジュール化された簡潔なコードに置き換えることが可能です。このセクションでは、try-catch構文を高階関数で抽象化する方法を解説します。

従来のTry-Catch構文


従来のtry-catch構文は以下のように記述します:

try {
    val result = performOperation()
    println("Result: $result")
} catch (e: Exception) {
    println("Error: ${e.message}")
}

この構文ではエラーハンドリングが明示的に記述されていますが、同様のコードが複数箇所に分散する場合、コードの冗長化や重複の問題が発生します。

高階関数による置き換え


try-catch構文を高階関数で置き換えることで、エラーハンドリングを簡潔にし、再利用可能な形に抽象化できます。以下にその実装例を示します:

fun <T> runWithHandling(action: () -> T): T? {
    return try {
        action()
    } catch (e: Exception) {
        println("Error: ${e.message}")
        null
    }
}

この関数runWithHandlingは、引数としてラムダ式を受け取り、その中で発生する可能性のある例外をキャッチします。これを使うと以下のようにコードを書き換えられます:

val result = runWithHandling { performOperation() }
println("Result: $result")

このようにすることで、エラーハンドリングの処理を一箇所に集約でき、コードが簡潔になります。

エラーメッセージのカスタマイズ


高階関数を拡張して、エラー発生時にメッセージをカスタマイズすることも可能です:

fun <T> runWithHandling(
    action: () -> T,
    onError: (Exception) -> Unit = { println("Error: ${it.message}") }
): T? {
    return try {
        action()
    } catch (e: Exception) {
        onError(e)
        null
    }
}

val result = runWithHandling(
    action = { performOperation() },
    onError = { println("Custom error: ${it.message}") }
)

この例では、エラー処理の内容を呼び出し元が自由に変更できるようになっています。

実践例:データベース操作


以下は、データベースクエリを実行する際にエラー処理を高階関数で抽象化する例です:

val queryResult = runWithHandling {
    database.executeQuery("SELECT * FROM users")
}
println("Query Result: $queryResult")

このようにすることで、コード全体の可読性を損なうことなくエラー処理を実現できます。

次のセクションでは、KotlinのResultクラスを活用してエラーハンドリングをさらに高度に行う方法について解説します。

Resultクラスの活用方法

KotlinにはResultクラスという標準的なエラーハンドリングのためのユーティリティが用意されています。このクラスを使用することで、成功と失敗の両方の状態を明示的に管理でき、エラーハンドリングがより簡潔かつ安全になります。このセクションでは、Resultクラスの基本的な使い方とその応用方法について解説します。

Resultクラスの概要


Resultクラスは、操作の結果が成功か失敗かを保持するラッパーです。以下の特徴があります:

  • 成功時には結果の値を保持
  • 失敗時には例外を保持

Resultクラスを使用すると、関数の戻り値に成功または失敗の状態をラップする形でエラーハンドリングができます。

基本的な使い方


以下はResultクラスを利用したエラーハンドリングの基本例です:

fun performOperation(): Result<Int> {
    return try {
        val result = 10 / 2 // 正常動作
        Result.success(result)
    } catch (e: Exception) {
        Result.failure(e)
    }
}

val result = performOperation()
result.onSuccess { value ->
    println("Operation succeeded: $value")
}.onFailure { error ->
    println("Operation failed: ${error.message}")
}

このコードでは、成功した場合はResult.successが返され、失敗した場合はResult.failureが返されます。onSuccessおよびonFailureを使用して結果を処理できます。

非同期操作への応用


非同期処理でもResultクラスを活用できます。以下は例です:

suspend fun fetchData(): Result<String> {
    return try {
        val data = fetchFromNetwork() // ネットワークからデータ取得
        Result.success(data)
    } catch (e: Exception) {
        Result.failure(e)
    }
}

val fetchResult = fetchData()
fetchResult.onSuccess { data ->
    println("Fetched data: $data")
}.onFailure { error ->
    println("Failed to fetch data: ${error.message}")
}

非同期操作でのエラーハンドリングがシンプルかつ安全に行えます。

Resultクラスの拡張


Resultクラスは拡張関数を使用してカスタマイズできます。以下は結果をログ出力する拡張例です:

fun <T> Result<T>.logResult(): Result<T> {
    this.onSuccess { println("Success: $it") }
        .onFailure { println("Error: ${it.message}") }
    return this
}

val operationResult = performOperation().logResult()

この拡張により、結果の処理とログ出力を一箇所で簡潔に記述できます。

例外を再スローする方法


場合によってはResultの中でキャッチした例外を再スローする必要があります。その場合は以下のように記述します:

val result = performOperation()
result.getOrElse { throw it }

getOrElseを使用すると、失敗時に例外を再スローできます。

応用例:APIリクエストのハンドリング


ResultクラスはAPIリクエストの結果を安全に管理する際にも役立ちます:

fun fetchUser(): Result<User> {
    return try {
        val user = api.getUser() // API呼び出し
        Result.success(user)
    } catch (e: Exception) {
        Result.failure(e)
    }
}

このようにResultクラスを活用することで、例外処理を明確にしつつ、コードを簡潔化できます。

次のセクションでは、安全なリソース管理を高階関数で実現する方法を解説します。

安全なリソース管理と高階関数

リソース管理は、プログラムの安定性を保つために重要な要素です。特にファイル操作やデータベース接続など、リソースを正しく解放しないとメモリリークや予期しない動作を引き起こす可能性があります。Kotlinでは、高階関数を活用することで、リソース管理を効率化し、安全性を向上させることができます。

リソース管理の課題


従来のリソース管理では、リソースの解放を明示的に記述する必要があります。以下は典型的な例です:

val reader = BufferedReader(FileReader("example.txt"))
try {
    val content = reader.readLine()
    println(content)
} catch (e: Exception) {
    println("Error: ${e.message}")
} finally {
    reader.close() // リソース解放
}

このコードでは、リソース解放をfinallyブロックに記述していますが、記述ミスや抜けによってリソースリークが発生するリスクがあります。

高階関数を使ったリソース管理


Kotlinではuse関数を使用することで、リソース管理を安全かつ簡潔に行えます。use関数は、高階関数として動作し、リソースを自動的に解放します:

BufferedReader(FileReader("example.txt")).use { reader ->
    val content = reader.readLine()
    println(content)
}

この例では、use関数を利用することで、finallyブロックを記述する必要がなく、リソースが自動的に解放されます。

use関数の仕組み


use関数はCloseableインターフェースを実装するオブジェクトに対して動作します。内部でtry-finallyを利用してリソース解放を保証しています。

以下はuse関数のシンプルな動作例です:

fun <T : Closeable, R> T.use(block: (T) -> R): R {
    try {
        return block(this)
    } finally {
        this.close()
    }
}

これにより、エラーが発生しても確実にcloseが呼び出されます。

データベース接続の管理例


データベース接続のようなリソース管理でもuse関数は役立ちます:

DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "user", "password").use { connection ->
    val statement = connection.createStatement()
    val resultSet = statement.executeQuery("SELECT * FROM users")
    while (resultSet.next()) {
        println("User: ${resultSet.getString("name")}")
    }
}

この例では、Connectionオブジェクトが自動的に解放されるため、手動で閉じる必要がありません。

カスタムリソースでの応用


カスタムリソースクラスでもuseを利用可能です。以下はその例です:

class CustomResource : Closeable {
    fun performAction() {
        println("Performing action")
    }

    override fun close() {
        println("CustomResource closed")
    }
}

CustomResource().use { resource ->
    resource.performAction()
}

この例では、リソースの利用と解放が簡潔に記述されています。

高階関数で独自のリソース管理を実装する


さらに、特定のリソース管理ロジックを高階関数としてカスタマイズできます:

fun <T> manageResource(resource: T, onClose: (T) -> Unit, action: (T) -> Unit) {
    try {
        action(resource)
    } finally {
        onClose(resource)
    }
}

val resource = "Temporary File"
manageResource(resource, onClose = { println("$it cleaned up") }) { res ->
    println("Using $res")
}

このように、高階関数を活用すれば、どのようなリソースでも柔軟に管理できます。

次のセクションでは、実際の応用例としてファイル操作でのエラーハンドリングを解説します。

実践演習:ファイル操作でのエラーハンドリング

ファイル操作はリソース管理とエラーハンドリングが特に重要な領域の一つです。ここでは、Kotlinの高階関数を利用して、ファイル操作時に発生する可能性のあるエラーを効率的に処理する方法を解説します。具体的な例を交えながら、安全で再利用可能なコードを書く方法を学びます。

従来のファイル操作と課題


以下は従来のファイル読み込みの例です:

val reader = BufferedReader(FileReader("example.txt"))
try {
    val content = reader.readLine()
    println(content)
} catch (e: IOException) {
    println("Error reading file: ${e.message}")
} finally {
    reader.close() // リソース解放
}

このコードは動作しますが、次の課題があります:

  • 冗長なリソース解放コード: finallyブロックでの手動リソース解放が必要。
  • エラーハンドリングが分散: エラー処理が一貫性に欠ける。

高階関数を使ったファイル操作


use関数を利用すれば、リソース解放を自動化できます:

BufferedReader(FileReader("example.txt")).use { reader ->
    try {
        val content = reader.readLine()
        println(content)
    } catch (e: IOException) {
        println("Error reading file: ${e.message}")
    }
}

use関数により、リソース解放コードを省略でき、エラー発生時にも安全に処理が行われます。

高階関数でエラーハンドリングを抽象化


エラーハンドリングをより簡潔にするため、専用の高階関数を実装します:

fun <T> handleFileOperation(filePath: String, action: (BufferedReader) -> T): T? {
    return try {
        BufferedReader(FileReader(filePath)).use { reader ->
            action(reader)
        }
    } catch (e: IOException) {
        println("Error handling file: ${e.message}")
        null
    }
}

この高階関数を使用すると、ファイル操作コードがシンプルになります:

val content = handleFileOperation("example.txt") { reader ->
    reader.readLine()
}
println("File content: $content")

この例では、エラーハンドリングとリソース管理が高階関数に集約され、呼び出し元のコードが簡潔になります。

実践例:複数行のファイル読み込み


以下は、複数行のファイルを読み込む例です:

val lines = handleFileOperation("example.txt") { reader ->
    reader.lineSequence().toList()
}
lines?.forEach { println(it) }

この例では、lineSequenceを使用してファイルの全行をリストに変換し、それぞれを出力しています。

応用:ファイル書き込み


書き込み操作にも同様の高階関数を適用できます:

fun handleFileWrite(filePath: String, action: (BufferedWriter) -> Unit) {
    try {
        BufferedWriter(FileWriter(filePath)).use { writer ->
            action(writer)
        }
    } catch (e: IOException) {
        println("Error writing file: ${e.message}")
    }
}

handleFileWrite("output.txt") { writer ->
    writer.write("Hello, Kotlin!")
}

このコードでは、ファイル書き込み操作が安全に実行され、エラーも適切に処理されます。

エラーハンドリングの拡張


必要に応じて、エラー処理をカスタマイズ可能な高階関数を作成できます:

fun <T> handleFileOperationWithCustomError(
    filePath: String,
    onError: (IOException) -> Unit,
    action: (BufferedReader) -> T
): T? {
    return try {
        BufferedReader(FileReader(filePath)).use { reader ->
            action(reader)
        }
    } catch (e: IOException) {
        onError(e)
        null
    }
}

handleFileOperationWithCustomError(
    filePath = "example.txt",
    onError = { println("Custom Error: ${it.message}") }
) { reader ->
    reader.readLine()
}

この例では、エラーメッセージをカスタマイズできるようになっています。

まとめ


高階関数を活用することで、ファイル操作のエラーハンドリングが大幅に簡略化されます。リソース管理が自動化されるだけでなく、コードの再利用性も向上します。次のセクションでは、APIリクエストのエラーハンドリングについて解説します。

応用例:APIリクエストとエラーハンドリング

APIリクエストでは、ネットワークエラーやデータフォーマットの不一致など、さまざまなエラーが発生する可能性があります。Kotlinの高階関数を活用することで、これらのエラーを効率的に処理し、安全かつ柔軟なコードを実現できます。ここでは、Kotlinを用いたAPIリクエストのエラーハンドリングの具体例を紹介します。

従来のエラーハンドリング


以下は、一般的なAPIリクエストのエラーハンドリング例です:

try {
    val response = apiClient.fetchData()
    if (response.isSuccessful) {
        println("Data: ${response.body}")
    } else {
        println("Error: ${response.errorBody}")
    }
} catch (e: IOException) {
    println("Network error: ${e.message}")
}

このコードでは、エラーハンドリングが分散しており、APIの成功と失敗、ネットワークエラーを個別に処理する必要があります。

高階関数を使った改善


エラーハンドリングを高階関数に集約することで、コードを簡潔にできます:

fun <T> handleApiRequest(
    action: () -> T,
    onError: (Exception) -> Unit
): T? {
    return try {
        action()
    } catch (e: Exception) {
        onError(e)
        null
    }
}

この高階関数を使用すると、以下のように簡潔に記述できます:

val data = handleApiRequest(
    action = { apiClient.fetchData() },
    onError = { println("API error: ${it.message}") }
)
data?.let { println("Data: $it") }

このコードでは、成功時とエラー時の処理を簡潔に記述できます。

非同期APIリクエストへの応用


非同期操作でも同様のアプローチが利用可能です。以下はCoroutineを利用した例です:

suspend fun <T> handleApiRequestAsync(
    action: suspend () -> T,
    onError: (Exception) -> Unit
): T? {
    return try {
        action()
    } catch (e: Exception) {
        onError(e)
        null
    }
}

val data = handleApiRequestAsync(
    action = { apiClient.fetchDataAsync() },
    onError = { println("API error: ${it.message}") }
)
data?.let { println("Data: $it") }

非同期APIリクエストを簡潔かつ安全に扱うことができます。

Resultクラスとの統合


Resultクラスを利用して、APIリクエストの結果をさらに明示的に扱うことも可能です:

fun <T> handleApiRequestWithResult(
    action: () -> T
): Result<T> {
    return try {
        Result.success(action())
    } catch (e: Exception) {
        Result.failure(e)
    }
}

val result = handleApiRequestWithResult { apiClient.fetchData() }
result.onSuccess { println("Data: $it") }
      .onFailure { println("Error: ${it.message}") }

これにより、成功と失敗を分離して処理できます。

実践例:複数APIリクエストの統合


複数のAPIリクエストを同時に実行し、それぞれの結果を安全に処理する例です:

val result1 = handleApiRequestWithResult { apiClient.fetchUserData() }
val result2 = handleApiRequestWithResult { apiClient.fetchPosts() }

result1.onSuccess { println("User Data: $it") }
       .onFailure { println("User Data Error: ${it.message}") }

result2.onSuccess { println("Posts: $it") }
       .onFailure { println("Posts Error: ${it.message}") }

このようにすることで、複数のAPIリクエストに対するエラーハンドリングを一貫した形式で記述できます。

例外の再スロー


場合によっては例外を再スローする必要がある場合もあります。以下のように実現できます:

fun <T> handleApiRequestAndRethrow(
    action: () -> T
): T {
    return try {
        action()
    } catch (e: Exception) {
        println("Logging error: ${e.message}")
        throw e
    }
}

エラーを記録した上で例外を再スローすることで、エラーハンドリングを柔軟に行えます。

まとめ


高階関数を活用することで、APIリクエストのエラーハンドリングを簡潔かつ効果的に実現できます。エラーの再スローや非同期処理との統合も可能で、コードの再利用性と保守性が大幅に向上します。次のセクションでは、この記事のまとめを行います。

まとめ

本記事では、Kotlinにおける高階関数を利用したエラーハンドリングの方法について解説しました。高階関数を活用することで、冗長なtry-catch構文を簡潔に置き換え、コードの可読性や再利用性を向上させることが可能です。

具体的には、use関数を用いたリソース管理の自動化、Resultクラスによる明示的なエラーハンドリング、そしてAPIリクエストや非同期処理への応用例を取り上げました。これにより、エラー処理を一貫性のある形で実装し、ソフトウェアの堅牢性を向上させる方法を学びました。

Kotlinの高階関数をマスターすることで、効率的でモダンなプログラム開発を実現しましょう。

コメント

コメントする

目次
  1. 高階関数とは何か
    1. 高階関数の特徴
    2. 高階関数の例
  2. エラーハンドリングの重要性
    1. エラーハンドリングの役割
    2. Kotlinにおけるエラーハンドリングの課題
    3. 高階関数による解決策
  3. 高階関数を使ったエラーハンドリングのメリット
    1. コードの簡潔化
    2. 可読性の向上
    3. 柔軟なエラーハンドリング戦略
    4. 非同期処理との統合
  4. Try-Catchを高階関数で置き換える方法
    1. 従来のTry-Catch構文
    2. 高階関数による置き換え
    3. エラーメッセージのカスタマイズ
    4. 実践例:データベース操作
  5. Resultクラスの活用方法
    1. Resultクラスの概要
    2. 基本的な使い方
    3. 非同期操作への応用
    4. Resultクラスの拡張
    5. 例外を再スローする方法
    6. 応用例:APIリクエストのハンドリング
  6. 安全なリソース管理と高階関数
    1. リソース管理の課題
    2. 高階関数を使ったリソース管理
    3. use関数の仕組み
    4. データベース接続の管理例
    5. カスタムリソースでの応用
    6. 高階関数で独自のリソース管理を実装する
  7. 実践演習:ファイル操作でのエラーハンドリング
    1. 従来のファイル操作と課題
    2. 高階関数を使ったファイル操作
    3. 高階関数でエラーハンドリングを抽象化
    4. 実践例:複数行のファイル読み込み
    5. 応用:ファイル書き込み
    6. エラーハンドリングの拡張
    7. まとめ
  8. 応用例:APIリクエストとエラーハンドリング
    1. 従来のエラーハンドリング
    2. 高階関数を使った改善
    3. 非同期APIリクエストへの応用
    4. Resultクラスとの統合
    5. 実践例:複数APIリクエストの統合
    6. 例外の再スロー
    7. まとめ
  9. まとめ