ActiveRecord modelinin sakıncaları nelerdir?


30

Veri erişimi / iş nesneleri için ActiveRecord desenini kullanmanın sakıncaları nelerdir merak ediyorum. Kafamın üstünden düşünebildiğim tek şey, Tek Sorumluluk İlkesini ihlal ettiğidir, ancak AR modeli, yalnızca bu nedenin, kullanmamayı haklı çıkarmak için "yeterince iyi" görünmediği kadar yaygındır (tabii ki benim Çalıştığım kodun hiçbiri SOLID ilkelerinden herhangi birini takip etmediğinden , görünüm eğrilebilir .

Şahsen ben değil o sınıfın gibi hissediyor çünkü çok fazla yapıyor (AR "doğal" hisseden bir Ruby on Rails uygulama, yazma hariç) ActiveRecord hayranıyım ve veri erişim sınıfına kendisine kadar olmamalı ele almak için. İş nesnelerini döndüren havuzları kullanmayı tercih ederim. Çalıştığım kodun çoğu, (yöntemin neden bir boole olduğunu bilmiyorum) biçiminde bir ActiveRecord varyasyonunu kullanma eğilimindedir:

public class Foo
{
    // properties...

    public Foo(int fooID)
    {
        this.fooID = fooID;
    }

    public bool Load()
    {
        // DB stuff here...
        // map DataReader to properties...

        bool returnCode = false;
        if (dr.HasRows)
            returnCode = true;

        return returnCode;
    }
}

veya bazen, public static Foo FindFooByID(int fooID)bulucular için bir yönteme ve public void Save()tasarruf / güncelleme hatlarında bir şeylere sahip olmanın "geleneksel" yoludur .

Ben ActiveRecord hayata geçirilmesi ve kullanımı genellikle çok daha kolaydır olsun, ama biraz görünüyor çok karmaşık uygulamalar için basit ve daha kolay değiş tokuş etmek zorunda saymıyorum bir Deposu (içinde veri erişim mantığı sararak daha sağlam bir mimariye sahip olabilir veri erişim stratejileri, örneğin belki Stored Procs + DataSets kullanıyorsunuz ve LINQ ya da başka bir şeye geçmek istiyorsunuz.

Öyleyse, ActiveRecord'un iş için en iyi aday olup olmadığına karar verirken göz önünde bulundurulması gereken bu modelin diğer sakıncaları nelerdir?

Yanıtlar:


28

En büyük dezavantajı, sizin “varlıklarınız”, birçok kötü tasarım kararına yol açan kendi sebatlarının farkında olduğudur.

Diğer hususlar, aktif kayıt araçlarının çoğunun temelde sıfırdan indirme katmanı olan tablolara 1 ile 1 arasında eşleşmesidir. Bu, küçük ölçeklerde çalışır, ancak çözülmesi zor sorunlarınız olduğunda dağılır.


Nesnelerinizin kalıcılığı hakkında bilgi sahibi olmanız, aşağıdaki gibi şeyleri yapmanız gerektiği anlamına gelir:

  • kolayca her yerde veritabanı bağlantısı var. Bu genellikle kötü kodlamaya veya her yerden etkilenebilecek bir tür statik bağlantıya yol açar.
  • nesneleriniz nesnelerden çok SQL gibi görünme eğilimindedir.
  • veritabanında kökleşmiş çünkü uygulamada bir şey yapmak zor bağlantısı kesildi.

Bunun üzerine bir sürü kötü karar vermiş olursun.


2
“diğer kötü tasarım kararları” hakkında ayrıntılı bilgi verir misiniz?
kevin cline

2
Teşekkürler. Bu sorunları Ruby on Rails'in geliştirilmesinde bir sorun olarak bulamadım. Davranış ve sebat ayrı ayrı test edilebilir. IMO'nun kalıcılığı davranıştan ayırması çok az pratik değere sahiptir.
kevin cline

kevin: bu şeyler, karışımlar ve ördek yazma gibi yakut özelliklerin dezavantajıdır. Statik dillerle - OP'nin sorusunda kullandığı C # gibi - ikisini ayırmak biraz daha zor.
Wyatt Barnett

@Wayne: Bana göre, sınıflar sadece metotları içine alan kutulardır - İş mantığını sebattan ayrı sınıflara koyarak ayırırım veya sadece iş metotlarının yapmadığından emin olarak onları kavramsal olarak ayırırım / O. Yetki verilmemiş temsilcilik desteğine sahip dillerde (örneğin Java), bu çok miktarda kod tasarrufu sağlar. OTOH, sadece Hazırda Bekleme'ye giriyorum, böylece tamamen yanılıyor olabilirim.
kevin cline

4
İki şey ekleyeceğim; 1. Kalıcılık mekanizmasıyla bağlantı, ünitenin uygun bir şekilde test edilmesini imkansız değilse de zorlaştırır. 2. Aktif Kayıt, kodunuzu merkezi bir kalıcılık mekanizmasındaki ilişkilere yapıştırır ve karar verirseniz monolitinizi ayırmanızı gerçekten zorlaştırır.
istepaniuk

15

Aktif kaydın en büyük sakıncası, etki alanınızın genellikle belirli bir kalıcılık mekanizmasına sıkı sıkıya bağlı kalmasıdır. Bu mekanizma, belki dosya tabanlı, DB tabanlı kalıcılık arasında veya veri erişim çerçeveleri arasında genel bir değişiklik gerektiriyorsa, bu modeli uygulayan HER sınıfı değişebilir. Dile, çerçeveye ve tasarıma bağlı olarak, DB'nin bulunduğu yeri değiştirmek veya "sahibi" olmak kadar basit bir şey bile, veri erişim yöntemlerini güncellemek için her nesnenin içinden geçmeyi gerektirebilir (bu, kolay erişim sağlayan çoğu dilde nadirdir). Bağlantı dizeleri ile dosyaları yapılandırmak için).

Aynı zamanda genellikle kendinizi tekrarlamanızı gerektirir. Süreklilik mekanizmalarının çoğu, bir DB'ye bağlanmak ve bir işlemi başlatmak için birçok ortak koda sahiptir. KURU (Kendinizi Tekrar Etmeyin) size bu tür bir mantığı merkezileştiren bir kodlayıcı olarak söyleyecektir.

Aynı zamanda atomik işlemleri zorlaştırır. Bir nesne grubunun hepsi ya da hiç bir şekilde kaydedilmesi gerekiyorsa (bir Fatura ve Fatura ve Fatura ve / veya Müşteri ve / veya GL girişleri gibi), bir nesnenin diğer tüm nesneleri bilmesi ve kalıcılığını kontrol etmesi gerekir ( kontrol nesnesinin kapsamını genişleten, birbirine bağlı büyük kayıtlar, bağımlılıkları hakkında her şeyi bilen kolayca “tanrı nesneler” haline gelebilir veya tüm işlem üzerindeki kontrol, etki alanının dışından ele alınmalıdır (ve bu durumda neden kullanıyorsunuz? AR?)

Aynı zamanda Nesne Yönelimli bir bakış açısıyla "yanlış" dır. Gerçek dünyada, bir fatura kendini nasıl dosyalayacağını bilmiyor, peki neden bir Fatura kodu nesnesi kendisini DB'ye nasıl kaydedeceğini biliyor? Elbette, “nesnelerin yalnızca gerçek dünyadaki meslektaşlarının neler yapabileceğini modellemesi gerekir” e aşırı bağlılık anemik alan modellerine yol açacaktır (bir fatura aynı zamanda kendi toplamını nasıl hesaplayacağını bilmez, ancak bu toplamın hesaplanmasını böler) başka bir nesne genellikle kötü bir fikir olarak kabul edilir).


Kalıcılığın çok basit bir anahtar kelime veya komutun arkasında tanımlanabileceği veya soyutlanabileceği Ruby'de sorun daha az olur. Çeşitli kalıcılık mekanizmalarını kurmak için daha fazla LoC gerektiren .NET'te, özellikle her atom için bir SQL bağlantısının olması, özellikle de bir atomik işlemde birden fazla nesnenin kaydedilmesi gerektiğinde gereksizdir. DB'ye bağlanma, bir Faturayı veya Müşteriyi kaydettiğinizde aynı görünüyor. Ortak şeyleri, kod tabanınızdaki tüm ActiveRecord nesneleri için ortak olan bir temel sınıfa soyutlar ya da kendi sınıfına
çıkarırsınız

puanlarınızı gösteren Ruby ActiveRecord kullanımına örnekler verebilir misiniz? Bu sorunları yaşamadım ama başvurum oldukça küçüktü. Ruby'ye göçler yazabilir ve farklı DB uygulamalarına uygulayabilirim. Ruby'nin ActiveRecord'un tekrarlamayı engellemede çok faydalı olduğunu öğrendim, bu yüzden neden ActiveRecord'u kullanmanın tam tersi bir etki yaratacağını iddia edersiniz. Tasarruf ile ilgili bir sorun yaşamadım: Sadece nesne modelini değiştirdim ve AR'nin nesne modelini yansıtacak şekilde DB'yi güncellemesine izin verdim.
kevin cline

2

Temel dezavantajı: Etki alanı modelinizi karmaşıklaştırır, çünkü yalnızca iş mantığını değil aynı zamanda kalıcılık bilgisini de tutar.

Dolayısıyla çözüm, ORM'nin Veri Eşleyici uygulamasını kullanmaktır . Bu, kalıcılık katmanını ayırır ve şimdi varlık iş mantığına daha fazla odaklandık. Doktrin olan Veri Mapper ORM.

Ancak bu yaklaşımın da biraz karmaşıklığı var. Şimdilik sorgu için Veri Eşleştiricisine fazlasıyla güveniyorsunuz, sorgu odaklı bir ortam oluşturuyor. Basitleştirmek için Etki Alanı Modeli arasında bir katman daha tanıtıldı ve Veri Eşleyici'ye Depo adı verildi .

depo kalıcılık katmanını özetler. Nesne yönelimli programlama anlamında mantıklıdır, tüm aynı tip nesnelerin (veritabanı tablosunda depolanan tüm varlıkların) toplanmasıdır ve toplama işlemi, ekleme , kaldırma gibi işlemlerin üzerinde işlem yapabilirsiniz . içerir vs.

Örneğin, Kullanıcı Varlığı için yapabileceğiniz aynı tür kullanıcı nesnelerinin (kullanıcılar tablosunda depolanan) koleksiyonunu temsil eden UserRepository . Kullanıcılar tablosunu sorgulamak için Kullanıcı Veri Eşleyici'yi kullanır, ancak etki alanı modeli Kullanıcı'ya soyutlanır .

Deposu desen türüdür veri erişim katmanı , başka bir şeydir veri erişim nesnesi yalnızca farklar Veri Havuzu vardır Agrega Kök özelliği


Havuz ve DAO desenleri farklıdır, DAO genel veri erişimidir, Havuz, tüm aynı tip nesnelerin toplanmasının sürekliliği içindir. Yani tüm havuzlar aynı arayüze sahip olmalıdır (dizi veya liste gibi). Diğer yöntemlerin kralı Depoya ait değildir . DAO düşük seviyedir, Havuz DAO kullanabilir. Genellikle, programcılar (özellikle PHP) DAO olarak Havuz kullanır, ancak doğru değildir.
xmedeko
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.