Software Architecture

Alan Odaklı Tasarımı Ustalaşmak: Karmaşık İş Mantığını Modelleme İçin Pratik Bir Rehber

Yazılım sistemleri büyür. Genişledikçe, desteklemeleri gereken iş mantığının karmaşıklığı da artar. İş kuralları teknik uygulama detaylarıyla iç içe geçtiğinde, kod tabanları kırılgan ve bakımı imkansız hale gelir. İşte burada Alan Odaklı Tasarım (DDD) devreye girer. DDD sadece bir kalıplar kümesi değil; bu, çekirdek alana ve alan mantığına öncelik veren, işin derin bir anlayışına dayalı karmaşık yapılar kuran bir zihniyettir.

Evrensel Dil: Kopukluğu Aşmak

Teknik yapılara dalmadan önce, DDD'nin en kritik yönünü kurmamız gerekir: evrensel dili. Bu, geliştiriciler ve alan uzmanları (iş paydaşları) tarafından kullanılan paylaşılan bir dildir. "Sipariş" teriminin satış departmanı için bir şeyi, lojistik departmanı için başka bir şeyi ifade ettiği çeviri hatalarını ortadan kaldırır.

Kod isimlerinin iş terminolojisiyle eşleşmesini sağlayarak, güncel kalmasını sağlayan canlı bir dokümantasyon oluştururuz. Bir iş terimi değişirse, kod da muhtemelen onunla birlikte değişmelidir.

Sınırlı Bağlamlar: Ölçeklenebilirlikte Karmaşılığın Yönetimi

Alanlar büyüdükçe, tek bir evrensel dil genellikle yetersiz hale gelir. İşte burada Sınırlı Bağlamlar devreye girer. Bir sınırlı bağlam, belirli bir modelin geçerli olduğu ve evrensel dilin geçerli sayıldığı bir sınırlı alanı tanımlar. Aynı kavram farklı bağlamlarda farklı anlamlara gelebilir. Örneğin, bir banka bağlamındaki bir "Hesap", müşteri profilini ifade ederken, faturalama bağlamında bir finansal defter girişini ifade eder.

Bu bağlamları birbirinden ayırmak, ekiplerin bağımsız çalışmasına ve her alt alan için en uygun teknik çözümleri seçmesine olanak tanır.

Birleşimler (Aggregates): Tutarlılık Sınırları

Bir sınırlı bağlam içinde, alan modelimizi Birleşimler kullanarak düzenleriz. Bir birleşim, veri değişiklikleri için birim olarak ele aldığımız ilişkili nesnelerden oluşan bir kümedir. Bir Birleşim Kökünden ve onun iç varlıklarından oluşur.

Temel kural şudur: dış nesneler yalnızca Birleşim Köküne referans tutabilir, iç nesnelere asla referans tutamaz. Bu, işlemsel bütünlüğü ve tutarlılığı sağlar. Bir birleşimi güncellediğinizde, onu bütünüyle güncellersiniz.

Örnek: Bir Sipariş Birleşimi


public class Order {
    private List items;
    private CustomerId customerId;
    private Money totalAmount;

    public void addItem(ProductId productId, int quantity) {
        // Ürün ekleme için iş mantığı
        this.items.add(new OrderItem(productId, quantity));
        this.recalculateTotal();
    }

    public void cancel() {
        if (this.items.isEmpty()) {
            throw new IllegalStateException("Boş bir sipariş iptal edilemez");
        }
        // Alan olayını tetikle
        this.raiseEvent(new OrderCanceledEvent(this.id));
    }

    private void recalculateTotal() {
        this.totalAmount = this.items.stream()
            .map(item -> item.getPrice().multiply(item.getQuantity()))
            .reduce(Money.ZERO, Money::add);
    }
}

Bu örnekte, Order Birleşim Köküdür. OrderItem ise birleşim içindeki bir Varlıktır. cancel metodunun iş kurallarını içsel olarak nasıl uyguladığına ve birleşimin tutarlılığını nasıl koruduğuna dikkat edin.

Varlıklar vs. Değer Nesneleri

DDD'deki kritik ayrım Varlıklar ve Değer Nesneleri arasındadır:

  • Varlıklar, özellikleri değişse bile zaman içinde kalıcı olan benzersiz bir kimliğe sahiptir (örneğin, bir Sipariş ID'si).
  • Değer Nesneleri değişmezdir ve özellikleriyle tanımlanır. İki değer nesnesi, tüm özellikleri eşitse eşittir (örneğin, bir Money nesnesi veya bir EmailAddress).

Para veya adresler gibi özellikler için Değer Nesneleri kullanmak, geçersiz durumları önler ve alan modelini daha zengin ve ifade gücü yüksek hale getirir.

Alan Olayları: Yan Etkilerin Ayrıştırılması

Karmaşık alanlar, e-posta göndermek veya envanter sayısını güncellemek gibi yan etkiler gerektirebilir. Bu eylemleri doğrudan alan mantığına bağlamak yerine, Alan Olayları kullanırız. Bunlar, alanda önemli bir şey olduğuna dair bildirimlerdir.

Yukarıdaki kod örneğinde, raiseEvent(new OrderCanceledEvent(this.id)) ifadesini gördük. Bu, iptal etme eylemini bildirim sürecinden ayırır. Ayrı bir olay işleyicisi, OrderCanceled olayını dinleyebilir ve Order birleşimini karıştırmadan gerekli aşağı akış eylemlerini gerçekleştirebilir.

Sonuç

Alan Odaklı Tasarım, karmaşık yazılım sistemleri oluşturmak için güçlü bir yaklaşımdır. Sınırlı bağlamlara odaklanarak, birleşim tutarlılığını uygulayarak, varlıkları ve değer nesnelerinden yararlanarak ve alan olaylarından yararlanarak, yalnızca teknik olarak sağlam değil, aynı zamanda iş hedefleriyle de derinlemesine uyumlu sistemler oluşturabiliriz. Öğrenme eğrisi dik olsa da, sürdürülebilirlik, ölçeklenebilirlik ve teknik ile iş ekipleri arasındaki daha net iletişimdeki uzun vadeli faydalar paha biçilemezdir.

Share: