Anemic Domain Model: Detaylı Bir İnceleme

[en] Read in English

2023-06-15

Anemic Domain Model, domain logic’inin çoğunlukla servislerde ve veri transfer nesnelerinde bulunduğu, genellikle işlevselliği ve davranışı belirsizleştiren ve genellikle sadece veri aktarımı için kullanılan bir yazılım tasarım desenidir. Bu terim, ilk olarak Martin Fowler tarafından tasarım deseninin olumsuz bir örneği olarak tanımlanmıştır.

Tipik bir örneği, nesnelerin verileri saklama yeteneklerine sahip olmasına ancak iş mantığının, servislerde ve diğer dış kaynaklarda olmasına dayanır. Bu nedenle, bu model genellikle veri erişim katmanının işlevselliği ile ilgilenir ve genellikle iş mantığından yoksundur.

Yapısal İnceleme

Genellikle şu bileşenlerden oluşur:

  1. Entity/Model: Veriyi saklayan nesneler. Bu nesneler genellikle sadece basit get ve set metodlarına sahip olur ve kendi iş mantığına sahip değildirler.

  2. Service: İş mantığı burada bulunur. Servisler, iş kurallarını uygulamak ve farklı modeller arasında ilişkiler kurmak için kullanılır.

  3. DTO (Data Transfer Object): Katmanlar veya servisler arasında veri taşınması için kullanılır.

Avantajları ve Dezavantajları

Bazı avantajları vardır:

  1. Kodun Anlaşılabilirliği: Domain modeli çok basit olduğu için, başlangıçta kodun anlaşılması daha kolay olabilir.

  2. Geliştirme Hızı: İş mantığının dışında, model sadece veri saklama ve aktarma işlemlerini ele aldığı için hızlı geliştirme sağlanabilir.

  3. Teknoloji Bağımlılığı Azdır: Veri erişim katmanı ve iş katmanı arasında net bir ayrım olduğu için, teknoloji değişiklikleri daha az karmaşık hale gelebilir.

Ancak, bu modelin de bazı önemli dezavantajları vardır:

  1. İş Mantığına Yabancılaşma: İş mantığı modelden ayrıldığı için, modelin neyi temsil ettiğini anlamak zor olabilir.

  2. Düşük Esneklik: Model üzerinde yapılan değişiklikler genellikle çok sayıda servisi etkiler. Bu, değişikliklerin daha karmaşık hale gelmesine ve yeni özelliklerin eklenmesinin daha zor olmasına neden olur.

  3. Kodun Karmaşıklığı: İş mantığı birden fazla servise dağıtıldığında, kod daha karmaşık ve zor yönetilebilir hale gelebilir.

Anemic Domain Model, yazılım geliştirmede çeşitli faktörler nedeniyle oluşabilir. Aşağıda en yaygın nedenlerden bazılarına değinilmiştir:

  1. Basitlik: Anemic Domain Model, başlangıçta çoğu zaman daha basit ve anlaşılır olabilir. Yeni başlayan bir geliştirici için, bu modelin basitliği ve anlaşılırlığı, geliştirme sürecine hızla katılımı kolaylaştırabilir.

  2. Hızlı Prototipleme: Bir ürünü veya uygulamayı hızla geliştirmek ve piyasaya sürmek isteyen ekipler için Anemic Domain Model çekici olabilir. Bu model, iş mantığını ve veri erişimini ayırarak hızlı bir şekilde özellikler eklemeye ve uygulamanın prototipini oluşturmaya yardımcı olabilir.

  3. Teknolojik Sınırlamalar: Bazı teknolojiler veya çerçeveler, daha karmaşık domain modellerini uygulamayı zorlaştırabilir. Bu durumda, Anemic Domain Model daha uygulanabilir olabilir.

  4. Eğitim ve Bilgi Eksikliği: Yazılım mühendisliği konusunda derinlemesine bilgiye sahip olmayan ekipler, genellikle anemic domain modellerini kullanma eğilimindedir. Bu durum, daha karmaşık domain modellerinin karmaşıklığını ve iş mantığını tam olarak anlamamaktan kaynaklanabilir.

Bu nedenlere rağmen, Anemic Domain Model’in, genellikle uygulamanın genişletilmesini ve bakımını zorlaştıran bazı önemli dezavantajları olduğunu unutmamak önemlidir. Bu model, bir projenin erken aşamalarında hızlı gelişim sağlayabilir, ancak projenin ömrü boyunca sürdürülebilirliğini azaltabilir. Özellikle büyük, karmaşık projelerde veya sürekli evrim geçiren projelerde, daha sağlam bir domain modeli gerekebilir.

