Veri erişimini neden ayırmalı?
Kitaptan, Model Odaklı Tasarım bölümünün ilk iki sayfasının, etki alanı modelinin uygulanmasından teknik uygulama ayrıntılarını neden özetlemek istediğinize dair bazı gerekçeler verdiğini düşünüyorum.
- Etki alanı modeli ile kod arasında sıkı bir bağlantı tutmak istiyorsunuz
- Teknik kaygıları ayırmak, modelin uygulama için pratik olduğunu kanıtlamaya yardımcı olur
- Her yerde bulunan dilin sistemin tasarımına nüfuz etmesini istiyorsunuz
Tüm bunlar sistemin gerçek uygulamasından boşanan ayrı bir "analiz modelinden" kaçınmak amacıyla görünüyor.
Kitaptan anladığım kadarıyla, bu "analiz modelinin" yazılım uygulamasını düşünmeden tasarlanabileceğini söylüyor. Geliştiriciler iş tarafı tarafından anlaşılan modeli uygulamaya çalıştıklarında, gereklilik nedeniyle kendi soyutlamalarını oluştururlar, iletişim ve anlayışta bir duvara neden olurlar.
Diğer yönde, etki alanı modeline çok fazla teknik endişe getiren geliştiriciler de bu bölünmeye neden olabilir.
Dolayısıyla, kalıcılık gibi endişelerin ayrılmasının uygulanmasının, bu tasarıma karşı farklı bir analiz modelinin korunmasına yardımcı olabileceğini düşünebilirsiniz. Kalıcılık gibi şeyleri modele sokmak gerekliyse, o zaman kırmızı bir bayraktır. Belki de model uygulama için pratik değildir.
Alıntı yapmak:
"Tek model hata olasılığını azaltır, çünkü tasarım şimdi dikkatle düşünülmüş modelin doğrudan bir büyümesidir. Tasarım ve hatta kodun kendisi bir modelin iletişim yeteneğine sahiptir."
Bunu yorumlama şeklim, eğer veritabanı erişimi gibi şeylerle ilgilenen daha fazla kod satırı ile sonuçlanırsanız, bu iletişimi kaybedersiniz.
Bir veritabanına erişme ihtiyacı benzersizliği kontrol etmek gibi bir şeyse, şunlara bir göz atın:
Udi Dahan: DDD'yi uygularken ekiplerin yaptığı en büyük hatalar
http://gojko.net/2010/06/11/udi-dahan-the-biggest-mistakes-teams-make-when-applying-ddd/
"Tüm kurallar eşit oluşturulmaz"
ve
Etki Alanı Modeli Modelini Kullanma
http://msdn.microsoft.com/en-us/magazine/ee236415.aspx#id0400119
aynı konuya değinen "Etki Alanı Modelini Kullanmama Senaryoları" altında.
Veri erişimini ayırma
Arayüz üzerinden veri yükleme
"Veri erişim katmanı", gerekli verileri almak için aradığınız bir arabirim üzerinden soyutlanmıştır:
var orderLines = OrderRepository.GetOrderLines(orderId);
foreach (var line in orderLines)
{
total += line.Price;
}
Artıları: Arabirim "veri erişimi" tesisat kodunu ayırır ve yine de testler yazmanıza izin verir. Veri erişimi, genel bir stratejiden daha iyi performans sağlayarak duruma göre işlenebilir.
Eksileri: Arama kodu neyin yüklü ve neyin yüklü olmadığını varsaymalıdır.
Diyelim GetOrderLines performans nedenleriyle null ProductInfo özelliğine sahip OrderLine nesnelerini döndürür. Geliştiricinin arabirimin arkasındaki kod hakkında derin bilgiye sahip olması gerekir.
Bu yöntemi gerçek sistemlerde denedim. Sonuçta, performans sorunlarını düzeltmek için her zaman yüklenenlerin kapsamını değiştirirsiniz. Neyin yüklenip neyin yüklenmediğini görmek için veri erişim koduna bakmak üzere arayüzün arkasına bakıyorsunuz.
Şimdi, endişelerin ayrılması, geliştiricinin mümkün olduğunca kodun bir yönüne bir kerede odaklanmasına izin vermelidir. Arabirim tekniği, yüklenen bu veri NASIL NASIL yüklenir, NASIL yüklenir, NE ZAMAN yüklenir ve NERE yüklenir.
Sonuç: Oldukça düşük ayrılma!
Yavaş yüklenme
Veriler talep üzerine yüklenir. Veri yükleme çağrıları, bir özelliğe erişmenin sonucu döndürmeden önce bir sql sorgusunun yürütülmesine neden olabileceği nesne grafiğinin içinde gizlenir.
foreach (var line in order.OrderLines)
{
total += line.Price;
}
Artıları: Veri erişiminin 'NE ZAMAN, NEREDE ve NASIL' alanı, etki alanı mantığına odaklanan geliştiriciden gizlenir. Toplamda veri yüklemeyle ilgili hiçbir kod yoktur. Yüklenen veri miktarı kodun gerektirdiği kesin miktar olabilir.
Eksileri: Bir performans sorunu ile vurulduğunda, genel bir "herkese uygun" bir çözüm olduğunda düzeltmek zordur. Tembel yükleme genel olarak daha kötü performansa neden olabilir ve tembel yükleme uygulamak zor olabilir.
Rol Arayüzü / İstekli Getirme
Her kullanım durumu, toplu sınıf tarafından uygulanan bir Rol Arayüzü aracılığıyla açık hale getirilir ve kullanım durumu başına veri yükleme stratejilerinin ele alınmasını sağlar.
Getirme stratejisi şöyle görünebilir:
public class BillOrderFetchingStrategy : ILoadDataFor<IBillOrder, Order>
{
Order Load(string aggregateId)
{
var order = new Order();
order.Data = GetOrderLinesWithPrice(aggregateId);
return order;
}
}
Daha sonra toplamınız şöyle görünebilir:
public class Order : IBillOrder
{
void BillOrder(BillOrderCommand command)
{
foreach (var line in this.Data.OrderLines)
{
total += line.Price;
}
etc...
}
}
BillOrderFetchingStrategy, toplamayı oluşturmak için kullanılır ve daha sonra toplam işini yapar.
Artıları: Kullanım durumuna göre özel kod sağlar ve en iyi performansı sağlar. Arabirim Ayrışma İlkesi ile uyumludur . Karmaşık kod gereksinimi yoktur. Agrega ünite testleri yükleme stratejisini taklit etmek zorunda değildir. Genel yükleme stratejisi çoğu durumda kullanılabilir (örneğin "tümünü yükle" stratejisi) ve gerektiğinde özel yükleme stratejileri uygulanabilir.
Eksileri: Geliştirici hala alan kodunu değiştirdikten sonra getirme stratejisini ayarlamalı / gözden geçirmelidir.
Getirme stratejisi yaklaşımıyla, iş kurallarındaki bir değişiklik için kendinizi özel getirme kodunu değiştirirken bulabilirsiniz. Endişelerin mükemmel bir şekilde ayrılması değil, ancak daha sürdürülebilir ve ilk seçenekten daha iyidir. Getirme stratejisi, NASIL, NE ZAMAN ve NEREDE verileri yüklenir. Endişelerin daha iyi ayrılması, tek bir boyutun tüm tembel yükleme yaklaşımına uyması gibi esnekliğini kaybetmeden.