Arrowのコア型による関数型ドメインモデリング
Either、NonEmptyList、検証済みエラーの蓄積を使用して、複雑なドメインをモデル化します。
「Arrowのコア型による関数型ドメインモデリング」はCoddyKit上の無料Kotlin Academyレッスンです。 これはレッスン4/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはKotlin Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Kotlin Academyコースには全4レッスンが含まれています。
関数型ドメインモデリングとは
関数型ドメインモデリングでは、代数的データ型(Either、Option、sealed class)を使って、ビジネスルールを型に組み込みます。無効な状態はコンパイル時に表現できなくなり、エラーは関数シグネチャで明示されます。隠れた例外はありません。
インラインクラス/値クラスによる値オブジェクト
プリミティブ型への過度な依存を防ぐために、Kotlin の値クラスでプリミティブ型をラップしてください。PostId が必要な場所に UserId を渡すと、型システムによって拒否されます:
@JvmInline value class UserId(val value: Long)
@JvmInline value class PostId(val value: Long)
fun findUser(id: UserId): Either<UserError, User> = TODO()
// findUser(PostId(1L)) // Compile error!ドメインエラーにsealed classを使う
エラーを sealed class の階層としてモデル化してください。各サブクラスには、そのエラーケースに関係するデータだけを持たせます:
sealed class UserError {
data class NotFound(val id: UserId) : UserError()
data class EmailTaken(val email: String) : UserError()
data class ValidationFailed(val field: String, val reason: String) : UserError()
}Validated:複数のエラーを蓄積する
最初のエラーだけでなく、すべての検証エラーを一度に報告したい場合は、Arrow の Validated(または Raise DSL の zipOrAccumulate)を使用してください。エラーは NonEmptyList に蓄積されます:
import arrow.core.Validated
import arrow.core.valid
import arrow.core.invalid
fun validateName(name: String): Validated<String, String> =
if (name.isNotBlank()) name.valid() else "Name is blank".invalid()検証を組み合わせる
複数の Validated 結果を組み合わせるには zip() を使用してください。いずれかが Invalid の場合は、すべてのエラーが蓄積されます:
val result: Validated<NonEmptyList<String>, User> =
validateName(name).zip(validateEmail(email)) { n, e -> User(n, e) }
.mapLeft { it }不正な状態を表現不可能にする
null 許容の email と isVerified フラグを持つ User の代わりに、sealed class のサブクラスを使用してください。これにより、未検証ユーザーのメールアドレスにアクセスできないよう、型システムで防止できます:
sealed class User {
data class Unverified(val id: UserId, val pendingEmail: String) : User()
data class Verified(val id: UserId, val email: String) : User()
}スマートコンストラクター
公開コンストラクターの代わりに、Either または Option を返す companion object のファクトリ関数を使用してください。これにより、インスタンスが常に有効な状態になることを保証できます:
class Email private constructor(val value: String) {
companion object {
fun of(raw: String): Either<String, Email> =
if (raw.contains("@") && raw.length <= 255) Email(raw).right()
else "Invalid email format".left()
}
}パイプラインでEitherとOptionを組み合わせる
実際のドメイン操作では通常、リポジトリ検索(Option)と検証(Either)を連鎖させます。Arrow の either { } ブロックと .bind() を使用すると、これらを自然な流れで組み合わせられます:
fun createPost(authorId: UserId, title: String, body: String): Either<PostError, Post> = either {
val author = userRepo.findById(authorId).toEither { PostError.AuthorNotFound }.bind()
val validTitle = validateTitle(title).bind()
postRepo.save(Post(author, validTitle, body))
}不変性とcopy()
ドメインエンティティは不変にしてください。データクラスと copy() を使って、新しい状態を生成します。Arrow の Lens(arrow-optics の一部)を使うと、変更を伴わずにネストされた値を簡潔に更新できます:
val updated = user.copy(email = "new@example.com")
// Arrow Optics:
val emailLens = User.email
val updatedWithLens = emailLens.set(user, "new@example.com")sealed classによる型安全な設定
アプリケーション設定のバリエーションを sealed class でモデル化すると、コンパイラによってすべてのケースの処理が強制されます:
sealed class DbConfig {
data class Postgres(val url: String, val user: String, val pass: String) : DbConfig()
data class InMemory(val dbName: String = "test") : DbConfig()
}メリットの概要
Arrow のコア型を使った関数型ドメインモデリングには、次のメリットがあります:
- ドメインコードで null ポインタ例外が発生しません
- エラーが関数シグネチャに現れます
- sealed class の階層に対する
whenの網羅的なチェックが可能です - テスト可能な純粋関数を使用できます
- コード自体が仕様を説明します
確認問題
例外をスローする方法と比べて、ドメインエラーに sealed class の階層を使う主なメリットは何ですか?
復習:Arrowのコア型による関数型ドメインモデリング
要点:
- 値クラスによって、プリミティブ型への過度な依存を防げます
- sealed class によるエラー階層によって、失敗ケースを網羅的かつ型安全に扱えます
- スマートコンストラクターによって、有効なインスタンスだけを生成できます
either { }.bind()によって、失敗する可能性のある操作を簡潔に組み合わせられます- 不変データと
copy()/Arrow Optics によって、安全に状態を遷移できます
よくある質問
「Arrowのコア型による関数型ドメインモデリング」レッスンは無料ですか?
はい。「Arrowのコア型による関数型ドメインモデリング」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Kotlin Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Kotlin Academyコースには全4レッスンが含まれています。
「Arrowのコア型による関数型ドメインモデリング」で何を学びますか?
Either、NonEmptyList、検証済みエラーの蓄積を使用して、複雑なドメインをモデル化します。 ブラウザで直接実行するハンズオンコードでKotlin Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
Kotlin Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのKotlin Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン4/4です。
「Arrowのコア型による関数型ドメインモデリング」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このKotlin Academyレッスンでコードを書いて実行できますか?
はい。すべてのKotlin Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- Either :例外を使わない型付きエラー処理
- Arrow Raise DSL:型付きエラーの合成
- OptionとNullable:それぞれを使う場面
- Arrowのコア型による関数型ドメインモデリング