Result Pattern Nedir? Neden Önemli?

Result Pattern, metotlarınızın başarılı mı yoksa hatalı mı sonuçlandığını tek bir yapı içinde tutmanızı sağlar. Böylece:

  • Tek Tip Dönüş: Hem veri hem de işlem sonucunu tek bir sınıfla dönebilirsiniz.
  • Hata Mesajı ve Kod: Her başarısızlık durumunda kullanıcıya veya log’a ayrıntılı bilgi iletebilirsiniz.
  • Akıcı Zincirleme: Birden çok işlemi ardışık çağırırken, hata durumunda akışı kesip geriye dönmek kolaylaşır.

Avantajlar & Dezavantajlar

Avantajlar

  1. Tutarlılık: Tüm servisler aynı Result<T> yapısını kullanır.
  2. Okunabilirlik: Hata kontrolü tek bir yerde, if-else’lerle dağılmaz.
  3. Zincirleme (Chaining): Başarısız olan bir adım, sonraki adımları otomatik atlayabilir.

Dezavantajlar

  1. İlave Tip: Her metot dönüşü için generic Result<T> sınıfı yazmanız gerekir.
  2. Öğrenme Eğrisi: Bazı geliştiriciler için yeni bir pattern’e alışmak zaman alabilir.

Pratik Not: Basit CRUD metotlarında doğrudan Task<T> dönmek yeterliyken, iş kuralları ve validasyon içeren metotlarda Result Pattern kullanmak uzun vadede kolaylık sağlar.

.NET Core Örnek Uygulama

1. Result Sınıfı Tasarımı

public class Result
{
    public bool IsSuccess { get; }
    public string Error { get; }

    protected Result(bool isSuccess, string error)
    {
        IsSuccess = isSuccess;
        Error = error;
    }

    public static Result Success() => new Result(true, null);

    public static Result Failure(string error) => new Result(false, error);
}

public class Result<T> : Result
{
    public T Value { get; }

    private Result(T value) : base(true, null)
    {
        Value = value;
    }

    private Result(string error) : base(false, error) { }

    public static Result<T> Success(T value) => new Result<T>(value);

    public static new Result<T> Failure(string error) => new Result<T>(error);
}

2. Servis Metodunda Kullanımı

public class UserService
{
    public async Task<Result<UserDto>> GetUserByIdAsync(int id)
    {
        var user = await _repository.GetByIdAsync(id);
        if (user == null)
            return Result<UserDto>.Failure("Kullanıcı bulunamadı.");

        var dto = _mapper.Map<UserDto>(user);
        return Result<UserDto>.Success(dto);
    }

    public async Task<Result> UpdateUserEmailAsync(int id, string email)
    {
        var user = await _repository.GetByIdAsync(id);
        if (user == null)
            return Result.Failure("Kullanıcı bulunamadı.");

        if (!email.Contains("@"))
            return Result.Failure("Geçersiz e-posta adresi.");

        user.Email = email;
        _repository.Update(user);
        await _unitOfWork.CommitAsync();
        return Result.Success();
    }
}

Gerçek Projelerde Dikkat Edilmesi Gerekenler

  • Exception vs Result: İş mantığı hatalarını Result.Failure() ile yönetin; altyapı hatalarını (DbException vb.) ise global exception handler’da yakalayın.
  • Hata Kodu Standardı: Tek bir metin yerine Error’a enum veya kod (“USER_NOT_FOUND”) eklemek, front-end ile anlaşmayı kolaylaştırır.
  • Zincirleme Akış:
var result = await service.UpdateUserEmailAsync(id, email);
if (!result.IsSuccess)
    return BadRequest(result.Error);
  • Loglama: Başarısız Result döndüğünde, özgün hata mesajını ve bağlamı log’layın.

Servis Katmanına Entegrasyon

public class AccountController : ControllerBase
{
    private readonly UserService _userService;

    public AccountController(UserService userService)
    {
        _userService = userService;
    }

    [HttpPut("{id}/email")]
    public async Task<IActionResult> UpdateEmail(int id, [FromBody] string email)
    {
        var result = await _userService.UpdateUserEmailAsync(id, email);
        if (!result.IsSuccess)
            return BadRequest(new { Error = result.Error });

        return Ok();
    }
}

İleri Okuma ve Kaynaklar

Sonuç

Result Pattern, .NET projelerinde hata yönetimini ve return akışını tutarlı hale getirir. Basit CRUD işlemlerinde ihtiyaç duymayabilirsiniz, ancak iş kuralları ve birçok validasyon içeren senaryolarda kodunuzun temiz ve okunabilir kalmasını sağlar.

By tanju.bozok

Software Architect, Developer, and Entrepreneur

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir