ORM'ler zengin alan modelleri oluşturmayı mümkün kılıyor mu?


21

Hibernate'i yaklaşık 8 yıl boyunca projelerimin çoğunda kullandıktan sonra, kullanımını engelleyen ve uygulamaların yalnızca DB ile depolanan prosedürler aracılığıyla etkileşime girmesini isteyen bir şirkete indim.

Bunu birkaç hafta yaptıktan sonra, oluşturmaya başladığım uygulamanın zengin bir etki alanı modeli oluşturamadım ve uygulama sadece (korkunç) bir işlem komut dosyası gibi gözüküyor.

Bulduğum bazı konular:

  • Saklı yordamlar yalnızca minimum miktarda veri yüklediğinden, nesne grafiği gezinilemiyor, bu da bazen farklı alanlara sahip benzer nesnelerimiz olduğunu gösteriyor. Bir örnek: tüm verileri müşteriden almak için saklı bir prosedürümüz var, diğeri ise hesap bilgilerini ve müşteriden birkaç alanı almak için.
  • Mantığın çoğu yardımcı sınıflarda sona ermektedir, bu nedenle kod daha yapılandırılmıştır (eski C yapıları olarak kullanılan varlıklar ile).
  • Daha sıkıcı iskele kodu, sonuç kümelerini saklı bir yordamdan ayıklayan ve bir varlık içine koyan hiçbir çerçeve olmadığı için.

Benim sorularım:

  • Herhangi biri benzer bir durumda mıydı ve mağaza prosedürü yaklaşımına katılmıyor mu? ne yaptın?
  • Saklı yordamları kullanmanın gerçek bir yararı var mı? aptal noktadan başka "hiç kimse bir damla tablo yayınlayamaz".
  • Saklı yordamları kullanarak zengin bir etki alanı oluşturmanın bir yolu var mı? DAO'ları / Depoları nesne grafiği üzerinde gezinmek için varlıklara enjekte etmek için AOP kullanma olasılığının olduğunu biliyorum. Bu seçeneği sevmedim, çünkü vudu yakın.

Sonuç

İlk olarak, cevaplarınız için hepinize teşekkür ederim. Geldiğim sonuç, ORM'lerin Zengin Etki Alanı modellerinin oluşturulmasını sağlamadığı (bazı kişilerin söylediği gibi), ancak (genellikle tekrarlayan) çalışma miktarını basitleştirdiğidir. Aşağıdaki, sonucun daha ayrıntılı bir açıklamasıdır, ancak herhangi bir katı veriye dayanmamaktadır.

Çoğu uygulama, diğer sistemlere bilgi talep eder ve gönderir. Bunu yapmak için, model terimlerinde bir soyutlama yaratırız (örneğin bir iş etkinliği) ve etki alanı modeli olayı gönderir veya alır. Etkinlik genellikle modelden küçük bir bilgi alt kümesine ihtiyaç duyar, ancak tüm model için değil. Örneğin, bir çevrimiçi mağazada, bir ödeme ağ geçidi bir kullanıcı için ücret talep etmek için bazı kullanıcı bilgilerini ve toplamı ister, ancak satın alma geçmişi, kullanılabilir ürünler ve tüm müşteri tabanını gerektirmez. Dolayısıyla, etkinliğin küçük ve özel bir veri kümesi var.

Bir uygulamanın veritabanını harici bir sistem olarak alırsak , Etki Alanı Modeli varlıklarını veritabanına eşleştirmemizi sağlayan bir soyutlama oluşturmamız gerekir ( NimChimpsky'nin dediği gibi , bir veri eşleyicisi kullanarak). Açık olan fark şu ki, her bir model varlık için veritabanına bir harita oluşturmaya ihtiyacımız var (ya eski bir şema ya da saklı yordamlar), ikisi eşzamanlı olmadığından, bir etki alanı parçasının kısmen eşleşebileceği için fazladan acı çekiyor. Bir veritabanı varlığına (örneğin, yalnızca kullanıcı adı ve şifreyi içeren bir UserCredentials sınıfı) diğer sütunlara sahip bir Kullanıcılar tablosuna eşlenir) veya bir etki alanı modeli öğesi birden fazla veritabanı varlığına (örneğin bire bir varsa) eşlenebilir masada bir eşleme, ancak tüm verileri sadece bir sınıfta istiyoruz).

Birkaç varlığa sahip bir uygulamada, varlıkları çaprazlamak gerekmiyorsa, fazladan iş miktarı az olabilir, ancak varlıkları geçmek için şartlı bir ihtiyaç olduğunda artar (ve böylece bir çeşit tembel uygulamak isteyebiliriz) Yükleniyor'). Bir uygulama daha çok varlığa sahip olmak için büyüdükçe, bu çalışma artar (ve doğrusal olmayan bir şekilde arttığı hissine sahibim). Buradaki varsayım, bir ORM'yi yeniden icat etmeye çalışmadığımızdır.

Veritabanını harici bir sistem olarak ele almanın bir yararı, içinde çalışan bir uygulamanın 2 farklı versiyonunu istediğimiz durumları kodlayabilmemizdir. Bu, üretime sürekli teslimat senaryosunda daha ilginç hale geliyor ... ama bunun ORM'lerle daha az ölçüde mümkün olduğunu düşünüyorum.

Veritabanına erişimi olmasa bile, bir geliştiricinin bir sistemde depolanan tüm bilgileri almasa bile, yalnızca kötü amaçlı kodları enjekte ederek (ör. Müşterilerin kredi kartı detaylarını kaydeden satırı kaldırmayı unuttuğuma inanamıyorum, sevgili lordum! ).


Küçük güncelleme (6/6/2012)

Saklı yordamlar (en azından Oracle'da) Sıfır kesinti süresinde sürekli teslimat gibi bir şey yapmayı önler, çünkü tabloların yapısındaki herhangi bir değişiklik prosedürleri ve tetikleyicileri geçersiz kılar. Böylece, DB güncellenirken, uygulama da azalacaktır. Oracle, Sürüme Dayalı Yeniden Tanımlama adı verilen bir çözüm sunar , ancak bu özellik hakkında sorduğum birkaç DBA, bunun kötü bir şekilde uygulandığını ve üretim DB'sine koymadıklarını belirtti.


Açıkçası, Hazırda Bekletme'nin yaptığı şeyi yapabilir ve kalıtımdan, dinamik grafik proxy nesnesi oluşturmak için kullanabilirsiniz; bu, nesne grafiğini almanıza olanak tanır. Bu SP ile son derece hacky olsa da: D
Max

Bu yüzden, kış uykusu ekibinin sahip olduğu 10 + yıllık tecrübe olmadan, kış uykusunun yarısını yeniden keşfedeceğim :).
Augusto

1
Herhangi bir DBA, belirli tabloların belirli kullanıcılar tarafından atılmasını engellemelidir. Nasıl yapmaya çalıştığınızın önemi olmamalıdır.
JeffO

1
Mybatis'e bir göz atabilirsiniz - ihtiyacınız olan özelliği sağlayabilir. Bir haritalama çerçevesinden daha az bir ORM. İstediğiniz gibi SQL yazabilir ve Mybatis'e nesne modelinizde nereye koyacağınızı söyleyebilirsiniz. Sahip olduğunuz durum gibi görünen çok sayıda sorgu içeren büyük nesne grafiklerini işleyecektir (çok fazla ince saklı yordam).
Michael K

1
@Augusto: Benzer bir durumdaydım, SP kullanımı nedeniyle değil, nesne ilişkilerini desteklemeyen tescilli bir haritalama çerçevesinin kullanılması nedeniyle. Günler içinde uygun bir ORM kullanarak dakikalar içinde yazılabilecek bir kod yazarak geçirdik. Bu sorunu hiç çözmedim.
kevin cline

Yanıtlar:


16

Başvurunuz hala alan odaklı tasarım ilkelerinden modellenmelidir. Bir ORM kullanıp kullanmadığınızı, düz JDBC'yi, SP'leri (ya da her neyse) çağırmak önemli olmamalıdır . Umarım modelinizi SP'lerden soyutlayan ince bir katman bu durumda hile yapmalıdır. Başka bir afişte belirtildiği gibi , SP'leri ve sonuçlarını bir hizmet olarak görmeli ve sonuçları etki alanı modelinizle eşlemelisiniz.


Martijn, uygulamanın DDD ilkeleri kullanılarak modellenmesi gerektiğine katılıyorum, ancak karşılaştığım sorun (ve bir çözüm varsa lütfen bana bildirin!) Bazı saklanan işlemlerin bir DDD varlığına anında ulaşmak için çok az bilgi vermesidir. Lütfen , saklı yordamların döndürdüğü bilgiler hakkında biraz daha fazla bilgi verdiğim bu yoruma bakın . Birden fazla saklı işlemi çağırarak ve örneğin tüm kullanıcı ayrıntılarını alarak ve sonra tüm hesap bilgilerini almak için başka birisini çağırarak bunu atlatabilirim, ancak yanlış geliyor :).
Augusto

