Etki alanı / kalıcılık modeli yalıtımı genellikle bu kadar garip midir?


13

Etki Alanlarına Dayalı Tasarım (DDD) kavramlarına daldım ve özellikle etki alanı ve kalıcılık modelinin izolasyonu ile ilgili bazı ilkeleri garip buldum. İşte temel anlayışım:

  1. Uygulama katmanındaki bir hizmet (özellik kümesi sağlar), etki alanı nesnelerini işlevini yerine getirmesi gereken bir havuzdan ister.
  2. Bu deponun somut uygulaması, uygulandığı depolama alanından veri getirir
  3. Hizmet, iş mantığını kapsülleyen etki alanı nesnesine durumunu değiştiren belirli görevleri gerçekleştirmesini bildirir.
  4. Hizmet, depoya değiştirilen etki alanı nesnesini sürdürmesini bildirir.
  5. Havuzun, etki alanı nesnesini depolamadaki karşılık gelen gösterime eşlemesi gerekir.

Akış illüstrasyon

Şimdi, yukarıdaki varsayımlar göz önüne alındığında, aşağıdakiler garip görünüyor:

İlan 2 .:

Etki alanı modeli, istenen işlev için gerekli olmasalar bile tüm etki alanı nesnesini (tüm alanlar ve başvurular dahil) yüklüyor gibi görünüyor. Bu etki alanı nesnelerini ve başvurdukları tüm nesneleri sırayla yüklemediğiniz sürece, diğer etki alanı nesnelerine başvuruda bulunulursa, yükleme işlemi tamamen mümkün olmayabilir. Tembel yükleme akla geliyor, ancak öncelikle deponun sorumluluğu olması gereken etki alanı nesnelerinizi sorgulamaya başladığınız anlamına gelir.

Bu sorun göz önüne alındığında, etki alanı nesnelerini yüklemenin "doğru" yolu, her kullanım durumu için özel bir yükleme işlevine sahip gibi görünmektedir. Bu özel işlevler daha sonra yalnızca tasarlandıkları kullanım durumunun gerektirdiği verileri yükler. Garipliğin devreye girdiği yer şudur: Birincisi, deponun her uygulaması için hatırı sayılır miktarda yükleme işlevi sürdürmek zorunda kalacaktım ve etki alanı nesneleri null, alanlarını taşıyan eksik devletlerle sonuçlanacaktı . İkincisi teknik olarak bir sorun olmamalıdır, çünkü bir değer yüklenmemişse, onu yine de talep eden işlevsellik gerektirmez. Hala garip ve potansiyel bir tehlike.

İlan 3 .:

Bir etki alanı nesnesi, depo hakkında herhangi bir fikri yoksa, yapı üzerindeki benzersizlik kısıtlamalarını nasıl doğrular? Örneğin, Userbenzersiz bir sosyal güvenlik numarasıyla (verilen) yeni bir tane oluşturmak istersem , en erken çakışma depodan yalnızca veritabanında tanımlanan bir benzersizlik kısıtlaması varsa nesneyi kaydetmesini istemekle ortaya çıkar. Aksi takdirde, Useryeni bir güvenlik oluşturmadan önce verilen sosyal güvenlikle ilgili bir şey arayabilir ve bir hata rapor edebilirim. Ancak daha sonra kısıtlama denetimleri ait oldukları etki alanı nesnesinde değil, hizmette yaşayacaktır. Ben sadece etki alanı nesneleri doğrulama için (enjekte) depoları kullanmak için çok iyi izin olduğunu fark ettim.

İlan 5 .:

Etki alanı nesnelerinin bir depolama arka ucuna eşlenmesini, etki alanı nesnelerinin altta yatan verileri doğrudan değiştirmesine kıyasla, yoğun çalışma gerektiren bir işlem olarak algılarım. Elbette, beton depolama uygulamasını etki alanı kodundan ayırmak için temel bir ön koşuldur. Ancak, bu kadar yüksek bir maliyetle mi geliyor?

Görünüşe göre sizin için eşleme yapmak için ORM araçlarını kullanma seçeneğiniz var. Bunlar genellikle etki alanı modelini ORM'nin kısıtlamalarına göre tasarlamanızı veya hatta etki alanından altyapı katmanına (örneğin etki alanı nesnelerinde ORM ek açıklamalarını kullanarak) bir bağımlılık getirmenizi gerektirir. Ayrıca ORM'lerin hatırı sayılır bir hesaplama yükü sunduğunu okudum.

ORS benzeri kavramların neredeyse hiç bulunmadığı NoSQL veritabanlarında, etki alanı modellerinde hangi özelliklerin değiştiğini nasıl takip edersiniz save()?

Düzenleme : Ayrıca, bir havuzun etki alanı nesnesinin durumuna (yani her alanın değeri) erişmesi için, etki alanı nesnesinin kapsüllemeyi kesen iç durumunu göstermesi gerekir.

Genel olarak:

  • İşlemsel mantık nereye gider? Bu kesinlikle kalıcılığa özgüdür. Bazı depolama altyapısı işlemleri (hatta bellek içi sahte depolar gibi) desteklemeyebilir.
  • Birden çok nesneyi değiştiren toplu işlemler için, nesnenin kapsüllenmiş doğrulama mantığından geçmek için her nesneyi tek tek yüklemem, değiştirmem ve depolamam gerekir mi? Bu, doğrudan veritabanına tek bir sorgu yürütmeye karşıdır.

Bu konuyla ilgili bazı açıklamaları takdir ediyorum. Varsayımlarım doğru mu? Değilse, bu sorunlarla başa çıkmanın doğru yolu nedir?


1
İyi noktalar ve sorular, bunlarla da ilgileniyorum. Bir yan not - toplamı düzgün bir şekilde modelliyorsanız, bu, herhangi bir varoluş anında, toplu örneğin geçerli durumda olması gerektiği anlamına gelir - bu, toplamın ana noktasıdır (ve bir toplama kabı olarak kompozisyon kullanmaz). Bu aynı zamanda, DB verilerini toplam formdan geri yüklemek için, deponun kendisinin genellikle belirli yapıcı ve mutasyon işlemleri setini kullanması gerektiği anlamına gelir ve herhangi bir ORM'nin bu işlemleri nasıl otomatik olarak sihirli bir şekilde bildiğini göremiyorum .
Dusan

2
Daha da hayal kırıklığı yaratan şey, sizin gibi bu soruların oldukça sık sorulmasıdır, ancak bildiklerime göre, kitapta bulunan toplamaların ve depoların uygulanmasına ilişkin SIFIR örnekleri var
Dusan

Yanıtlar:


5

Temel anlayışınız doğrudur ve çizdiğiniz mimari iyidir ve iyi çalışır.

Satırlar arasında okumak, daha veritabanı merkezli bir aktif kayıt stilinden geliyormuş gibi görünüyor mu? Çalışan bir uygulamaya geçmek için şunu söylemeliyim ki

1: Etki alanı nesnelerinin tüm nesne grafiğini içermesi gerekmez. Örneğin:

public class Customer
{
    public string AddressId {get;set;}
    public string Name {get;set;}
}

public class Address
{
    public string Id {get;set;}
    public string HouseNumber {get;set;
}

Adres ve Müşterinin yalnızca "müşteri adı yalnızca ev adı ile aynı harfle başlayabilir" gibi bir mantığınız varsa aynı toplamın parçası olması gerekir. Nesnelerin tembel olarak yüklenmesini ve 'Lite' sürümlerini kullanmaktan kaçınabilirsiniz.

2: Teklik kısıtlamaları genellikle alan nesnesinin değil, havuzun amacıdır. Etki Alanı Nesneleri'ne depo enjekte etmeyin, bu etkin kayda geri dönüş, sadece hizmet kaydetmeye çalıştığında hata.

İş kuralı "Aynı SocialSecurityNumber değerine sahip iki Kullanıcının hiçbir zaman aynı anda var olamaz" değildir.

Aynı depoda var olamazlar.

3: Bireysel özellik güncelleme yöntemleri yerine depo yazmak zor değildir. Aslında, her iki şekilde de hemen hemen aynı koda sahip olduğunuzu göreceksiniz. Sadece hangi sınıfa koyduğunuz.

Bu günlerde ORM'ler kolaydır ve kodunuz üzerinde fazladan bir kısıtlama yoktur. Bunu söyledikten sonra, kişisel olarak sadece SQL'i krankla kullanmayı tercih ederim. Bu o kadar zor değil, ORM özellikleriyle hiçbir zaman karşılaşmazsınız ve gerektiğinde optimize edebilirsiniz.

Kaydettiğinizde hangi özelliklerin değiştiğini gerçekten takip etmeye gerek yoktur. Etki Alanı Nesnelerinizi küçük tutun ve eski sürümün üzerine yazın.

Genel Sorular

  1. İşlem mantığı depoya gider. Ama bunlardan herhangi birine sahip olmamalısınız. Tabii ki, topluluğun alt nesnelerini koyduğunuz alt tablolarınız varsa, ancak bunlar tamamen SaveMyObject depo yöntemi içinde kapsüllenecekse bazılarına ihtiyacınız vardır.

  2. Toplu güncellemeler. Evet, her nesneyi ayrı ayrı değiştirmeniz ve ardından toplu güncellemeyi yapmak için deponuza bir SaveMyObjects (List nesneleri) yöntemi eklemeniz gerekir.

    Etki Alanı Nesnesi veya Etki Alanı Hizmeti'nin mantığı içermesini istiyorsunuz. Veritabanı değil . Bunun anlamı, "müşteri set name = x nerede y'yi güncelle" yapamayacağınızdır, çünkü Müşteri nesnesini bildiğiniz her şey için veya CustomerUpdateService, adı değiştirdiğinizde 20 tuhaf başka şey yapar.


Mükemmel cevap. Kesinlikle haklısın, aktif bir kodlama kayıt stiline alışkınım, bu yüzden depo deseni ilk bakışta garip görünüyor. Ancak, "yalın" alan nesneleri (do AddressIdyerine Address) çelişmektedir OO ilkelerini?
Çift M

hayır, hala bir Adres nesneniz var, bu sadece bir Müşterinin çocuğu değil
Ewan

Değişiklik izleme olmadan reklam nesne haritalama softwareengineering.stackexchange.com/questions/380274/...
Çift M

2

Kısa cevap: Anlayışınız doğrudur ve sahip olduğunuz sorular, çözümlerin doğrudan ileri veya evrensel olarak kabul edilmediği geçerli sorunlara işaret etmektedir.

Nokta 2 .: (tam nesne grafiklerinin yüklenmesi)

ORM'lerin her zaman iyi bir çözüm olmadığını belirten ilk kişi ben değilim. Ana sorun ORM'lerin gerçek kullanım durumu hakkında hiçbir şey bilmemeleri, bu yüzden ne yükleyecekleri veya nasıl optimize edecekleri konusunda hiçbir fikirleri yok. Bu bir problem.

Söylediğiniz gibi, bariz çözüm her kullanım durumu için kalıcılık yöntemlerine sahip olmaktır. Ancak bunun için hala bir ORM kullanıyorsanız, ORM sizi her şeyi veri nesnelerine paketlemeye zorlar. Gerçekten nesne yönelimli olmamak dışında, yine bazı kullanım durumları için en iyi tasarım değildir.

Bazı kayıtları toplu olarak güncellemek istersem ne olur? Neden tüm kayıtlar için bir nesne sunumuna ihtiyacım var? Vb.

Bu nedenle çözüm, iyi bir kullanım olmayan kullanım durumları için bir ORM kullanmak değildir. Bazen verilerin kendisinin (veri nesneleri) ek bir "soyutlaması" ne de "tablolar" (depolar) üzerinde bir soyutlama gerektirmeyen bir kullanım durumu "doğal olarak" olduğu gibi uygulayın.

Yarı dolu veri nesnelerine sahip olmak veya nesne referanslarını "ids" ile değiştirmek, işaret ettiğiniz gibi iyi tasarımlar değil, en iyi çözümlerdir.

Nokta 3 .: (kontrol kısıtlamaları)

Kalıcılık soyutlanmazsa, her kullanım durumu istediği kısıtlamayı kolayca kontrol edebilir. Nesnelerin "havuzu" bilmemesi gerekliliği tamamen yapaydır ve teknolojinin bir sorunu değildir.

Nokta 5 .: (ORM'ler)

Elbette, beton depolama uygulamasını etki alanı kodundan ayırmak için temel bir ön koşuldur. Ancak, bu kadar yüksek bir maliyetle mi geliyor?

Hayır. Kalıcı olmanın başka birçok yolu var. Sorun, ORM'nin her zaman (en azından ilişkisel veritabanları için) kullanılacak "çözüm" olarak görülmesidir. Bir projedeki bazı kullanım durumları için kullanılmamasını önermeye çalışmak boştur ve ORM'nin kendisine bağlı olarak bazen imkansızdır, çünkü önbellekler ve geç yürütme bazen bu araçlar tarafından kullanılır.

Genel soru 1 .: (işlemler)

Tek bir çözüm olduğunu düşünmüyorum. Tasarımınız nesne yönelimli ise, her kullanım durumu için bir "üst" yöntem olacaktır. İşlem orada olmalı.

Diğer kısıtlamalar tamamen yapaydır.

Genel soru 2 .: (toplu işlemler)

Bir ORM ile, (bildiğim çoğu ORM için) tek tek nesnelerden geçmek zorunda kalırsınız. Bu tamamen gereksizdir ve eliniz ORM tarafından bağlanmazsa muhtemelen tasarımınız olmaz.

"Mantık" ı SQL'den ayırma gereksinimi ORM'lerden gelir. Bunu söylemek zorundalar , çünkü destekleyemezler. Doğal olarak "kötü" değildir.

özet

Demek istediğim, ORM'lerin bir proje için her zaman en iyi araç olmadığı ve öyle olsa bile, bir projedeki tüm kullanım durumları için en iyisi olması pek olası değildir.

Benzer şekilde, DDD'nin dataobject-depo soyutlaması da her zaman en iyisi değildir. Şimdiye kadar söyleyebilirim ki, bunlar nadiren optimal tasarımdır.

Bu bizi tek bedene uygun bir çözüm bırakmaz, bu yüzden her kullanım durumu için ayrı ayrı çözümler düşünmeliyiz, bu iyi bir haber değildir ve işimizi daha da zorlaştırır :)


Orada çok ilginç noktalar, varsayımları onayladığınız için teşekkür ederim. Kalıcı olmanın başka birçok yolu olduğunu söyledin. Hala PI sağlayacak olan grafik veritabanlarıyla (ORM yok) kullanılacak performans tasarım desenini önerebilir misiniz?
Çift M

1
Aslında ilk etapta izolasyona (ve ne tür) ihtiyacınız olup olmadığını sorgulayacağım. Teknoloji başına yalıtım (yani veritabanı, kullanıcı arabirimi vb.), Veritabanı teknolojisinin daha kolay değiştirilmesi avantajı için neredeyse otomatik olarak kaçınmaya çalıştığınız "beceriksizlik" getirir. Ancak maliyet, iş mantığının daha zor bir değişimidir, çünkü bu katmanlar boyunca yayılır. Ya da değişen veritabanlarını zorlaştıracak, ancak mantığı değiştirmeyi kolaylaştıracak iş fonksiyonları boyunca bölünebilirsiniz. Hangisini gerçekten istiyorsun?
Robert Bräutigam

1
Etki alanını (örneğin, işletme işlevleri) modelliyor ve veritabanını soyutlamıyorsanız (ilişkisel veya grafik önemli değilse) en iyi performansı elde edebilirsiniz. Veritabanı kullanım senaryosundan soyutlanmadığından, kullanım senaryosu istediği en uygun sorguları / güncellemeleri uygulayabilir ve istediğini gerçekleştirmek için bazı garip nesne modellerinden geçmesi gerekmez.
Robert Bräutigam

Temel amaç, anlaşılması, genişletilmesi ve test edilmesi kolay temiz kodlara sahip olmak için kalıcılık endişelerini iş mantığından uzak tutmaktır. DB teknolojilerini değiştirebilmek sadece bir bonus. Kullanabileceğiniz (ancak kullanılmasına izin verilmeyen) güçlü sorgular nedeniyle grafik DB'lerle daha güçlü görünen verimlilik ve cehalet arasında açıkça bir sürtünme olduğunu görebiliyorum.
Çifte M

1
Bir Java Enterprise geliştiricisi olarak, son yirmi yıldır kalıcılığı mantıktan ayırmaya çalıştığımızı söyleyebilirim. Çalışmıyor. Birincisi, ayrılma asla gerçekten gerçekleşmedi. Bugün bile, sözde "iş" nesnelerinde veritabanı ile ilgili her türlü şey var, ana olanı veritabanı kimliği (ve bir çok veritabanı ek açıklaması). İkincisi, dediğin gibi, bazen iş mantığı her iki şekilde de veritabanında yürütülür. Üçüncüsü, belirli veritabanlarına sahip olmamızın nedeni, verilerin olduğu yerde en iyi şekilde yapılan bazı mantığın boşaltılmasını sağlamaktır.
Robert Bräutigam
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.