Result Type: nedir, Result kapsayıcı türü ve mobil geliştirmede nasıl çalışır

Yazar: IT Sectr Yayınlanma: 2026-05-26 Okuma süresi: 9 dk

Result Type — başarı (Success) veya hata (Failure) ile tamamlanabilen bir işlemin sonucunu temsil eden bir kapsayıcı türdür. İstisnaların aksine, Result hatayı yığın açma olmadan normal bir değer olarak iletir ve beklenen hataların işlenmesini daha güvenli ve birleştirilebilir hale getirir. Apple Swift Documentation (2026)'ya göre, Swift'teki Result<Success, Failure>, program yürütmeyi kesintiye uğratmadan map ve flatMap aracılığıyla otomatik hata işleme ile işlemleri zincirlemenize olanak tanır.

Önemli Noktalar

  • Result Type — iki durumlu genel bir kapsayıcı: Success (veri) ve Failure (hata), yığın açma olmadan
  • Swift'te Result<Success, Failure> — map, flatMap, mapError ve get yöntemlerine sahip yerleşik bir tür
  • Kotlin'de Result<T> başarı veya Throwable'ı temsil eder, getOrNull, getOrDefault, fold işlevlerine sahiptir
  • Dart'ta standart Result<T> Dart 3.0'dan itibaren kullanılabilir, ayrıca fpdart paketinden Either
  • Kompozisyon map ve flatMap aracılığıyla Result döndüren birden çok işlemi iç içe kontroller olmadan birleştirmeye olanak tanır

Result Type Nedir?

Result Type, başarılı olabilen veya başarısız olabilen bir işlemin sonucunu kapsülleyen genel bir türdür. Bir hatanın normal akışı kesintiye uğrattığı ve bir catch bloğu bulmak için yığın açma gerektirdiği istisnaların aksine, Result hatayı normal bir değer olarak iletir — çağıran her zaman bir nesne alır ve onu nasıl ele alacağına karar verir. Bu, özellikle beklenen hatalar için kullanışlıdır: geçersiz giriş, iş kuralları, sunucu reddi; burada istisnalar çok ağır bir mekanizma olurdu.

Result kavramı, benzer türlerin Either (veya Left/Right) olarak adlandırıldığı işlevsel programlamadan gelir. Swift'te Result, Swift 5.0'da standart bir tür haline geldi; Kotlin'de Result<T> standart kütüphanede göründü; Dart 3.0'da yerleşik Result<T> tanıtıldı. Her uygulama, kapsayıcıyla çalışmak için yöntemler sağlar: map (başarı değerini dönüştürme), flatMap (Result işlevlerini zincirleme), mapError (hatayı dönüştürme), fold (her iki durumu da ele alma). Result Type, mobil geliştirmede işlevsel hata işlemenin temel taşıdır ve beklenen senaryolar için try-catch'e bir alternatiftir.

Result'un temel avantajı birleştirilebilirliktir. Her biri başarısız olabilen birden çok işlemi, iç içe try-catch blokları olmadan tek bir zincirde birleştirebilirsiniz. Zincirdeki herhangi bir işlem Failure ile başarısız olursa, tüm zincir kesintiye uğrar ve Failure döndürür — tek bir if koşulu veya catch bloğu olmadan. Bu, özellikle birden çok sıralı API isteği veya iş kuralı denetimi olan senaryolarda kodu doğrusal ve okunabilir hale getirir.

Swift'te Result

Swift'te, Result<Success, Failure> iki durumlu bir enum'dur: .success(Success) ve .failure(Failure), burada Failure Error protokolü tarafından kısıtlanmıştır. Swift Result, map, flatMap, mapError ve get yöntemlerine sahip tam işlevsel bir türdür. get özel bir yöntemdir: sonuç başarılıysa Success değerini döndürür ve Failure ise hatayı fırlatır. Bu, Result'un işlevsel ve istisna tabanlı stiller arasında bir köprü görevi görmesini sağlar: bir zincirde map/flatMap aracılığıyla işleme ve sonunda throws koduyla entegre olmak için do-catch ile get kullanma.