Anemic Domain Model’i bir anti-pattern olarak kabul etmek her zaman evrensel bir görüş olmamıştır. Anemic Domain Model’in bazı durumlarda geçerli ve kullanışlı olabileceğini savunan birçok eleştiri ve yorum bulunmaktadır.

Bu eleştirilerin bazıları şunları içerir:

  1. Görev Odaklı İş Mantığı: İş mantığı bazen bir nesne tarafından değil, bir işlem veya işlem dizisi tarafından yönetilir. Bu tür durumlardaki uygulamalar, Anemic Domain Model yaklaşımından faydalanabilir. Çünkü burada domain nesneleri veri taşımaktan çok daha fazlasını yapmak zorunda değillerdir.

  2. Yapılandırma Basitliği: Anemic Domain Model, genellikle nesne yönelimli programlama dillerinin ve çerçevelerinin gerektirdiği karmaşıklıktan kaçınır. Model, DTO’lar ve servisler arasında net bir ayrım sağlar ve bu, karmaşık iş uygulamalarında kodun daha anlaşılır olmasına yardımcı olabilir.

  3. Ölçeklenebilirlik ve Dağıtım: Büyük, dağıtılmış sistemlerde, iş mantığı genellikle birden çok servis ve mikroservis arasında dağıtılır. Bu durumda, Anemic Domain Model kullanışlı olabilir çünkü veri ve iş mantığının net bir şekilde ayrılmasını sağlar.

  4. Kapsülleme: İş mantığını bir hizmet katmanında tutmak, veri ve iş mantığını birbirinden ayırır ve kapsülleme sağlar. Bu, bir uygulamanın farklı bölümlerinin birbirinden bağımsız olarak değiştirilmesine ve güncellenmesine olanak sağlar.

Anemic Domain Model’in bir anti-pattern olduğunu kabul etmek tamamen duruma bağlıdır. Genel kabul görmüş en iyi uygulamaların dışında kalırken, belirli durumlar ve koşullar altında yararlı ve etkili olabilir. Kullanımının, projenin gereksinimlerine ve ekibin yeteneklerine dayanması gerektiğini unutmamak önemlidir.

Anemic Domain Model, birçok yazılım mühendisi ve tasarımcısı tarafından bir anti-pattern olarak görülür çünkü bazı önemli yazılım tasarım ilkeleri ve pratikleriyle çelişir. İşte Anemic Domain Model’in bir anti-pattern olarak kabul edilmesinin başlıca nedenleri:

  1. Nesne Yönelimli Programlama (OOP) İlkelerine Aykırıdır: OOP, verinin ve iş mantığının bir arada olduğu bir paradigmaya dayanır. Bununla birlikte, Anemic Domain Model, iş mantığını ve veriyi birbirinden ayırarak bu prensiplere aykırıdır. İş mantığı genellikle ayrı servislerde saklanırken, modeller genellikle sadece veriyi saklar. Bu, OOP’nin temel amacı olan birleşik bir model sağlama prensibini ihlal eder.

  2. Düşük Kapsülleme: Anemic Domain Model, iş mantığının ve verinin ayrılması nedeniyle genellikle düşük kapsüllemeye sahiptir. İş mantığı modelden ayrı olduğunda, iş kuralları genellikle çok sayıda servise yayılır. Bu, bir modelin veya servisin değiştirilmesi gerektiğinde kodun farklı bölümlerinde değişiklikler yapılmasını gerektirebilir, bu da koda karmaşıklık ekler.

  3. Tek Sorumluluk İlkesine Aykırıdır: Her sınıfın veya modülün tek bir sorumluluğu olması gerektiğini öneren Tek Sorumluluk İlkesi (SRP) ile de çelişir. Anemic Domain Model’de, iş mantığı ve veri saklama genellikle ayrı ayrı sınıflar veya modüller tarafından yönetilir, bu da her birinin birden çok sorumluluğu olabilir.

  4. Kodun Bakımı ve Genişletilmesi Zorlaşır: Anemic Domain Model, kodun genişletilmesini ve bakımını zorlaştırabilir. Bir modelin değiştirilmesi genellikle ona bağlı olan servislerin de değiştirilmesini gerektirir. Bu, zamanla büyük miktarda teknik borç biriktirebilir.