1
@Augusto Pekala ... Siz uygulama geliştiricisisiniz, bu nedenle belirli nesnelerin NULL değerine ayarlanmış olarak bulunmasının mantıklı olup olmadığına karar vermelisiniz. Mantıklıysa (örneğin belirli bir görev için) öyleyse bırak. Değilse, SP yazarından daha fazla veri sağlamasını isteyin, böylece nesnelerinizi oluşturabilirsiniz.
Jacek Prucia

Ve Jacek'in yorumuna ek olarak - 2'den fazla saklanan procs'u çağırmak gerçekten mükemmel bir şekilde kabul edilebilir, etki alanı modelinizi oluşturmak için bunları tekrar çağırmanız gereken iki uzak hizmet olarak düşünün :-).
Martijn Verburg

@ Martijn: Benim tecrübeme göre, ince bir katman yeterli değil. Eşleme kodu, temeldeki iş mantığından çok daha uzun olabilir.
kevin cline

@Kevin cline - İyi nokta, 'umutla' cevabını koydum :-)
Martijn Verburg

5

Saklı yordamları kullanmanın gerçek bir yararı var mı?

Finans dünyasında (ve Sarbanes-Oxley uyumluluğunun gerekli olduğu yerlerde ), yapmaları gerekeni yapmalarını sağlamak için sistemleri denetleyebilmeniz gerekir. Bu gibi durumlarda, tüm verilere erişim saklı yordamlar aracılığıyla olduğunda uyumu sağlamak çok daha kolaydır. Ve tüm geçici SQL kaldırıldığında, bir şeyleri gizlemek çok daha zordur. Bunun neden "iyi bir şey" olacağına bir örnek olarak, sizi Ken Thompson'ın Trusting Trust üzerine Düşünceler adlı klasik makalesine yönlendiririm .


evet milyon kere evet! Ayrıca, kullanıcıların tablolara doğrudan haklara sahip olmamaları ve depolanan procs'ların bu kadar yardımcı olmaları dahil, yapmaları gerekmeyen şeyleri yapamadıklarından emin olmanız gerekir.
HLGEM

1
Halka açık bir şirket için çalışıyorum ve biz SOX'u çok istiyoruz. Denetim konusundaki zayıf bilgim olabilir, ancak denetimin DB düzeyinde (depolanmış işlemlerle) veya uygulama düzeyinde yapılması arasındaki farkı göremiyorum. Her uygulamanın kendi DB şeması olmalıdır ve bu şemaya farklı uygulamalar arasında paylaşılmak yerine, uygulamadan erişilebilir.
Augusto

bozuk link ...
Alex R

@AlexR, sabit bağlantı
Tangurena

2

Saklı yordamlar, istemci tarafı SQL kodundan çok daha verimlidir. DB'de bazı optimizasyonlar yapmasına izin veren önceden derlerler.