Result enum ve kapsamlı switch

Swift Result, genel parametrelere sahip bir enum'dur ve derleyicinin switch veya do-catch aracılığıyla kapsamlı işlemeyi zorlamasına olanak tanır. NetworkError enum'una yeni bir durum eklerseniz, derleyici bu durumun işlenmediği tüm switch ifadelerinde bir hata üretir. Kapsamlı denetim, Result'un istisnalara göre ana avantajıdır: derleyici, derleme zamanında tüm olası hataların hesaba katıldığını garanti eder. Buna karşılık, Swift'te istisnalar derleyici tarafından denetlenmez (yalnızca throws bildirilir, ancak hata türü bildirilmez).

swift
enum NetworkError: Error {
    case badURL
    case requestFailed(String)
    case decodingFailed
}

func fetchUser(id: Int) -> Result<User, NetworkError> {
    guard let url = URL(string: "https://api.example.com/users/\(id)") else {
        return .failure(.badURL)
    }
    let result = performRequest(url: url)
    switch result {
    case let .success(data):
        if let user = try? JSONDecoder().decode(User.self, from: data) {
            return .success(user)
        }
        return .failure(.decodingFailed)
    case let .failure(error):
        return .failure(.requestFailed(error.localizedDescription))
    }
}

// switch ile kullanım
let result = fetchUser(id: 42)
switch result {
case .success(let user):
    showUser(user)
case .failure(.badURL):
    logError("Invalid URL")
case .failure(.requestFailed(let msg)):
    showAlert(msg)
case .failure(.decodingFailed):
    logError("Decoding error")
}

Result<Success, Failure>, tür düzeyinde hatayı tiplemeye olanak tanır: fetchUser işlevi, NetworkError'un üç durumlu somut bir enum olduğu Result<User, NetworkError> döndürür. Çağıran, kapsamlı kapsamla switch aracılığıyla her durumu işler — derleyici tüm varyantların işlendiğini denetler. Kapsamlı switch, Result'un istisnalara göre önemli bir avantajıdır: derleyici, .badURL, .requestFailed veya .decodingFailed'i işlemeyi unutmayacağınızı garanti eder. İstisnalarda derleyici işleme gerektirmez ve kod incelemesinde eksik bir catch(.badURL) kolayca gözden kaçabilir.

Kotlin'de Result

Kotlin'de, Result<T> standart kütüphaneden başarıyı (T) veya hatayı (Throwable) temsil eden yerleşik bir türdür. Swift'in aksine, Kotlin Result somut bir hata türü belirtmeye izin vermez — yalnızca Throwable. Bu basitlik için yapılmıştır ancak when ifadesi aracılığıyla ek hata türü denetimi gerektirir. Kotlin Result, fold (her iki durumu işleme), getOrNull (başarı veya null), getOrDefault (başarı veya varsayılan), map, recover, andThen işlevlerini destekler. Kotlin'in bir özelliği: Result, işlev sınırları boyunca doğrudan yayılmak üzere tasarlanmamıştır — ek uyarlama olmadan Android SDK yöntemleri veya Kotlin Coroutines API için dönüş türü olarak kullanılamaz.

kotlin
fun parseJson(input: String): Result<JsonObject> {
    return runCatching {
        JsonParser.parseString(input).asJsonObject()
    }
}

fun validateEmail(email: String): Result<String> {
    return if (email.contains("@")) {
        Result.success(email.trim())
    } else {
        Result.failure(IllegalArgumentException("Invalid email"))
    }
}

data class SignupData(val name: String, val email: String)

fun processSignup(name: String, email: String): SignupResult {
    return validateEmail(email).fold(
        onSuccess = { validateName(name) },
        onFailure = { SignupResult.Error("Invalid email") }
    )
}

runCatching, Kotlin'de herhangi bir istisnayı yakalayan ve Result.failure döndüren kullanışlı bir sarmalayıcıdır. validateEmail, doğrulamaya bağlı olarak Result.success veya Result.failure döndürür. fold, her iki durumu da kompakt bir şekilde işler: Success'te sonraki doğrulama işlevi çağrılır; Failure'da SignupResult.Error döndürülür. Önemli: Kotlin Result, veri sınıfı alanlarında depolama veya askı işlevi sınırları boyunca doğrudan iletim için tasarlanmamıştır — Jetpack Compose veya MVVM'de UI durumlarını temsil etmek için özel sealed class'lar (Success/Error/Loading) kullanın.

Dart ve Flutter'da Result

Dart 3.0'dan itibaren standart kütüphane, yerleşik bir Result<T> içerir — iki kurucuya sahip sealed bir sınıf: T.ok() (başarı) ve Error.error() (Object ve StackTrace ile hata). Dart 3.0'dan önce, Flutter geliştiricileri dartz paketinden Either<L, R> veya özel sealed sınıflar kullanıyordu. Dart'taki yerleşik Result minimalisttir: doğrudan map/flatMap sağlamaz — bu işlevler when aracılığıyla veya genişletme yöntemleri kullanılarak uygulanmalıdır. Ciddi işlevsel işleme için, fpdart'tan Either, map, flatMap, mapLeft, fold, andThen ve bind işleçleri desteğiyle daha güçlü bir çözüm olmaya devam etmektedir.

fpdart'tan Either

Either<L, R>, fpdart paketinden sola eğilimli bir türdür; burada Left hatadır ve Right başarıdır. Yerleşik Result<T>'nin aksine, Either, tür parametresi düzeyinde (L) hatayı tipler ve derleme zamanında hata türü ayrımına olanak tanır. fpdart paketi, eksiksiz bir işlevsel birleştirici seti sağlar: map (Right -> Right), mapLeft (Left -> Left), flatMap (bind — iç içe Either), andThen (dönüşüm olmadan zincirleme), fold (Either'dan çıkış), getOrElse (varsayılan değer). İşlevsel yaklaşıma sahip Flutter uygulamaları için Either, fiili standarttır.

dart
import 'dart:convert';
import 'package:fpdart/fpdart.dart';

class UserService {
    Either<AppError, User> fetchUser(String id) {
        try {
            final response = await http.get(
                Uri.parse('https://api.example.com/users/$id')
            );
            if (response.statusCode == 200) {
                final user = User.fromJson(
                    json.decode(response.body)
                );
                return Either.of(user);
            }
            return Either.left(
                AppError.serverError(response.statusCode)
            );
        } on SocketException catch (e) {
            return Either.left(AppError.networkError(e.message));
        }
    }
}

// fold ile kullanım
final result = await service.fetchUser('42');
result.fold(
    (left)  => showError(left.message),
    (right) => showUser(right),
);

Either<L, R> (fpdart) sola eğilimli bir türdür: Left — hata, Right — başarı. fetchUser, AppError'un somut hata türlerine (serverError, networkError) sahip sealed bir sınıf olduğu Either<AppError, User> döndürür. fold her iki durumu da işler: ilk geri çağırma Left (hata) için, ikincisi Right (başarı) için. Dart 3.0'da yerleşik Result da fold'u destekler, ancak map/flatMap sağlamaz. Zincirler için fpdart'tan Either, map, flatMap (bind), mapLeft, andThen sağlar — hata kompozisyonu için eksiksiz bir işlevsel birleştirici seti.

map ve flatMap ile Result Kompozisyonu

Result'un istisnalara göre ana avantajı kompozisyondur. Her biri başarısız olabilen birden çok işleminiz varsa, bunları tek bir iç içe if veya try-catch olmadan map ve flatMap kullanarak zincirleyebilirsiniz. map başarı değerini dönüştürür: Result.success(x) -> Result.success(f(x)). flatMap (bind veya andThen olarak da adlandırılır), dönüşümün kendisinin bir Result döndürdüğü durumlar içindir: Result.success(x) -> f(x) -> Result<Y>. Herhangi bir adım Failure ile başarısız olursa, sonraki işlemler yürütülmez — zincir kesintiye uğrar.

kotlin
data class UserRequest(val userId: String, val token: String)

sealed class AuthError {
    data object InvalidToken : AuthError()
    data class UserNotFound(val id: String) : AuthError()
}

typealias Outcome<T> = Either<AuthError, T>

fun validateToken(token: String): Outcome<String> =
    if (token.isNotBlank()) Either.right(token)
    else Either.left(AuthError.InvalidToken)

fun fetchProfile(userId: String): Outcome<Profile> =
    if (userId == "42") Either.right(Profile("Alice"))
    else Either.left(AuthError.UserNotFound(userId))

// flatMap ile kompozisyon (fpdart'ta andThen)
val result = validateToken("abc123")
    .flatMap { fetchProfile("42") }
    .map { it.name }
    .getOrElse { "Guest" }

println(result) // "Alice"

Zincir: validateToken -> fetchProfile -> map name -> getOrElse “Misafir”. validateToken Left (InvalidToken) döndürürse, zincir kesintiye uğrar ve “Misafir” döndürür. fetchProfile Left (UserNotFound) döndürürse — yine “Misafir”. Her iki işlem de başarılı olursa — profil adı. flatMap, her biri başarısız olabilen Either işlevlerini tek bir doğrusal zincirde birleştirmeye olanak tanır. Geleneksel istisna stilinde, aynı kod iki iç içe try-catch veya null denetimi gerektirirdi. Sondaki getOrElse, kompozisyondan çıkış noktasıdır ve Failure durumu için varsayılan bir değer sağlar.

Result vs İstisnalar: Ne Zaman Hangisini Seçmeli

Result ve istisnalar birbirini dışlayan yaklaşımlar değildir. Her birinin kendi alanı vardır ve iyi tasarlanmış bir mobil uygulamada her ikisi de kullanılır. Seçim, hatanın beklenen mi yoksa beklenmeyen mi olduğuna bağlıdır. Result, iş mantığının bir parçası olan beklenen hatalar içindir: geçersiz e-posta, yetersiz bakiye, hız sınırı aşımı. İstisnalar, beklenmeyen sistem hataları içindir: ağ kaybı, OutOfMemoryError, NullPointerException (olmaması gereken ancak olan).

KriterResult Typeİstisnalar (Exception/Error)
Hata TürüBeklenen (iş mantığı)Beklenmeyen (sistem)
PerformansDüşük maliyet (yığın açma olmadan)Yüksek maliyet (yığın açma, StackTrace yakalama)
Kompozisyonmap/flatMap ile — doğrusal zincirlerİç içe try-catch — okuması zor
DerleyiciKapsamlı denetim (switch/when)Yalnızca Java'da denetlenen istisnalar
Yürütme AkışıKesintiye uğramaz — hata değer olarakEn yakın catch'e kadar kesintiye uğrar
TestKolay: sonucu kontrol et, isSuccess/isError iddia etassertThrows ve mock nesneleri gerektirir
Ne Zaman Kullanılmalıİş doğrulama, istek zincirleri, formlarAğ kaybı, G/Ç hataları, sistem çökmeleri

Pratik kural: hata uygulamanın normal iş akışının bir parçasıysa (kullanıcı geçersiz e-posta girdi, yetersiz izinler) — Result kullanın. Hata istisnai bir durumsa (sunucu yanıt vermiyor, bellek tükendi) — istisnaları kullanın. Mobil geliştirmede, katman sınırlarında Result (UseCase -> ViewModel) ve katmanlar içinde istisnalar (API -> Repository), her iki yaklaşımın avantajlarını birleştiren yaygın bir kalıptır.

İstisnalardan Result'a Geçiş Stratejisi

Mevcut istisna tabanlı kodu Result'a geçirmek kademeli olmalıdır. Katman sınırlarından başlayın: throws işlev çağrılarını Result { try ... } (Swift) veya runCatching { ... } (Kotlin) ile sarın. Ardından Repository ve UseCase yöntemlerinin dönüş türünü Result/Either ile değiştirin, iç uygulamayı istisnalarda bırakarak. Son adımda, ViewModel'i geçirin: istisnalı UiState yerine, Error'un bir Throwable değil, bir alan hatası depoladığı sealed sınıf UiState<T> (Loading, Success, Error) kullanın. Kademeli geçiş, genel bir yeniden düzenleme olmadan her katmanı ayrı ayrı test etmeye olanak tanır.

Sıkça Sorulan Sorular

Result Type, Optional/Option'dan nasıl farklıdır?

Optional (T?) bir değerin varlığını veya yokluğunu temsil eder — nil “veri yok” anlamına gelir ancak nedenini açıklamaz. Result (Success/Failure) yalnızca başarıyı değil, aynı zamanda somut bir türle hata nedenini de içerir. Yokluk normal olduğunda (örneğin, isteğe bağlı bir profil alanı) Optional kullanın ve hata bilgisine ihtiyacınız olduğunda Result kullanın.

Bir throws işlevi Result'a nasıl dönüştürülür?

Swift'te, Result { try throwingFunc() } kullanın — Result kurucusu bir throws closure alır. Kotlin'de, Result<T> döndüren runCatching { throwingFunc() } kullanın. Dart'ta, Result<T>.tryCatch(() => throwingFunc()) kullanın. Bu, istisna tabanlı kodun Result zincirlerine kolay entegrasyonunu sağlar.

Bilgi kaybetmeden Result'ta bir hata nasıl işlenir?

Başarı değerini değiştirmeden hata türünü dönüştürmek için mapError (Swift) veya mapLeft (Dart/Kotlin'de Either) kullanın. Her iki durumu da işlemeniz ve tek bir değer döndürmeniz gerekiyorsa, fold kullanın. Zinciri kesintiye uğratmadan günlüğe kaydetmek için onFailure (Kotlin) veya bir ön ek denetim noktası kullanın.

Kotlin'de Result, coroutines ile kullanılabilir mi?

Evet, ancak dikkatli olun. Kotlin Result<T>, K2 derleyicisi ve yansıma özellikleri nedeniyle askı işlevleri için doğrudan dönüş türü olarak önerilmez. Coroutines'de durumları temsil etmek için kendi sealed sınıfınız NetworkResult<T> (Success, Error, Loading) kullanın. İş mantığındaki beklenen hatalar için Arrow'dan Either daha güçlü bir alternatiftir.

Result bağlamında fold nedir?

fold, iki geri çağırma alan bir yöntemdir: onSuccess (başarı durumu için) ve onFailure (hata durumu için) ve herhangi bir türde tek bir değer döndürür. Bir switch ifadesinin eşdeğeridir ancak yüksek dereceli bir işlev olarak. fold, Result zincirlerinden ana çıkış noktasıdır; burada Success/Failure'ı UiState, kullanıcıya yönelik bir dize veya başka bir Result'a dönüştürürsünüz.

Özet

  • Result Type — yığın açma olmadan beklenen hataların güvenli işlenmesi için genel bir kapsayıcı (Success/Failure)
  • Swift'te Result<Success, Failure> (Failure: Error ile) tür güvenli hatalarla switch aracılığıyla kapsamlı denetim sağlar
  • Kotlin'de Result<T> başarıyı veya Throwable'ı sarar, runCatching throws kodundan kullanışlı bir kurucudur
  • Dart'ta yerleşik Result<T> (Dart 3.0) ve fpdart'tan Either<L, R> ile map/flatMap ile gelişmiş kompozisyon
  • Kompozisyon map (başarıyı dönüştürme) ve flatMap (Result işlevlerini zincirleme) ile iç içe try-catch'in yerini alır
  • Result vs istisnalar: Beklenen iş hataları için Result, beklenmeyen sistem arızaları için istisnalar
  • Yürütme akışını kesintiye uğratmadan açık ve test edilebilir hata işleme için katman sınırlarında Result kullanın

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.

Projeyi tartış

Ayrıca okuyun