Bu nedenlerle, Anemic Domain Model genellikle bir anti-pattern olarak kabul edilir. Ancak, belirli durumlarda ve özellikle belirli teknolojik sınırlamalar altında yine de kullanışlı olabilir. Her zaman olduğu gibi, en iyi uygulama modelinin seçimi, projenin gereksinimlerine ve bağlamına dayanmalıdır.

Evet tabii ki. Anemic ve rich (anemic olmayan) Domain Model’lerin daha açıklayıcı bir örneğini vereceğim. Bu örnekte Product adında bir nesnemiz olsun ve bu nesne üzerinde Discount adında bir işlem yapacağız.

C# dilinde Anemic ve rich Domain Model örneği:

Anemic Model (C#)

public class Product // Anemic model
{
    public string Name { get; set; }
    public decimal Price { get; set; }
    public decimal Discount { get; set; }
}

public class ProductService // Service
{
    public void ApplyDiscount(Product product, decimal discountPercentage)
    {
        product.Discount = product.Price * discountPercentage / 100;
    }
}

Bu örnekte Product nesnesi hiçbir iş mantığı içermemekte ve ApplyDiscount işlemi ProductService adlı bir hizmet sınıfı içinde bulunmaktadır.

Rich Model (C#)

public class Product // Rich model
{
    public string Name { get; set; }
    public decimal Price { get; set; }
    public decimal Discount { get; set; }

    public void ApplyDiscount(decimal discountPercentage)
    {
        this.Discount = this.Price * discountPercentage / 100;
    }
}

Bu örnekte, ApplyDiscount işlemi Product sınıfı içerisine eklenmiştir ve bu sayede iş mantığı ve veri bir arada tutulmuştur.

Aynı örneği Java ile de gösterebiliriz.

Anemic Model (Java)

public class Product { // Anemic model
    private String name;
    private BigDecimal price;
    private BigDecimal discount;

    // Getters and setters...
}

public class ProductService { // Service
    public void applyDiscount(Product product, BigDecimal discountPercentage) {
        product.setDiscount(product.getPrice().multiply(discountPercentage).divide(BigDecimal.valueOf(100)));
    }
}

Rich Model (Java)

public class Product { // Rich model
    private String name;
    private BigDecimal price;
    private BigDecimal discount;

    // Getters and setters...
    
    public void applyDiscount(BigDecimal discountPercentage) {
        this.setDiscount(this.getPrice().multiply(discountPercentage).divide(BigDecimal.valueOf(100)));
    }
}

Bu örnekte, Java kullanılarak benzer şekilde Anemic ve rich domain modelleri gösterilmiştir. rich modelde applyDiscount işlemi Product sınıfı içerisine eklenmiştir, böylece iş mantığı ve veri bir arada tutulmuştur.

Sonuç

Anemic ve rich Domain Model’ler, yazılım mühendisliği uygulamalarında verinin ve iş mantığının yönetimi konusunda farklı yaklaşımlar sunarlar.

Anemic Domain Model, iş mantığını ve veriyi birbirinden ayırarak işlevselliği servis katmanlarına yayar. Bu, başlangıçta basit ve anlaşılır olabilir ve hızlı prototipleme veya teknolojik sınırlamalar gibi durumlardan dolayı çekici olabilir. Ancak bu modelin ana dezavantajlarından biri, Nesne Yönelimli Programlama’nın (OOP) temel ilkelerine aykırı olmasıdır. Bu, özellikle daha karmaşık veya sürekli gelişen projelerde kodun bakımını ve genişletilmesini zorlaştırabilir.

Öte yandan, rich Domain Model, iş mantığını ve veriyi bir arada tutarak birleşik bir model sunar. Bu, OOP ilkelerine daha uyumludur ve kodun bakımını ve genişletilmesini kolaylaştırabilir. Ancak bu yaklaşım da kendi karmaşıklıklarını ve zorluklarını getirebilir, özellikle de büyük, dağıtılmış sistemlerde iş mantığının yönetilmesi gerektiğinde.

Her iki modelin de kullanılabilirliği ve etkinliği, projenin gereksinimlerine, ekibin yeteneklerine ve kullanılan teknolojiye bağlıdır. Önemli olan, seçilen modelin projenin uzun vadeli başarısı için en uygun olanı olmasıdır. Hangi modelin seçileceği, ekip tarafından belirli bir proje bağlamında belirlenmelidir. Her durumda, iş mantığının yönetilmesi ve bakımının nasıl en etkin şekilde gerçekleştirileceği dikkatlice düşünülmelidir.