Veri Nesneleri İçin Bağımlılık Enjeksiyonu Kullanılsın mı?


11

Sadece bağımlılık enjeksiyonunu öğreniyorum ve bir şeye takıldım. Bağımlılık Enjeksiyonu, yapıcı aracılığıyla bağımlı sınıflar göndermenizi önerir, ancak bunun veri nesneleri için gerekli olup olmadığını merak ediyorum. Birim-Test Edilebilirlik, DI'nin temel faydalarından biri olduğundan, yalnızca verileri depolayan ve herhangi bir prosedürün hiç bir şekilde test edilmediği bir veri nesnesi olur, bu da DI'yi gereksiz bir karmaşıklık katmanı yapar veya yine de bağımlılıkları göstermeye yardımcı olur veri nesneleri ile?

Class DO{
    DO(){
        DataObject2List = new List<DO2>();
    }

    public string Field1;
    public string Field2;
    public List<DO2> DataObject2List;
}

Class DO2{
    public DateTime Date;
    public double Value;
}

"Veri nesnesi" ile tam olarak ne demek istiyorsun? Bu standart bir terim değil. Bir DTO'dan mı bahsediyorsunuz yoksa herhangi bir yöntemi olmayan herhangi bir sınıfa mı başvuruyorsunuz (bir alan adı modelinin özellikle sıkıcı bir kısmı gibi)? İkisi arasında büyük bir fark var.
Aaronaught

Tabii, sadece yöntemsiz bir sınıf, sadece veri depolayan bir sınıf demek istiyorum. Veri Nesnesi bunun için doğru terim değilse, var mıdır, yoksa yöntemsiz bir sınıf mıdır?
sooprise

@sooprise Bu iyi bir soru. İyi düşünmek.
Matthew Rodatus

@sooprise Belki de cevabım taban dışında. CRUD yöntemlerini nereye koyacaksınız? Ayrı bir veri erişim sınıfında Veri Nesneleri alıp onları bir veritabanı tablosuna devam? Yani DataAccess.Create (<DataObject>)?
Matthew Rodatus

1
@Matthew, bu bir Veri Erişim Nesnesi olacaktır - aslında OP'nin konuştuğu şey buysa, o zaman hiç de net değildir. Modern uygulamalar yine de havuzlara ve / veya iş birimlerine dayanarak bu modelden uzaklaşmaya meyillidir.
Aaronaught

Yanıtlar:


7

Burada kullandığınız bazı terminolojilerin, özellikle "bağımlılık" ve "bağımlılık enjeksiyonu" konularının açıklığa kavuşturulmasını önermek istiyorum.

Bağımlılık:

"Bağımlılık" tipik olarak başka bir sınıfın bağımlı olması gereken bazı işlevleri yerine getiren karmaşık bir nesnedir. Bazı klasik örnekler bir günlükçü veya veritabanı erişimcisi veya belirli bir iş mantığı parçasını işleyen bir bileşen olabilir.

Bir veriler sadece bazı gerekli işlevi yerine olmadığı bir DTO veya bir değer nesnesi gibi bir nesne, tipik olarak, bir "bağımlılığı" olarak ifade edilmez.

Bunu böyle bakıp sonra, (sizin örnekte ne yaptığını oluştururkenDO bir listesini nesneyi D02yapıcısı aracılığıyla nesneler) hiç "Bağımlılığı enjeksiyon" olarak kabul edilmemelidir. Sadece bir mülk oluşturuyor. Yapıcıda veya başka bir şekilde sağlamanız size kalmış, ancak sadece kurucudan geçirmeniz bağımlılık enjeksiyonu yapmaz.

Bağımlılık Enjeksiyonu:

Senin Eğer DO2sınıf aslında bazı ek işlevler sunuyorlardı DOsınıf ihtiyacı, o zaman gerçekten bir bağımlılık olacaktı. Bu durumda, bağımlı sınıf, DObir arabirime (ILogger veya IDataAccessor gibi) ve bu arabirimi sağlamak için arama koduna güvenmelidir (diğer bir deyişle, DOörneğe 'enjekte etmek' ).

