Yaklaşık 8 yıldır alan güdümlü tasarımı uyarlıyorum ve bunca yıldan sonra bile, beni rahatsız eden bir şey var. Bu, bir etki alanı nesnesine karşı veri depolamada benzersiz bir kayıt olup olmadığını kontrol etmektir.
Eylül 2013'te Martin Fowler , mümkünse, tüm alan nesnelerine uygulanması gereken TellDon'tAsk prensibinden bahsetti , bu da bir mesaj döndürmeli, işlemin nasıl gittiğini (nesne yönelimli tasarımda, bu genellikle istisnalar yoluyla yapılır, işlem başarısız oldu).
Projelerim genellikle iki bölüme ayrılır; bunlardan ikisi Alan adıdır (iş kuralları içerir ve hiçbir şey içermez, alan adı tamamen kalıcılık-cahildir) ve Hizmetler'dir. CRUD verilerine kullanılan havuz katmanını bilen hizmetler.
Bir nesneye ait bir özniteliğin benzersizliği bir etki alanı / iş kuralı olduğundan, etki alanı modülüne uzun olmalıdır, bu nedenle kural tam olarak olması gerektiği yerdir.
Bir kaydın benzersizliğini kontrol edebilmek için, diyelim ki başka bir kaydın Name
zaten mevcut olup olmadığını öğrenmek için geçerli veri kümesini, genellikle bir veritabanını sorgulamanız gerekir .
Etki alanı katmanı kalıcılık bilgisizdir ve verilerin nasıl alınacağına dair bir fikri yoktur, ancak yalnızca üzerlerinde işlemlerin nasıl yapılacağını, havuzların kendisine gerçekten dokunamaz.
Daha sonra uyarladığım tasarım şöyle:
class ProductRepository
{
// throws Repository.RecordNotFoundException
public Product GetBySKU(string sku);
}
class ProductCrudService
{
private ProductRepository pr;
public ProductCrudService(ProductRepository repository)
{
pr = repository;
}
public void SaveProduct(Domain.Product product)
{
try {
pr.GetBySKU(product.SKU);
throw Service.ProductWithSKUAlreadyExistsException("msg");
} catch (Repository.RecordNotFoundException e) {
// suppress/log exception
}
pr.MarkFresh(product);
pr.ProcessChanges();
}
}
Bu, etki alanı katmanının kendisi yerine etki alanı kurallarını tanımlayan hizmetlere sahip olmanıza ve kuralların kodunuzun birden çok bölümüne dağılmasına neden olur.
TellDon'tAsk ilkesinden bahsettim, çünkü açıkça görebileceğiniz gibi, hizmet bir eylem sunuyor (ya Product
bir istisna kaydediyor ya da bir istisna atıyor), ancak yöntemin içinde, prosedürel yaklaşımı kullanarak nesneler üzerinde işlem yapıyorsunuz.
Açık çözüm, fırlatma yöntemine Domain.ProductCollection
sahip bir sınıf oluşturmaktır , ancak performansta çok eksiktir, çünkü bir Ürünün zaten aynı SKU'ya sahip olup olmadığını kodda bulmak için tüm Ürünleri veri deposundan almanız gerekir. eklemeye çalıştığınız Ürün olarak.Add(Domain.Product)
ProductWithSKUAlreadyExistsException
Bu sorunu nasıl çözüyorsunuz? Bu gerçekten kendi başına bir sorun değil, hizmet katmanı yıllardır belirli etki alanı kurallarını temsil ettim. Hizmet katmanı genellikle daha karmaşık alan adı işlemlerine de hizmet eder, sadece kariyeriniz sırasında daha iyi, daha merkezi bir çözümle karşılaşıp karşılaşmadığınızı merak ediyorum.