Mimari olarak, bir SP, bir görev için gerekli olan minimum veriyi geri gönderir; bu, daha az veri aktarıldığı için iyidir. Eğer böyle bir mimariye sahipseniz, DB'yi bir servis olarak düşünmeniz gerekir (bunu bir web servisi olarak düşünün ve her SP'yi çağırmanın bir yöntemidir). Bu şekilde çalışmak sorun olmamalı, ORM ise sanki yerel verilermiş gibi uzak verilerle çalışmanıza rehberlik ediyor, bu yüzden dikkatli değilseniz performans sorunlarının ortaya çıkmasını sağlamanız için sizi kandırıyor.

SP'leri tamamen kullandığımız durumlarda, DB bir veri API'si sağladı ve kullandık. Bu özel uygulama çok büyük ölçekli ve şaşırtıcı derecede iyi bir performans sergiledi. SP'lerden sonra söylenen kötü bir şey söylemeyeceğim!

Başka bir avantaj var - DBA'lar sizin için tüm SQL sorgularınızı yazacak ve DB'deki tüm ilişkisel hiyerarşiyi mutlu bir şekilde ele alacaktır, bu yüzden de zorunda değilsiniz.


3
gbjbaanb, söylediklerinizin çoğu eski veritabanları için geçerlidir. Yeni veritabanlarının çoğu, hangi yeni optimizasyonların kullanılacağına karar vermek için sorguları sık sık yeniden derler (üretilen depolanmış olsalar bile). DB'yi harici bir sistem olarak kullanma hakkında söylediklerinize katılıyorum, ancak aynı zamanda uygulamanın veritabanına sahip olduğu ve her ikisinin de mümkün olduğu kadar senkronize olması gerektiği gibi çok çalışma olduğunu da görüyorum. Örneğin, tablo / sınıfların ve alanların / sütunların isimlendirilmesiyle. Ayrıca, DBA'ların prosedürleri yazmasına izin verme yaklaşımı, multidisipliner bir takıma sahip olmak yerine, geliştirme siloları gibi kokuyor.
Augusto

7
SP'ler her zaman daha verimli olmak zorunda değildir ve SQL'i DBA'lara teslim etmenin kötü bir yol olduğunu düşünüyorum. Bir etki alanı uzmanı olarak, geliştirici hangi veriyi almak istediğini ve nasıl elde edeceğini bilmelidir
Martijn Verburg

1
Bu iyi bir cevap, ancak deneyimlerime göre çoğu müşteri, ORM araçlarınızı uygulama katmanında tam olarak kullanmanın zorluğuna karşı saklı yordamlarla veri erişimini kontrol etmek için performans kazanmalarına ihtiyaç duymuyor. Çoğu zaman, yazılım mağazalarında verilen ve bu "gri sakal" saklı yordam programcılarının başka hiçbir yeteneği olmayan , şişirilmiş maaşlarını haklı gösterme ihtiyacı duydukları bu mimari kararları göremiyorum .
maple_shaft

1
@Augusto the approach of letting the DBAs write the procedures smells like development silos+100 hakikat bu gem için size internets. Bunu her zaman veri erişiminin saklı yordamlarla kontrol edildiği bir durum olarak gördüm.
maple_shaft

1
@maple_shaft: neden, SP’leri yazan DBA’lar geliştirici ekibinin bir parçası olarak kabul edilmiyor mu? Çalıştığı yerde, sistemin bu yönünü gerçekten iyi bilen, çoğu genel amaçlı geliştiriciden çok daha iyi olan uzman kodlayıcılar. Bu ORM'lerin popülaritesine yol açan sorun olabilir. Yani, hiç kimse GUI'yi bir tasarımcıya sahip olmaktan iki kez düşünmez, öyleyse neden şema üzerinde çalışan bir veri mimarının nefreti?
gbjbaanb

2

Sık sık olan şey, geliştiricilerin ORM nesnelerini etki alanı modelleri olarak yanlış kullanmalarıdır.

Bu yanlıştır ve etki alanınızı doğrudan DB şemanıza bağlar.

Gerçekten olması gereken, alan adlarını istediğiniz kadar zengin ve ORM katmanını ayrı olarak kullanın.

Bu, her nesne kümesi arasında eşlemeye ihtiyaç duyacağınız anlamına gelir.


1
Bu iyi bir fikir ama daha küçük projeler için gerçekten fazla abartılı gibi hissetmeye başlıyor. Bu yaklaşım ayrıca ORM kalıcılık katmanı ve etki alanı modeli arasında bir çeviri katmanı gerektirir.
maple_shaft

@maple_shaft aynı fikirdeydi, ve demek istediğim "mapping" :-)
ozz

@Ozz, çalıştığım yol tam olarak, varlık sınıfları etki alanı modeli ARE (ve oldukça başarılı bir şekilde ekleyebilirim). Etki alanı modelini şemaya bağladığını kabul ediyorum, ancak tam olarak istediğim bu, yapılandırma konvansiyonunu kullandığım gibi ve güzel yan etkisi, bir varlık üzerinde bir alan görürsem, zor düşünmem gerekmediğidir. Bu bilgilerin depolandığı tablo ve sütunun adı hakkında.
Augusto

@Augusto Ben de yaptım! maple_shaft'ın dediği gibi, küçük CRUD tarzı uygulamalar için sorun değil, ancak OP'nin bulduğu gibi birçok sorun var. Bunun bir örneği, çok sayıda haritalama tablonuzun bulunduğu yer olabilir. Örneğin: Öğrencileri kendi sınıflarına haritalayan ve yalnızca StudentID ve classID içeren StudentClasses. Bunu etki alanınızda eşlemek istemeyebilirsiniz. Bu sadece benim kafamdaki en iyi örneklerden biri.
ozz

2
@Ozz: Yorumunuz bir ORM fikriyle çelişiyor gibi görünüyor. Bir ORM "etki alanınızı doğrudan DB şemanıza bağlamaz". ORM , alanınızı ayrı bir DAO katmanına ihtiyaç duymadan, bir DB şemasıyla eşleştirir . Bu bir ORM'nin amacı. Ve ORM'lerin çoğu, eşleştirme tablosu için hiçbir etki alanı modeli gerektirmeden, çok sayıda eşleştirmeyi gayet iyi idare eder.
kevin cline

1

Etki alanı nesneleriniz, Hazırda Beklet işlevini kullanmak için gerekli olmadıkça, lütfen doldurulabilir. Bence uygun terim veri haritasıdır . Kalıcı verilerinizin etki alanı nesnelerinizden tamamen farklı bir yapıya sahip olması çok olasıdır.


Şu anda veri eşleştiricileri kullanıyoruz, ancak sorun, procs'ları, bazen bir nesneyi doldurmak için yeterli olmayan (belki de saklı yordamların daha fazla bilgi döndürmesine izin vermemiz gerekir), minimum veri kümesini döndürmeleridir. Örneğin, bir mağaza proc bir kullanıcı e-postası, ad, soyad; diğeri ise kullanıcı kimliği ve adres ekler. Veriler farklı olduğu için verileri depolamak için farklı nesneler kullanıyoruz, bu da farklı 'Kullanıcı' sınıflarımız olduğu anlamına gelir. Miras kullanmaktan kaçınmaya çalışıyorum, çünkü yanlış kullandığını düşünüyorum.
Augusto

@Augusto: Arayüzler?
Kramii Monica

@Karmii, arayüzlerin burada yardımcı olacağını sanmıyorum, çünkü o zaman mantığı çoğaltmak zorunda kalacağız çünkü farklı sınıflarda. Ya da arayüzleri kullanabiliriz ve ardından işlemeyi bir yardımcı sınıfa devredebiliriz, ancak bu gerçekten OO değil: (.
Augusto

1
@Augusto Sorunu anlamadım: "saklanan işlemler, bazen bir nesneyi doldurmak için yeterli olmayan, minimum veri kümesini döndürür" Böylece, sproc'u değiştirir veya başka bir tane yaratırsınız ve ardından veri eşleştiricisinin eşlemeyi yapmasına izin verirsiniz
NimChimpsky
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.