Either, iki olası varyanttan birinin değerini temsil eden işlevsel bir türdür: hatalar için Left ve başarı için Right. İstisnaların aksine, Either hata yönetimini tür düzeyinde açık hale getirir ve try-catch blokları gerektirmez. Arrow, 2026'ya göre Either, yan etkiler olmadan başarısız olabilen işlemleri birleştirmek için Kotlin projelerinde yaygın olarak kullanılır.
Önemli Noktalar
Either, işlevsel programlamadan ödünç alınan, iki olası türden tam olarak birini temsil eden cebirsel bir veri türüdür. Hata yönetimi bağlamında, kural şudur: Left türü (Left) sorunun açıklamasını içerirken, Right türü (Right) başarılı bir sonucu içerir.
Either kavramı Haskell dilinden ve Either a b tür kategorisinden gelir; burada a sol değerin türü, b ise sağ değerin türüdür. Mobil geliştirmede Either, Kotlin için Arrow kütüphanesi ve Swift'teki işlevsel yaklaşımlar sayesinde popülerlik kazanmıştır.
Either'ın istisnalara göre temel avantajı, gizli yürütme yollarının olmamasıdır. Either döndüren bir işlev, imzasında başarısız olabileceğini açıkça bildirir. Derleyici, her iki varyantın da ele alındığını kontrol eder.
Exceptions fırlatmanın aksine Either, veri akışı şeffaflığını korur. Either döndüren bir işlevi çağırmak, çağıran tarafta try-catch gerektirmez — pattern-matching veya fold yeterlidir. Bu, her veri kaynağının Either döndürdüğü ve dönüşüm zincirlerinin map ve flatMap üzerinden oluşturulduğu tepkisel yaklaşımlı mimarilerde özellikle önemlidir.
Either iki alt türden oluşur: Left ve Right. Bir Either örneği, herhangi bir anda bunlardan yalnızca biri olabilir. Kotlin'deki tipik imza Either<E, A> şeklindedir; burada E hata türü ve A başarı değerinin türüdür.
Left başarısızlık durumunu temsil eder. İstisnaların aksine Left, yürütme akışını kesintiye uğratmaz — yalnızca ele alınması gereken bir değer döndürür. Hata türü herhangi bir şey olabilir: String, Int, özel bir sealed class veya bir alan modeli.
Right, işlemin doğru sonucunu içerir. İsim doğruluğu yansıtır — kural olarak Right, başarı anlamına gelir. map ve flatMap gibi dönüşümler Right'a uygulanarak her adımı kontrol etmeden hesaplama zincirleri oluşturulmasını sağlar.
flatMap, Either birleştirmenin ana mekanizmasıdır. Geçerli değer Right ise, flatMap iletilen işlevi uygular ve yeni bir Either döndürür. Left ise, flatMap dönüşümü atlar ve hatayı iletir. Bu davranışa kısa devre değerlendirmesi denir.
flatMap'in yanı sıra Either, hata dönüşümü için mapLeft, her iki varyantı tek bir yerde ele almak için fold ve varsayılan bir değerle değer çıkarmak için getOrElse işlevlerini destekler. Bu işlevler, basit çıkarmadan Kotlin eşyordamları veya Swift Combine'daki eşzamansız çağrılarla karmaşık birleştirmeye kadar tüm senaryoları kapsar.
fun parseInt(input: String): Either<String, Int> =
input.toIntOrNull()?.let { Right(it) }
?: Left("Dönüştürülemedi: $input")
fun divide(a: Int, b: Int): Either<String, Int> =
if (b == 0) Left("Sıfıra bölme")
else Right(a / b)
val result = parseInt("10")
.flatMap { divide(it, 2) }
Kotlin ekosisteminde Either, Arrow kütüphanesinde uygulanmıştır. Kotlin standart kütüphanesi Result sunar, ancak Either daha fazla esneklik sağlar: rastgele hata türü, flatMap ile birleştirme ve işlevsel desenler için destek.
Arrow, Kotlin için Either, Option, Validated ve diğer türleri ekleyen işlevsel bir kütüphanedir. Arrow.Either, iki alt sınıfı olan bir sealed class'tır: ArrowCore.Left ve ArrowCore.Right. Kütüphane ayrıca kullanışlı uzantılar da sağlar: .getOrElse(), .fold(), .mapLeft().
Gerçek bir senaryo düşünelim — bir Android uygulamasında olası hatalarla birlikte bir ağ isteği: ağ yok, sunucu hatası, geçersiz yanıt. Either, tüm varyantları tek bir dönüş türünde birleştirmeye olanak tanır.
sealed class NetworkError {
data class NoConnection(val message: String): NetworkError()
data class ServerError(val code: Int): NetworkError()
data class ParseError(val detail: String): NetworkError()
}
suspend fun fetchUser(id: String): Either<NetworkError, User> {
return try {
val response = api.getUser(id)
if (response.isSuccessful) {
Right(response.body()!!)
} else {
Left(NetworkError.ServerError(response.code()))
}
} catch (e: IOException) {
Left(NetworkError.NoConnection(e.message ?: ""))
}
}
Swift'te, 5.0 sürümünden itibaren, kavramsal olarak Either'a benzeyen ancak sınırlamaları olan yerleşik Result türü mevcuttur: hata Error protokolüne uygun olmalı ve başarı değeri tek bir türde olmalıdır. Swift'te Either, iki genel parametreli bir enum ile uygulanır.
Result<Success, Failure> Swift'in yerleşik türüdür ve Failure: Error şeklindedir. Either, hata türü üzerinde herhangi bir kısıtlama getirmez; String, özel yapılar veya iç içe enumlar aracılığıyla birden çok hata türünü saklamaya olanak tanır.
enum Either<E, A> {
case left(E)
case right(A)
func map<B>(_ transform: (A) -> B) -> Either<E, B> {
switch self {
case .left(let e): return .left(e)
case .right(let a): return .right(transform(a))
}
}
}
let result: Either<String, Int> = .right(42)
let mapped = result.map { $0 * 2 }
Either, istisnalar olmadan açık ve tür güvenli hata yönetimi gerektiren senaryolar için idealdir. Kotlin ve Swift ile mobil geliştirmedeki ana kullanım durumlarını ele alalım.
Yan etkileri olmayan basit işlemler için Either kullanmayın — normal bir dönüş değeri daha güvenilir ve okunması daha kolaydır. Ayrıca, başarısızlık beklenen bir senaryo değil de istisnai bir durum olduğunda Either gereksizdir.
Either, Kotlin'de eşyordamlarla çalışırken de etkilidir. Either döndüren bir işlev, iş parçacığını engellemeden fold veya mapLeft ile hata yönetimiyle bir eşyordam içinde çağrılabilir. Bu, her deponun Either döndürdüğü ve ViewModel'in sonucu UiState'e dönüştürdüğü MVVM mimarisine sahip Android uygulamalarında özellikle kullanışlıdır.
Either ile ilk kez tanışan geliştiriciler sıklıkla benzer hatalar yapar. En yaygın olanları ve bunlardan nasıl kaçınılacağını inceleyelim.
Sıkça Sorulan Sorular
Optional, bir değerin varlığını veya yokluğunu (Some/None) temsil eder, ancak yokluğun nedenini bildirmez. Either, hata için sol ve başarı için sağ olmak üzere iki somut tür sağlar ve başarısızlık bağlamının iletilmesine olanak tanır.
Java'da yerleşik Either yoktur, ancak Vavr ve functionaljava kütüphaneleri uygulama sağlar. Android geliştirmede, Vavr'dan Either, lambda'larla işlevsel bir stil için popüler bir alternatiftir.
Kotlin'de Sealed class, ikiden fazla varyant olduğunda veya farklı yapılara sahip olduklarında daha kullanışlıdır. İkili sonuç (hata/başarı) için Either daha derli topludur ve kullanıma hazır işlevsel birleştiriciler sağlar.
Either değiştirilemez ve varsayılan olarak iş parçacığı güvenlidir. Kotlin'de eşyordamlarla Either mükemmel şekilde birleşir: flatMap bir eşyordam kapsamı içinde çalışır ve hata yönetimi kilit gerektirmez.
Hayır. Either, beklenen hataları olan işlemler (ağ, doğrulama, iş mantığı) için uygundur. Yan etkileri olmayan basit getter'lar ve hesaplamalar için normal bir tür okuması daha kolaydır ve gereksiz karmaşıklık eklemez.
Özet
Anahtar teslim bir mobil uygulama geliştireceğiz
IT Sectr, 2017'den beri girişimler ve işletmeler için iOS ve Android uygulamaları oluşturmaktadır. Size danışmanlık yapacak ve en iyi çözümü önereceğiz.
Ayrıca okuyun