エラーハンドリングの原則 - Ki-Kobayashi/Android-Wiki GitHub Wiki
🟩 「runCatching」と「try / finally」 の違い
🟡finally の違い
- try / finally では、例外がスローされたかどうかに関係なく、finally ブロックが常に実行されることを保証する
fun tryToDoSomething(): Int {
var result = 0
val resource = acquireResource()
try {
// Code that can throw an exception
result = performAction(resource)
} finally {
releaseResource(resource)
}
return result
}
- runCatching()ブロックの後に手動でリソースを解放する
fun doSomethingRunCatching(): Int {
val resource = acquireResource()
val result = runCatching {
// Code that can throw an exception
performAction(resource)
}
releaseResource(resource)
return result.getOrThrow()
}
※コードで例外を処理せずにリソースのクリーンアップが必要な場合は、try / finally
🟡 キャッチするスコープの違い
- try-catch: catchブロックに書いたものだけを catch
- runCatching: すべてを catch (値を返すか、例外をスロー)
.# 🟩 不必要に広い範囲の例外をキャッチすることは、バグの早期発見の妨げ
.
🟩 API接続に関するエラーハンドリングの原則
https://engineering.linecorp.com/ja/blog/droidkaigi2023_code_review_challenge_4
- ネットワーク関連のトラブルを示す IOException のみをハンドリングすれば十分
.
🛑【runCathing】
runCathingを使用することでその他の例外も全てキャッチする
例えば、 NullPointerException は"実装の問題"から生じる。そのためコードを修正する必要があるが、 runCatching を使っていると発見が難しくなってしまう。
CancellationException は Coroutine が正しく動作するために必要な例外。こちらをキャッチしてしまうと、正常にキャンセルが動作しなくなる。
→そのため必要最小限の例外をキャッチするよう心がけるべき
suspend fun getUserData(userId: UserId): UserData? = try {
// ...snip
} catch (e: IOException) {
null
}
suspend fun getUserData(userName: UserName): UserData? = try {
// ...snip
} catch (e: IOException) {
null
}
🟩 コルーチンでtry-catchする罠
https://note.com/actbe_ohashi/n/n69a6d72db2c7
Coroutine内 の 【async に対して】、エラーハンドリングしたいなら、try-catch はあまり使わないほうがいい?
→ CoroutineExceptionHandler だったりを使った方が良さそう
🟡 事例(理由)
Coroutine内 の async の内部がキャッチされない
lifecycleScope.launch {
try {
async {
// 例外に落ちるかもしれない処理
}
} catch (exception: Exception) {
Log.d(TAG, "落ちたのをログで確認したい${exception.message}")
}
}
🟡 解決案(try-catchをそのまま使いたい場合)
👇の回答もあるが、そもそも「lifecycleScope.launch」自体をtry-catchで囲うとどうなる?
lifecycleScope.launch {
try {
coroutineScope {
async {
// 例外に落ちるかもしれないの処理
}
}
} catch (exception: Exception) {
Log.d(TAG, "落ちたのをログで確認したい${exception.message}")
}
}
.
🟩 エラーハンドリングの方法3種
- try-catch
- Either
- Result
🟡try-catch
.## 🟡Either
.## 🟡Result
.
🟩
🟡
.
🟩
🟡
.
🟩
🟡
.
🟩
🟡
.
🟩
🟡
.
🟩
🟡
.