Back to Blog

Transaction Architecture

February 12, 20263 min
Backend ArchitectureLayered ArchitectureClean Code PrinciplesTransaction Management
Transaction Architecture

Layered Architecture: Query → Service → API

Bugün öğrendiğimiz kavramları (transaction, isolation, locking vb.) sistem içinde nerede ve nasıl uygulayacağımızı inceleyeceğiz.

Bu noktada devreye Layered Architecture girer.

Modern yazılım mimarisinde:

Query → Service → API hattı, Separation of Concerns (Sorumlulukların Ayrılması) prensibine dayanır.

Amaç şudur:

  • Veritabanı işlemlerini
  • Business logic’i
  • HTTP katmanını

birbirinden tamamen izole etmek.


1. API Katmanı (Controller)

API katmanı sistemin dış dünyaya açılan kapısıdır. Sadece HTTP protokolü ile ilgilenir.

Görevleri:

  • Request’i karşılamak
  • Gelen veriyi doğrulamak
  • Service katmanını çağırmak
  • Response dönmek
// controllers/CartController.js
static async addToCart(req, res, next) => {
  try {
    const { productId, quantity } = req.body;
    const userId = req.user.id;

    const result = await CartService.addItem({
      userId,
      productId,
      quantity
    });

    return res.status(200).json(result);
  } catch (error) {
    next(error);
  }
};

⚠ Controller içinde:

  • SQL yazılmaz
  • Transaction başlatılmaz
  • Business kuralı yazılmaz

2. Service Katmanı (Business Logic)

Service katmanı sistemin beyin kısmıdır.

Burada:

  • İş kuralları uygulanır
  • Kontroller yapılır
  • Transaction boundary belirlenir
  • Data katmanı çağrılır
// services/CartService.js
static async addItem({ userId, productId, quantity }) {
  return await sequelize.transaction(async (t) => {

    const product = await ProductData.getById(productId, {
      transaction: t
    });

    if (product.stock < quantity) {
      throw new Error("Yetersiz stok");
    }

    await CartData.upsertItem(
      { userId, productId, quantity },
      { transaction: t }
    );

    return { message: "Ürün sepete eklendi" };
  });
}

Transaction boundary burada başlar ve burada biter.

Service katmanı:

  • Veri nasıl alınır değil,
  • İş mantığı nasıl çalışır sorusuyla ilgilenir.

3. Data Katmanı (Repository)

Repository katmanında yalnızca veri işlemleri yapılır.

  • Veriyi getir
  • Veriyi kaydet
  • Veriyi güncelle

Hepsi bu.

// data/ProductData.js
export const getById = async (id, { transaction }) => {
  return await Product.findOne({
    where: { id },
    transaction,
    lock: transaction.LOCK.UPDATE
  });
};

Burada business logic yoktur. Sadece veritabanı erişimi vardır.


Workflow (Adım Adım)

  1. Client → POST /cart/add
  2. Route → Controller’a yönlendirir
  3. Controller → Service’i çağırır
  4. Service → Transaction başlatır
  5. Data → DB’den veriyi çeker (gerekirse locking yapar)
  6. Service → Kontrolleri yapar ve kaydeder
  7. Controller → Response döner

Neden DB İşlemlerini Controller’da Yapmayız?

Eğer Controller içinde:

  • Veri doğrulama
  • Stok kontrolü
  • SQL sorgusu
  • Transaction yönetimi
  • Mail gönderme

gibi işlemleri yazarsan:

  • Dosya devasa büyür
  • Test edilemez hâle gelir
  • Hata ayıklamak zorlaşır
  • Kod tekrarları oluşur

Layered mimari sayesinde:

  • Kod daha okunabilir olur
  • Test etmek kolaylaşır
  • Business logic tekrar kullanılabilir
  • Sistem büyüdüğünde çökmek yerine ölçeklenir

Mimari Özet

Controller (HTTP)
   ↓
Service (Business Logic + Transaction)
   ↓
Repository (DB Access)

Her katman yalnızca kendi sorumluluğundan sorumludur.