Repository deseni nedir? Neden kullanılır, ORM varken gerekli midir?

Cevap

Repository, domain nesnelerine erişimi bir koleksiyon benzeri arayüz (get_by_id, add, find_by_email) arkasına saklayan ve veri erişim detaylarını (SQL, ORM, API çağrısı) iş mantığından ayıran bir desendir.

Ne kazandırır?

  • Ayrıştırma: servis katmanı verinin PostgreSQL'den mi, cache'ten mi geldiğini bilmez.
  • Test edilebilirlik: iş mantığını gerçek veritabanı yerine bellekte çalışan sahte bir repository ile test edebilirsiniz.
  • Sorguların tek yerde toplanması: aynı sorgu kod tabanına dağılmaz.
from abc import ABC, abstractmethod
from dataclasses import dataclass

@dataclass
class User:
    id: int
    email: str

class UserRepository(ABC):
    @abstractmethod
    def get(self, user_id: int) -> User | None: ...
    @abstractmethod
    def add(self, user: User) -> None: ...

class SqlUserRepository(UserRepository):
    def __init__(self, conn):
        self.conn = conn
    def get(self, user_id):
        row = self.conn.execute("SELECT id, email FROM users WHERE id = ?", (user_id,)).fetchone()
        return User(*row) if row else None
    def add(self, user):
        self.conn.execute("INSERT INTO users (id, email) VALUES (?, ?)", (user.id, user.email))

class InMemoryUserRepository(UserRepository):   # testler için
    def __init__(self):
        self.items = {}
    def get(self, user_id):
        return self.items.get(user_id)
    def add(self, user):
        self.items[user.id] = user

class RegisterUser:
    def __init__(self, repo: UserRepository):
        self.repo = repo
    def execute(self, user_id, email):
        if self.repo.get(user_id):
            raise ValueError("Kullanıcı zaten var")
        self.repo.add(User(user_id, email))

ORM varken gerekli mi?

Tartışmalı bir konudur:

  • Entity Framework DbContext veya Spring Data JPA zaten repository/unit of work sağlar. Üzerine bir de generic repository (Repository<T> ile sadece CRUD) yazmak çoğu zaman gereksiz bir soyutlama katmanıdır.
  • Domain'e özgü repository'ler (OrderRepository.find_overdue()) ise sorguları anlamlı isimlerle toplamak için hâlâ değerlidir.

İlişkili desen: Unit of Work

Birden fazla repository'deki değişikliği tek bir transaction'da commit eder. ORM'lerde session/DbContext bu rolü üstlenir.

  1. Clean code nedir? Yaygın code smell'ler nelerdir?OrtaOOP & Tasarım DesenleriYazılım Müh.
  2. Dependency Injection nedir? IoC container ne işe yarar?ZorOOP & Tasarım DesenleriYazılım Müh.
  3. Strategy deseni nedir? if/else zincirlerini nasıl ortadan kaldırır?OrtaOOP & Tasarım DesenleriYazılım Müh.
  4. Observer deseni nedir? Gerçek hayatta nerelerde karşımıza çıkar?OrtaOOP & Tasarım DesenleriYazılım Müh.
  5. Factory deseni nedir? Ne zaman kullanılır?OrtaOOP & Tasarım DesenleriYazılım Müh.
  6. Singleton deseni nedir? Neden bazen anti-pattern olarak görülür?ZorOOP & Tasarım DesenleriYazılım Müh.

Bu konuda başka bir soru biliyor musun?

Mülakatta karşılaştığın soruları ekle, onaylandıktan sonra yayına alınsın.

Soru ekle