Mikro Hizmetlerde Etki Alanı Odaklı Tasarım (DDD)

Mikro Hizmetlerde Etki Alanı Odaklı Tasarım (DDD)

Kuruluşlar monolitik bir mimariden mikro hizmetlere geçiş yaptıklarında kritik ve önemli bir soruyla karşı karşıya kalırlar: Hizmetlerimizin sınırlarını nasıl çizeriz?

Teorik olarak mikro hizmetler, bağımsız olarak geliştirilebilen, dağıtılabilen ve ölçeklendirilebilen gevşek, ayrılmış birimler olmalıdır. Ancak pratikte pek çok ekip sonunda dağıtılmış bir monolit inşa ediyor; bu sistem, hizmetlerin çok sıkı bir şekilde birbirine bağlandığı, tek bir iş değişikliğinin birden fazla hizmetin aynı anda değiştirilmesini ve dağıtılmasını gerektirdiği, ağ gecikmesini ve dağıtım sorunlarını bir araya getiren bir sistem.

Bu tuzağa düşmemek için yazılım mimarları Etki Alanına Dayalı Tasarıma (DDD) yöneliyor. İlk olarak 2003 yılında Eric Evans tarafından tanıtılan DDD, kod yapılarını temsil ettikleri karmaşık iş alanlarıyla uyumlu hale getiren bir yazılım geliştirme metodolojisidir.

Bu makalede, DDD’nin temiz, ayrıştırılmış ve bakımı yüksek düzeyde mikro hizmetler tasarlamak için stratejik ve taktiksel planları nasıl sağladığını inceleyeceğiz.


1. Stratejik Plan: Hizmet Sınırlarının Çizilmesi

DDD iki ana aşamaya ayrılmıştır: Stratejik Tasarım ve Taktik Tasarım. Stratejik tasarım, iş bağlamlarının modellenmesi ve hizmet sınırlarının tanımlanmasıyla ilgilidir. Mimarinin “makro” görünümünü sağlar.

Mikro Hizmetler Mimari Diyagramına DDD Sınırlı Bağlam eşlemesi

A. Her Yerde Bulunan Dil

Bir işletmede farklı departmanlar aynı kelimeleri tamamen farklı şeyleri ifade etmek için kullanır. Örneğin:

  • Satış ekibi için “Kullanıcı” potansiyel müşteri veya potansiyel müşteridir.
  • Güvenlik ekibi için “Kullanıcı”, bir dizi oturum açma kimlik bilgisidir.
  • Gönderim ekibi için “Kullanıcı” fiziksel alıcı adresidir.

Herkesi memnun eden bir “Kullanıcı” için tek, birleşik bir veritabanı modeli oluşturmaya çalışmak, devasa, karmaşık bir kod tabanıyla sonuçlanır. DDD bu sorunu, belirli bir sınır dahilinde hem iş alanı uzmanları hem de geliştiriciler tarafından tanımlanan ve kullanılan ortak bir kelime dağarcığı olan Her Yerde Bulunan Dil oluşturarak çözer.

B. Sınırlı Bağlamlar

Sınırlı Bağlam, bir etki alanı modelinin uygulandığı açık sınırdır. Sınırın içinde, Her Yerde Bulunan Dildeki tüm terimlerin tek ve açık bir anlamı vardır.

Tek bir “Kullanıcı” modeli yerine, ilgili Sınırlı Bağlamları dahilinde ayrı modeller tanımlarız:

  • Sipariş İçeriği’nde müşteri iletişim bilgilerini içeren bir Order modelimiz vardır.
  • Kimlik Bağlamında bir Credentials modelimiz var.
  • Gönderim İçeriğinde bir DeliveryAddress modelimiz var.

Mikro Hizmetlerin Altın Kuralı: Tek Sınırlı Bağlam doğrudan tek bir Mikro Hizmetle eşleşir.

Sistemi Sınırlı Bağlamlara bölerek mikro hizmetlerin gevşek bir şekilde bağlanmasını ve farklı iş yeteneklerini temsil etmesini sağlıyoruz.

C. Bağlam Eşleme: Hizmetler Nasıl İletişim Kurar?

Sınırlı Bağlamlar tek başına mevcut değildir; etkileşime girmeleri gerekir. Bağlam Haritası bağlamlar arasındaki ilişkileri ve çeviri mekanizmalarını tanımlar. Anahtar kalıplar şunları içerir:

  • Paylaşılan Çekirdek: İki bağlam, etki alanı modelinin ve veritabanının küçük bir alt kümesini paylaşır (genellikle mikro hizmetlerde birleştirme nedeniyle önerilmez).
  • Müşteri-Tedarikçi: Bir bağlam (tedarikçi) diğerine (müşteri) veri sağlamalıdır. Tedarikçi, sürüm programlarını müşteriyle koordine etmelidir.
  • Yolsuzlukla Mücadele Katmanı (ACL): Harici bir sistemden gelen verileri müşterinin dahili etki alanı modeline çeviren ve harici modellerin dahili mimariyi kirletmesini önleyen bir çeviri katmanı.

2. Taktik Taslak: Mikro Hizmet Kod Tabanını Yapılandırmak

Hizmet sınırları stratejik tasarım kullanılarak çizildikten sonra Taktik Tasarım, kodu tek bir mikro hizmet içinde yapılandırmak için bir dizi tasarım modeli sağlar.

A. Varlıklar ve Değer Nesneleri

Bir mikro hizmetin içinde modeller iki kategoriye ayrılır:

  1. Varlıklar: Nitelikleri değişse bile zaman içinde varlığını sürdüren benzersiz bir kimliğe sahip nesneler. Örnekler arasında Order veya Product yer alır.
  2. Değer Nesneleri: Benzersiz bir kimliğe sahip olmayan ve tamamen nitelikleriyle tanımlanan nesneler. Onlar değişmezdir. Örnekler arasında ShippingAddress veya ProductDimensions yer alır. İki değer nesnesi aynı niteliklere sahipse eşit kabul edilir.

B. Toplamalar ve Toplama Kökleri

Toplama, veri değişiklikleri için tek bir birim olarak ele alınan ilişkili Varlıklar ve Değer Nesneleri kümesidir. Her toplamanın, harici nesnelerin toplamayla etkileşime girebileceği tek giriş noktası olan bir Toplama Kökü vardır. Kök, tüm iş değişmezlerinin (kuralların) uygulanmasını sağlar.

Örneğin yukarıdaki şemada:

  • Sipariş Hizmetinde, Order Toplu Kök’tür. OrderItem (Varlık) ve ShippingAddress (Değer Nesnesi) içerir. Harici hizmetler OrderItem öğesini doğrudan değiştiremez; Order kökünde, siparişin henüz gönderilmediğini doğrulayan bir yöntemi (ör. order.AddItem()) çağırmaları gerekir.

C. Etki Alanı Olayları

Alan Etkinliği, iş uzmanlarının önemsediği alanda gerçekleşen bir şeydir. Sınırlı Bağlamlardaki değişiklikleri eşzamansız olarak iletmek için kullanılır. Bir Toplama bir komutu yürüttüğünde, bir Etki Alanı Olayı yayınlar (örneğin, OrderCreated). Diğer hizmetler bu olayı dinler ve durumlarını buna göre güncelleyerek eşzamanlı API bağımlılıkları olmadan nihai tutarlılığı sağlar.


3. Somut Bir Örnek: Sipariş Hizmeti ve Envanter Hizmeti Karşılaştırması

Toplu Kök’ün iş kurallarını nasıl koordine ettiğini gösteren Sipariş Hizmeti için Go’da taktiksel DDD’nin basitleştirilmiş bir uygulamasına bakalım.

package domain

import (
	"errors"
	"time"
)

// Value Object (Immutable, identity-less)
type ShippingAddress struct {
	Street  string
	City    string
	ZipCode string
}

// Entity (Has identity, mutable)
type OrderItem struct {
	ProductID string
	Quantity  int
	Price     float64
}

// Aggregate Root (Enforces transactional boundaries)
type Order struct {
	ID        string
	Items     []OrderItem
	Address   ShippingAddress
	Status    string
	CreatedAt time.Time
}

// NewOrder creates a new Order Aggregate Root
func NewOrder(id string, address ShippingAddress) *Order {
	return &Order{
		ID:        id,
		Items:     []OrderItem{},
		Address:   address,
		Status:    "PENDING",
		CreatedAt: time.Now(),
	}
}

// AddItem enforces business rules before mutating state
func (o *Order) AddItem(productID string, qty int, price float64) error {
	if o.Status != "PENDING" {
		return errors.New("cannot add items to a finalized or cancelled order")
	}
	if qty <= 0 {
		return errors.New("quantity must be greater than zero")
	}
	
	o.Items = append(o.Items, OrderItem{
		ProductID: productID,
		Quantity:  qty,
		Price:     price,
	})
	return nil
}

Sipariş başarıyla kaydedildiğinde hizmet, bir mesaj komisyoncusuna bir etkinlik yayınlar:

{
  "event_id": "evt_98231",
  "event_type": "OrderCreated",
  "timestamp": "2026-06-26T00:15:00Z",
  "payload": {
    "order_id": "ord_5521",
    "items": [
      { "product_id": "prod_88", "quantity": 2 }
    ]
  }
}

Envanter Hizmeti bu olayı dinler, yerel StockLevel varlığını günceller ve akışı eşzamansız olarak tamamlar.


4. Mikro Hizmetlerde Stratejik ve Taktiksel DDD

Aşama / Unsur Stratejik DDD Taktik DDD
Kapsam Küresel sistem mimarisi (makro) Tek bir hizmet kod tabanının içinde (mikro)
Birincil Hedef Temiz, ayrılmış hizmet sınırlarını çizin Zengin iş mantığını modelleyin ve değişmezleri uygulayın
Temel Kavramlar Sınırlı Bağlamlar, Her Yerde Bulunan Dil, Bağlam Haritası Varlıklar, Değer Nesneleri, Toplamalar, Etki Alanı Olayları
İzleyici Mimarlar, Ürün Yöneticileri, Geliştiriciler Yazılım Geliştiricileri, Kod İnceleyenler
Mikro Hizmetler Üzerindeki Etkisi Hizmetlerin sayısını ve kapsamını belirler Veritabanı işlemlerini ve dizin yapısını belirler

Sonuç: Önce Stratejik DDD ile Başlayın

Etki Alanı Odaklı Tasarımı mikro hizmetlere uygulamak, mimarinizin iş yapınıza uygun olmasını sağlamanın güçlü bir yoludur. Ancak ekipler sıklıkla stratejik tasarımı göz ardı ederken taktik modellere (depo arayüzleri ve değer nesneleri yazmak gibi) çok fazla odaklanma hatasına düşer.

Sınırları doğru şekilde belirlemezseniz, hiçbir temiz taktik kod sisteminizi dağıtılmış bir monolite dönüşmekten kurtaramaz. Her zaman stratejik haritalamayla başlayın; Her Yerde Bulunan Dilinizi tanımlayın, mantığı Sınırlı Bağlamlar halinde gruplayın, iletişim akışlarının haritasını çıkarın ve mikro hizmet sınırlarınızın bu tanımlardan doğal olarak ortaya çıkmasına izin verin.


Ghaznix Blogunda daha fazla yazılım mimarisi, tasarım modeli ve mühendislik bilgisini keşfedin →