Bağımlılığı bu şekilde enjekte etmek, DOnesneyi daha esnek hale getirir , çünkü her farklı bağlam, DOnesneye arabirimin kendi uygulamasını sağlayabilir . (Ünite testini düşünün.)


7

Sorudaki karışıklığı gidermek için elimden geleni yapacağım.

Her şeyden önce, "Veri Nesnesi" anlamlı bir terim değildir. Eğer sadece bu nesnenin belirgin özelliklerinden yöntemi yok yani, o zaman hepsi de var olmamalıdır . Yararlı bir davranışsız nesne aşağıdaki alt kategorilerden en az birine uymalıdır:

  • Değer Nesneleri veya "kayıtların" hiçbir kimliği yoktur. Ortamın bunu desteklediği varsayılarak, referans üzerine kopya semantiği ile değer türleri olmalıdır . Bunlar sabit yapılar olduğu için, bir VO sadece ilkel tip veya sabit bir ilkel dizisi olmalıdır. Bu nedenle, bir VO'nun herhangi bir bağımlılığı veya ilişkisi olmamalıdır ; varsayılan olmayan herhangi bir kurucu yalnızca değerin başlatılması amacıyla, yani değişmez olarak ifade edilemediği için var olur.

  • Veri Aktarımı Nesneleri genellikle yanlışlıkla değer nesneleriyle karıştırılır. DTOs yapmak kimlik sahibi ya da en azından onlar can . Bir DTO'nun tek amacı, bir alandan diğerine bilgi akışını kolaylaştırmaktır. Asla "bağımlılıkları" yoktur. Onlar olabilir (bir dizi veya koleksiyona yani) dernek var ama çoğu insan yassı bunları yapmak için tercih ediyorum. Temel olarak, bir veritabanı sorgusunun çıktısındaki satırlara benzerler; genellikle bu nedenle kalıcı ya da tefrika edilmesi gereken ve geçici nesneler konum olamaz bu onları kullanışsız yapacak gibi herhangi bir soyut türlerini referans.

  • Son olarak, Veri Erişim Nesneleri bir tür veritabanına bir sarmalayıcı veya cephe sağlar. Bunların açıkça bağımlılıkları vardır - veritabanı bağlantısına ve / veya kalıcılık bileşenlerine bağlıdırlar. Bununla birlikte, bağımlılıkları neredeyse her zaman harici olarak yönetilir ve arayanlar için tamamen görünmezdir. In Active kayıt desen konfigürasyon üzerinden şeyi yönetir çerçeve var; daha eski (günümüz standartlarına göre eski) DAO modellerinde, bunları sadece konteyner yoluyla inşa edebilirsiniz. Bunlardan birini yapıcı enjeksiyonu ile görürsem çok, çok endişelendim.

Ayrıca düşünce olabilir varlık nesne veya "iş nesnesi" ve bu durumda do ama düşündüğün bu şekilde ya da düşünmek nedenlerle, destek bağımlılık enjeksiyon istiyorum. Kullanıcı kodunun yararı için değil , sorgu anlama veya tembel yükleme gibi süslü şeyler yapmak için kestiği bir proxy'yi sessizce enjekte edecek bir varlık yöneticisi veya ORM'nin yararı içindir .

Bunlarda genellikle do not enjeksiyon için bir kurucu sağlamaktayız; bunun yerine, özelliği sanal hale getirmeniz ve soyut bir tür kullanmanız gerekir (örneğin, IList<T>yerine List<T>). Gerisi perde arkasında gerçekleşir ve kimse daha akıllı değildir.

Sonuçta bir "veri nesnesine" görünür bir DI deseninin gereksiz olduğunu ve hatta muhtemelen bir kırmızı bayrağın olduğunu söyleyebilirim; ancak büyük ölçüde, bir veritabanından verileri temsil etmek için özel olarak kullanıldığı durumlar dışında, nesnenin varlığı kırmızı bir bayraktır. Hemen hemen her durumda bir kod kokusu, tipik olarak bir Anemik Etki Alanı Modeli'nin veya en azından bir Poltergeist'in başlangıcı .

