kotlin-control-flow について
開発者やコーディングエージェント向けの Kotlin 制御フロースキルです。subject 付き `when`、ガード分岐、網羅的な分岐選択に加え、プロジェクトのビルドツールによる検証も扱います。
主な機能
- 01`when` と `if` の選択指針
- 02条件を絞るガード分岐
- 03閉じた型の網羅的な分岐
- 04無効状態を除く早期リターン
- 05スマートキャストを使う分岐処理
- 06プロジェクトのビルドとテストの検証
活用シーン
- 01同じ値を調べる条件のリファクタリング
- 02enum や sealed 型の結果処理
- 03無効値や nullable 状態を主経路から除外
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ chrisbanes/ skills --skill kotlin-control-flowインストール後、Claude Code で/kotlin-control-flowを入力して読み込まれたか確認します。
詳細
Kotlin の制御フロー
基本原則
分類する値が明確に分かるようにし、分岐固有の述語はその分岐内に置き、閉じた値域の網羅性はコンパイラーに証明させます。
手順
-
分類する値に名前を付けます。すべての分岐がその値をテストするなら、
when (subject)を使います。それ以外の場合は、subject のないwhenまたはifチェーンを使います。 -
分岐の形を選びます。
コードの形 推奨 1 つの値を分類する when (subject)関連のないブール条件 subject のない whenまたはif/else主条件と分岐固有の述語 ガード条件 メインの処理経路より前に無効な入力を処理する 早期リターン、 require、またはcheck閉じた値域で値を返す 網羅的な when式開いた入力または意図的なフォールバック 明示的な else -
ガードは、subject のある
whenで主条件の後にのみ使います。追加の述語がその分岐に属し、ガードなしの分岐でも主条件を処理する場合に使います。ガード付きの分岐を先に置きます。カンマで区切られた条件のうち 1 つにガードを付けるのではなく、条件を分割します。ガードは Kotlin 2.2 以降で安定しています。明示的なlanguageVersionの設定があればそれに従います。設定がない場合は、ビルドファイルまたはバージョンカタログに記載されたプロジェクトの Kotlin バージョンでサポートを確認できます。そのため、さらなる証拠がないことを理由にガードの使用を避けないでください。 -
閉じた列挙型、Boolean、sealed 型、または閉じた nullable 型では、すべてのケースを列挙し、
elseを省略します。オブジェクトは値で、クラスや data class のサブタイプはisで照合します。入力が開いたサーバー/プラットフォームの値である場合や、実際にフォールバックやログ出力が必要な場合は、elseを残します。catch-all にまとめるサブタイプも含め、データを持つ各サブタイプにそれぞれ独自のis分岐を設けます。そのデータがマッピングや安全な処理に影響する場合は、公開される値が一定のままでも、指摘や変更にスマートキャストされたメンバーアクセスを含める必要があります。is Outcome.Failed -> safeFailureLabel(outcome.reason)isチェックによってoutcomeがスマートキャストされるため、この分岐ではキャストせずにreasonを使えます。ヘルパー名は例示です。ケース名を列挙するだけ、または元の値を呼び出し元に確認させるだけでは、分岐の案内として不十分です。データが結果に影響しない場合は、そのis分岐で現在の値を維持し、データの用途を作り出さないでください。 -
早期リターンは、メインの処理経路から無効な状態または nullable な状態を取り除く場合にのみ使います。クリーンアップ、トランザクション、エラー処理を表すネストは維持します。
-
as、!!、可変の一時変数、重複したキャストを使わずに、スマートキャストが引き続き機能することを確認します。機能しない場合は、元の形を維持するか、より小さなリファクタリングにとどめます。 -
プロジェクト固有のビルドツールでコンパイルとテストを行います。Gradle プロジェクトでは、Gradle の実行ワークフローを使い、生の Gradle は使わないでください。失敗した場合は、該当する最も小さな前の手順に戻るか、以前の形を維持します。subject、フォールバック、関連する分岐データが読み手に明確で、結果の形がより読みやすくなったら完了です。
レシピ
ネストした if の代わりに、1 つのケースを絞り込むガード付き分岐を使います。
return when (event) {
is Event.Message if event.isUnread -> Row.Highlighted(event.message)
is Event.Message -> Row.Normal(event.message)
Event.Empty -> Row.Empty
}
繰り返し現れる条件で 1 つの値を分類する場合は、subject のある when を使います。より大きな分類の 1 ケースとして null がある場合は、分岐に含めます。
return when (val selected = selection) {
null -> SelectionUi.None
is Selection.Single if selected.item.isArchived -> SelectionUi.Archived(selected.item)
is Selection.Single -> SelectionUi.Active(selected.item)
is Selection.Multiple -> SelectionUi.Count(selected.items.size)
}
サポートされていない Kotlin バージョンでガードを導入したり、関連のないブールチェックを無理に subject のある when にしたり、開いた値域のフォールバックを削除したり、クリーンアップ、トランザクション、エラーを分かりにくくするコードを平坦化したりしないでください。
関連項目
- Kotlin の並行処理と Flow — 状態/イベントのプリミティブ。
- Kotlin API 設計 — 共通コードでの明示的な分岐。