Funkcjonalne modelowanie domeny za pomocą typów podstawowych Arrow
Modeluj złożone domeny za pomocą Either, NonEmptyList oraz akumulowania zweryfikowanych błędów.
Funkcjonalne modelowanie domeny za pomocą typów podstawowych Arrow to bezpłatna lekcja Kotlin Academy na CoddyKit. To lekcja 4 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Kotlin Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Kotlin Academy zawiera 4 lekcji w sumie.
Czym jest funkcyjne modelowanie domeny?
Funkcyjne modelowanie domeny wykorzystuje typy algebraiczne (Either, Option, klasy sealed) do zapisywania reguł biznesowych w typach. Nieprawidłowe stany stają się niemożliwe do utworzenia już na etapie kompilacji, a błędy są jawnie określone w sygnaturach funkcji — bez ukrytych wyjątków.
Obiekty wartości za pomocą klas inline/value
Używaj klas wartości Kotlinu do opakowywania typów prostych i zapobiegania obsesji na punkcie typów prostych. System typów odrzuci przekazanie UserId w miejscu, w którym oczekiwany jest 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!Klasy sealed dla błędów domenowych
Modeluj błędy jako hierarchie klas sealed. Każda podklasa zawiera tylko dane istotne dla danego przypadku błędu:
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: agregowanie wielu błędów
Jeśli chcesz zgłosić wszystkie błędy walidacji naraz, a nie tylko pierwszy, użyj Validated z Arrow (lub zipOrAccumulate w Raise DSL). Błędy zostaną zagregowane w 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()Łączenie walidacji
Używaj zip(), aby łączyć wiele wyników typu Validated. Jeśli którykolwiek z nich ma status Invalid, wszystkie błędy zostaną zagregowane:
val result: Validated<NonEmptyList<String>, User> =
validateName(name).zip(validateEmail(email)) { n, e -> User(n, e) }
.mapLeft { it }Uniemożliwianie reprezentowania nieprawidłowych stanów
Zamiast klasy User z nullable email i flagą isVerified użyj podklas sealed, aby system typów uniemożliwił dostęp do adresu e-mail niezweryfikowanego użytkownika:
sealed class User {
data class Unverified(val id: UserId, val pendingEmail: String) : User()
data class Verified(val id: UserId, val email: String) : User()
}Inteligentne konstruktory
Używaj fabrycznych funkcji obiektu companion, które zwracają Either lub Option, zamiast publicznych konstruktorów. Dzięki temu instancje zawsze będą znajdować się w prawidłowym stanie:
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()
}
}Łączenie Either i Option w potoku operacji
Rzeczywista operacja domenowa zazwyczaj łączy wyszukiwanie w repozytoriach (Option) z walidacją (Either). Użyj bloku either { } biblioteki Arrow wraz z .bind(), aby płynnie je komponować:
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))
}Niezmienność i copy
Encje domenowe powinny być niezmienne. Używaj klas danych i copy(), aby wyprowadzać nowe stany. Lens biblioteki Arrow (z arrow-optics) umożliwia wygodne zagnieżdżone aktualizacje bez mutowania danych:
val updated = user.copy(email = "new@example.com")
// Arrow Optics:
val emailLens = User.email
val updatedWithLens = emailLens.set(user, "new@example.com")Konfiguracja bezpieczna pod względem typów za pomocą klas sealed
Modeluj warianty konfiguracji aplikacji za pomocą klas sealed, aby kompilator wymuszał obsługę każdego przypadku:
sealed class DbConfig {
data class Postgres(val url: String, val user: String, val pass: String) : DbConfig()
data class InMemory(val dbName: String = "test") : DbConfig()
}Korzyści w skrócie
Funkcyjne modelowanie domeny z użyciem podstawowych typów Arrow zapewnia:
- Brak wyjątków null pointer w kodzie domenowym
- Błędy widoczne w sygnaturach funkcji
- Kompletne sprawdzanie hierarchii sealed za pomocą
when - Funkcje czyste, które można łatwo testować
- Kod, który sam dokumentuje swoje działanie
Szybkie sprawdzenie
Jaka jest główna korzyść z używania hierarchii sealed class dla błędów domenowych zamiast zgłaszania wyjątków?
Podsumowanie: funkcyjne modelowanie domeny za pomocą podstawowych typów Arrow
Najważniejsze informacje:
- Klasy wartości zapobiegają obsesji na punkcie typów prostych
- Hierarchie błędów sealed zapewniają kompletną i bezpieczną typowo obsługę przypadków niepowodzenia
- Inteligentne konstruktory gwarantują prawidłowe instancje
either { }.bind()przejrzyście łączy operacje, które mogą zakończyć się niepowodzeniem- Niezmienne dane +
copy()/ Arrow Optics zapewniają bezpieczne przejścia między stanami
Ucz się Kotlin dzięki korepetycjom AI — za darmo
Pisz i uruchamiaj kod w przeglądarce, otrzymuj natychmiastową pomoc od korepetytora AI dostępnego 24/7 i kontynuuj naukę w sieci lub w aplikacji.
- Kursy
- 51
- Lekcje
- 203
Często zadawane pytania
Czy lekcja „Funkcjonalne modelowanie domeny za pomocą typów podstawowych Arrow” jest bezpłatna?
Tak — pełny tekst „Funkcjonalne modelowanie domeny za pomocą typów podstawowych Arrow” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Kotlin Academy, przejdź na CoddyKit PRO. Kurs Kotlin Academy zawiera 4 lekcji w sumie.
Co nauczysz się w „Funkcjonalne modelowanie domeny za pomocą typów podstawowych Arrow”?
Modeluj złożone domeny za pomocą Either, NonEmptyList oraz akumulowania zweryfikowanych błędów. Ćwiczysz Kotlin Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć Kotlin Academy?
Nie wymagamy żadnego doświadczenia. Kotlin Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 4 z 4.
Ile czasu zajmuje lekcja „Funkcjonalne modelowanie domeny za pomocą typów podstawowych Arrow”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji Kotlin Academy?
Tak. Każda lekcja Kotlin Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.
Wszystkie lekcje w tym kursie
- Either : typowana obsługa błędów bez wyjątków
- DSL Raise w Arrow: składanie typowanych błędów
- Option i nullable: kiedy używać każdego z nich
- Funkcjonalne modelowanie domeny za pomocą typów podstawowych Arrow