Tekrarlamak için:

  1. "Veri nesneleri" oluşturmayın.
  2. Bir "veri nesnesi" oluşturmanız gerekiyorsa, bunun açıkça tanımlanmış bir amacı olduğundan emin olun . Bu amaç size DI'nin uygun olup olmadığını söyleyecektir. İlk başta olmaması gereken bir nesne hakkında anlamlı tasarım kararları vermek imkansızdır.

Fin.


0

Örneğinizde, DOherhangi bir işlevsel bağımlılığa sahip değildir (temelde hiçbir şey yapmadığı için). Somut tipine bağımlıdır DO2, bu DO2nedenle tüketicinin çocuk sınıfının kendi somut uygulamasını uygulayabilmesi için soyutla bir arabirim getirmek isteyebilirsiniz .

Gerçekten, buraya hangi bağımlılığı enjekte edersiniz?


Cevapladığım bir başka soruya göre, sorunun CRUD operasyonları içeren bir Veri Nesnesi olduğunu düşünüyorum. Veri nesnesine veritabanı bağımlılığı nasıl / nereye enjekte edilir? Yöntemlerde? Yapıcıda mı? Başka bir yol? Varsayım, bağımlılığın yöntemlerin gövdesinde gizlenmemesi gerektiğidir - bu da Veri Tabanı bağımlılığının Veri Nesnesinden ayrılmasını devre dışı bırakır, böylece Veri Nesnesi birim sınanabilir.
Matthew Rodatus

@Matthew Rodatus - Anlıyorum. Evet, bu durumda, iki seçeneğiniz vardır: kalıcılık hizmetini enjekte edin veya DOPersisternasıl devam edeceğini DOve onu yalnızca veriye dayalı bir nesne olarak (bence daha iyi) bırakacağını bilen başka bir sınıf oluşturun . İkinci durumda, DOPersisterveritabanı bağımlılığı ile enjekte edilir.
Scott Whitlock

Sorusunu tekrar okuduktan sonra daha az eminim. Analizim yanlış olabilir. Onun sorusunda DO'sunun herhangi bir prosedürü olmayacağını söyledi. Bu, kalıcılığın DO'da OLMADIĞI anlamına gelir. Bu durumda, cevabınız doğrudur - enjekte etmek için bağımlılık yoktur.
Matthew Rodatus

0

Bu, veri erişim katmanındaki bir Veri Nesnesi olduğundan, doğrudan bir veritabanı hizmetine bağlı olmalıdır. Yapıcıya bir DatabaseService belirtebilirsiniz:

DataObject dataObject = new DataObject(new DatabaseService());
dataObject.Update();

Ancak, enjeksiyonun yapıcıda olması gerekmez. Alternatif olarak, bağımlılığı her CRUD yöntemi aracılığıyla sağlayabilirsiniz. Bu nesneyi bir öncekine tercih ediyorum çünkü Veri Nesneniz, aslında devam etmeniz gerekene kadar nerede kalacağını bilmesine gerek yok.

DataObject dataObject = new DataObject();
dataObject.Update(new DatabaseService());

Kesinlikle yok değil uzakta REZİL yöntemleri inşaat gizlemek istiyor!

public void Update()
{
    // DON'T DO THIS!
    using (DatabaseService dbService = new DatabaseService())
    {
        ...
    }
}

Alternatif bir seçenek, geçersiz kılınabilir bir sınıf yöntemi ile DatabaseService oluşturmak olacaktır.

public void Update()
{
    // GetDatabaseService() is protected virtual, so in unit testing
    // you can subclass the Data Object and return your own
    // MockDatabaseService.
    using (DatabaseService dbService = GetDatabaseService())
    {
        ...
    }
}

Son bir alternatif, tekton tarzı bir ServiceLocator kullanmaktır. Bu seçeneği beğenmeme rağmen, birim test edilebilir.

public void Update()
{
    // The ServiceLocator would not be a real singleton. It would have a setter
    // property so that unit tests can swap it out with a mock implementation
    // for unit tests.
    using (DatabaseService dbService = ServiceLocator.GetDatabaseService())
    {
        ...
    }
}
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.