Modellazione funzionale del dominio con i tipi fondamentali di Arrow
Modelli domini complessi utilizzando Either, NonEmptyList e l'accumulo degli errori tramite validazione.
Modellazione funzionale del dominio con i tipi fondamentali di Arrow è una lezione Kotlin Academy gratuita su CoddyKit. Questa è la lezione 4 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Kotlin Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Kotlin Academy include 4 lezioni in totale.
Che cos'è la modellazione funzionale del dominio?
La modellazione funzionale del dominio utilizza tipi algebrici (Either, Option, classi sealed) per codificare le regole di business nei tipi. Gli stati non validi diventano impossibili da rappresentare in fase di compilazione e gli errori sono espliciti nelle firme delle funzioni: non ci sono eccezioni nascoste.
Value object con classi inline/value
Utilizzi le value class di Kotlin per racchiudere i primitivi e prevenire la primitive obsession. Il sistema dei tipi rifiuta di passare un UserId quando è previsto un PostId:
@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!Classi sealed per gli errori di dominio
Modelli gli errori come gerarchie di classi sealed. Ogni sottoclasse contiene solo i dati pertinenti al relativo caso di errore:
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: accumulare più errori
Quando desidera segnalare tutti gli errori di validazione contemporaneamente, anziché solo il primo, utilizzi Validated di Arrow (oppure zipOrAccumulate nel Raise DSL). Gli errori vengono accumulati in una 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()Comporre le validazioni
Utilizzi zip() per combinare più risultati Validated. Se uno qualsiasi è Invalid, tutti gli errori vengono accumulati:
val result: Validated<NonEmptyList<String>, User> =
validateName(name).zip(validateEmail(email)) { n, e -> User(n, e) }
.mapLeft { it }Rendere impossibili da rappresentare gli stati non validi
Anziché utilizzare un User con un email nullable e un flag isVerified, utilizzi sottoclassi sealed, in modo che il sistema dei tipi impedisca di accedere all'email di un utente non verificato:
sealed class User {
data class Unverified(val id: UserId, val pendingEmail: String) : User()
data class Verified(val id: UserId, val email: String) : User()
}Costruttori intelligenti
Utilizzi funzioni factory dell'oggetto companion che restituiscono Either o Option invece di costruttori pubblici. In questo modo le istanze sono sempre in uno stato valido:
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()
}
}Combinare Either e Option in una pipeline
Una vera operazione di dominio concatena in genere le ricerche nei repository (Option) con le validazioni (Either). Utilizzi il blocco either { } di Arrow con .bind() per comporle in modo fluido:
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))
}Immutabilità e copy
Le entità del dominio devono essere immutabili. Utilizzi data class e copy() per derivare nuovi stati. La Lens di Arrow (da arrow-optics) consente di aggiornare comodamente strutture annidate senza mutazioni:
val updated = user.copy(email = "new@example.com")
// Arrow Optics:
val emailLens = User.email
val updatedWithLens = emailLens.set(user, "new@example.com")Configurazione type-safe con classi sealed
Modelli le varianti della configurazione dell'applicazione con classi sealed, in modo che il compilatore obblighi a gestire ogni caso:
sealed class DbConfig {
data class Postgres(val url: String, val user: String, val pass: String) : DbConfig()
data class InMemory(val dbName: String = "test") : DbConfig()
}Vantaggi in sintesi
La modellazione funzionale del dominio con i tipi fondamentali di Arrow offre:
- Nessuna eccezione di puntatore nullo nel codice del dominio
- Errori visibili nelle firme delle funzioni
- Controlli
whenesaustivi sulle gerarchie sealed - Funzioni pure facilmente testabili
- Codice autoesplicativo
Verifica rapida
Qual è il principale vantaggio di utilizzare una gerarchia di sealed class per gli errori di dominio invece di lanciare eccezioni?
Riepilogo: modellazione funzionale del dominio con i tipi fondamentali di Arrow
Punti chiave:
- Le value class prevengono la primitive obsession
- Le gerarchie sealed degli errori rendono esaustivi e type-safe i casi di errore
- I costruttori intelligenti garantiscono istanze valide
either { }.bind()compone in modo chiaro le operazioni che possono fallire- Dati immutabili +
copy()/ Arrow Optics per transizioni di stato sicure
Domande Frequenti
La lezione «Modellazione funzionale del dominio con i tipi fondamentali di Arrow» è gratuita?
Sì — il testo completo di «Modellazione funzionale del dominio con i tipi fondamentali di Arrow» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Kotlin Academy, passa a CoddyKit PRO. Il corso Kotlin Academy include 4 lezioni in totale.
Cosa imparerò in «Modellazione funzionale del dominio con i tipi fondamentali di Arrow»?
Modelli domini complessi utilizzando Either, NonEmptyList e l'accumulo degli errori tramite validazione. Eserciti Kotlin Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.
Ho bisogno di esperienza per iniziare Kotlin Academy?
Non è richiesta alcuna esperienza precedente. Kotlin Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 4 di 4.
Quanto tempo richiede la lezione «Modellazione funzionale del dominio con i tipi fondamentali di Arrow»?
La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.
Posso scrivere ed eseguire codice in questa lezione Kotlin Academy?
Sì. Ogni lezione Kotlin Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.
Tutte le lezioni di questo corso
- Either : gestione tipizzata degli errori senza eccezioni
- DSL Raise di Arrow: composizione degli errori tipizzati
- Option e nullable: quando utilizzare ciascuno
- Modellazione funzionale del dominio con i tipi fondamentali di Arrow