Modelagem funcional de domínios com os tipos centrais do Arrow
Modele domínios complexos usando Either, NonEmptyList e acumulação de erros validados.
Modelagem funcional de domínios com os tipos centrais do Arrow é uma aula grátis de Kotlin Academy no CoddyKit. Esta é a aula 4 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Kotlin Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Kotlin Academy inclui 4 aulas no total.
O que é modelagem funcional de domínio
A modelagem funcional de domínio usa tipos algébricos (Either, Option, classes seladas) para codificar regras de negócio nos tipos. Estados inválidos tornam-se impossíveis de representar em tempo de compilação, e os erros ficam explícitos nas assinaturas das funções — sem exceções ocultas.
Objetos de valor com classes inline/de valor
Use classes de valor do Kotlin para encapsular tipos primitivos e evitar a obsessão por tipos primitivos. O sistema de tipos rejeita passar um UserId onde se espera um 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!Classes seladas para erros de domínio
Modele os erros como hierarquias de classes seladas. Cada subclasse contém apenas os dados relevantes para aquele caso de erro:
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: acumulando vários erros
Quando quiser relatar todos os erros de validação de uma só vez, e não apenas o primeiro, use Validated do Arrow (ou zipOrAccumulate na DSL Raise). Ele acumula os erros em uma 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()Compondo validações
Use zip() para combinar vários resultados Validated. Se algum deles for Invalid, todos os erros serão acumulados:
val result: Validated<NonEmptyList<String>, User> =
validateName(name).zip(validateEmail(email)) { n, e -> User(n, e) }
.mapLeft { it }Tornando estados ilegais impossíveis de representar
Em vez de usar um User com um email anulável e um sinalizador isVerified, use subclasses seladas para que o sistema de tipos impeça o acesso ao e-mail de um usuário não verificado:
sealed class User {
data class Unverified(val id: UserId, val pendingEmail: String) : User()
data class Verified(val id: UserId, val email: String) : User()
}Construtores inteligentes
Use funções de fábrica do objeto companheiro que retornem Either ou Option, em vez de construtores públicos. Isso garante que as instâncias estejam sempre em um estado válido:
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()
}
}Combinando Either e opção em uma cadeia
Uma operação de domínio real normalmente encadeia consultas a repositórios (Option) com validações (Either). Use o bloco either { } do Arrow com .bind() para compô-las de forma fluida:
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))
}Imutabilidade e cópia
As entidades de domínio devem ser imutáveis. Use classes de dados e copy() para derivar novos estados. O Lens do Arrow (de arrow-optics) permite atualizações aninhadas práticas sem mutação:
val updated = user.copy(email = "new@example.com")
// Arrow Optics:
val emailLens = User.email
val updatedWithLens = emailLens.set(user, "new@example.com")Configuração com segurança de tipos usando classes seladas
Modele as variantes de configuração da aplicação com classes seladas para que o compilador obrigue você a tratar cada 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()
}Benefícios em resumo
A modelagem funcional de domínio com os tipos fundamentais do Arrow oferece:
- Nenhuma exceção de ponteiro nulo no código de domínio
- Erros visíveis nas assinaturas das funções
- Verificações exaustivas de
whennas hierarquias seladas - Funções puras fáceis de testar
- Código autodocumentado
Verificação rápida
Qual é o principal benefício de usar uma hierarquia de sealed class para erros de domínio em vez de lançar exceções?
Recapitulação: modelagem funcional de domínio com os tipos fundamentais do Arrow
Principais aprendizados:
- Classes de valor evitam a obsessão por tipos primitivos
- Hierarquias seladas de erros tornam os casos de falha exaustivos e seguros quanto aos tipos
- Construtores inteligentes garantem instâncias válidas
either { }.bind()compõe operações sujeitas a falha de forma limpa- Dados imutáveis +
copy()/ Arrow Optics para transições de estado seguras
Perguntas Frequentes
A aula “Modelagem funcional de domínios com os tipos centrais do Arrow” é grátis?
Sim — o texto completo de “Modelagem funcional de domínios com os tipos centrais do Arrow” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Kotlin Academy, atualize para CoddyKit PRO. O curso de Kotlin Academy inclui 4 aulas no total.
O que vou aprender em “Modelagem funcional de domínios com os tipos centrais do Arrow”?
Modele domínios complexos usando Either, NonEmptyList e acumulação de erros validados. Você pratica Kotlin Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar Kotlin Academy?
Nenhuma experiência prévia é necessária. Kotlin Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 4 de 4.
Quanto tempo leva a aula “Modelagem funcional de domínios com os tipos centrais do Arrow”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de Kotlin Academy?
Sim. Cada aula de Kotlin Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.
Todas as aulas deste curso
- Either : tratamento de erros tipado sem exceções
- DSL Raise do Arrow: composição de erros tipados
- Option e Nullable: quando usar cada um
- Modelagem funcional de domínios com os tipos centrais do Arrow