Sınıf Çoğaltma Kalıbı?


11

Şu anda mevcut projemde solo geliştirici olarak çalışıyorum. Projeyi, şirketten ayrılan başka bir geliştiriciden miras aldım. C # model görünüm denetleyicisi tarzı bir web uygulamasıdır. Nesne ilişkisel eşleme için Entity Framework kullanır. Etki alanı modelindeki türler için iki farklı sınıf kümesi vardır. Bir set ORM ile etkileşim için kullanılır ve diğeri MVC sisteminde model olarak kullanılır. Örneğin, aşağıdaki gibi iki sınıf olabilir:

public class Order{
    int ID{get;set;}
    String Customer{get;set;}
    DateTime DeliveryDate{get;set;}
    String Description{get;set;}
}

ve

public class OrderModel{
    String Customer{get;set;}
    DateTime DeliveryDate{get;set;}
    String Description{get;set;}
    public OrderModel( Order from){
        this.Customer= from.Customer;
        // copy all the properties over individually
    }
    public Order ToOrder(){
        Order result =new Order();
        result.Customer = this.Customer;
        // copy all the properties over individually
    }

}

Bu yaklaşımın (bir şey değiştiğinde kodu değiştirmek için daha fazla yer, bellekte oturan daha fazla nesne, verileri kopyalamak için daha fazla zaman harcadığım) birkaç dezavantajı düşünebilirim, ancak burada avantajların ne olduğundan emin değilim. Sanırım model sınıfları için daha fazla esneklik? Ama bunu varlık sınıflarını da alt sınıflandırarak elde edebilirim. Eğilim, bu iki sınıf grubunu birleştirmek ya da model sınıflarının varlık sınıflarının alt sınıfları olmasını sağlamak olabilir. Burada önemli bir şey mi eksik? Bu farkında olmadığım ortak bir tasarım deseni mi? Düşündüğüm refactor ile geçmemek için iyi nedenler var mı?

GÜNCELLEME

Buradaki bazı cevaplar, projeyle ilgili ilk açıklamamın bazı önemli ayrıntıların eksik olduğunu anlamamı sağlıyor. Projede var olan üçüncü bir sınıf grubu da vardır: sayfa modeli sınıfları. Onlar aslında sayfayı destekleyen model olarak kullanılanlardır. Ayrıca, kullanıcı arayüzüne özgü bilgiler içerir ve veritabanında bir siparişle depolanmazlar. Örnek bir sayfa modeli sınıfı şunlar olabilir:

public class EditOrderPagelModel
{
    public OrderModel Order{get;set;}
    public DateTime EarliestDeliveryDate{get;set;}
    public DateTime LatestAllowedDeliveryDate{get;set;}
}

Bu üçüncü grubun faydasının burada farklı olduğunu tamamen görüyorum ve başka bir şeyle birleştirmeyi planlamıyorum (yeniden adlandırabilirim).

Model grubundaki sınıflar şu anda uygulamanın API'sı tarafından da kullanılıyor, ki bu da iyi bir fikir olup olmadığı konusunda girdi duymakla ilgileniyorum.

Ayrıca burada bir dize olarak temsil edilen müşterinin, aslında sistemde bu şekilde temsil edildiği için değil, örneği basitleştirmek olduğunu belirtmeliyim. Gerçek sistem, müşterinin kendi özelliklerine sahip etki alanı modelinde farklı bir tür olduğunu gösterir.


1
"Projeyi, şirketten ayrılan başka bir geliştiriciden miras aldım" bu şekilde başlayan hikayelere adanmış bir site var .

Güncellemenizle ilgili olarak: bu yeterli fayda için çok fazla dolaylı gibi görünüyor.
Robert Harvey

@RobertHarvey Çok fazla dolaylılık olarak neyi kastediyorsunuz?
Robert Ricketts

1
OrderModel. OrderViewModel (muhtemelen EditOrderPageModel olarak adlandırdığınız şey) yeterli dolaylıdır; cevabımı aşağıda görebilirsiniz.
Robert Harvey

@RobertHarvey Bu aslında sormaya çalıştığım sorunun cevabı gibi görünüyor
Robert Ricketts

Yanıtlar:


16

Burada önemli bir şey mi eksik?

EVET

Bunlar aynı şey gibi görünse ve etki alanında aynı şeyi temsil etse de, aynı (OOP) nesneler değildir.

Bunlardan biri, Orderkodun veri depolama kısmı tarafından bilindiği gibidir. Diğeri OrderUI tarafından bilindiği gibidir. Bu sınıfların aynı özelliklere sahip olması hoş bir tesadüf olsa da, garanti edilmez .

Veya başka bir perspektiften bakmak için Tek Sorumluluk İlkesini göz önünde bulundurun. Buradaki temel motivasyon, "bir sınıfın değişmek için bir nedeni vardır". Özellikle ORM ve / veya UI çerçevesi gibi yaygın çerçevelerle uğraşırken, çerçevede yapılan değişiklikler genellikle varlıklarınızın değişmesine neden olacağından nesnelerinizin iyi yalıtılmış olması gerekir.

Varlıklarınızı her iki çerçeveye bağlayarak, onu daha da kötüleştiriyorsunuz.


7

Görünüm Modelinin amacı iki şekilde ayırmayı sağlamaktır: Görünümün gerektirdiği şekilde (modelden bağımsız olarak) veri sağlayarak ve (özellikle MVVM'de) Görünüm mantığının bir kısmını veya tamamını Görünümden geri iterek Görünüm Modeline.

Tamamen normalleştirilmiş bir modelde Müşteri, Modelde bir dize ile değil, bir kimlikle temsil edilir. Model, müşterinin adına ihtiyaç duyuyorsa, Siparişler tablosunda bulunan MüşteriNo'yu kullanarak Müşteriler tablosundan adı arar.

Öte yandan bir Görünüm Modeli, Namekimlikle değil müşterinin ilgisini çekebilir . Müşteri Modelde güncellenmedikçe kimliğe ihtiyaç yoktur.

Ek olarak, Görünüm Modeli farklı bir şekil alabilir (genellikle saf CRUD olmadığı sürece ). Bir Fatura Görüntüleme Modeli nesnesinin müşteri adı, adresleri ve satır öğeleri olabilir, ancak modelde müşteriler ve açıklamalar bulunur.

Başka bir deyişle, faturalar normalde görüntülendikleri şekilde saklanmaz.


3

Bazı açılardan haklısınız: İkisi de aynı domainobject'e atıfta bulunuyor order. Fakat siz yanıldınız, bu farklı amaçlardan kaynaklanan farklı bir temsilden ziyade gerçek bir çoğaltma değildir . Siparişinizi devam ettirmek istiyorsanız, örneğin her bir sütuna erişmek istersiniz. Ama bunu dışarıya sızmak istemiyorsunuz. Bütün Varlıkları telden geçirmenin yanı sıra gerçekten istediğiniz şey değildir. ordersBirkaç kb'nin yeterli olacağı müşteriye MB'lerin bir koleksiyonunun gönderildiği durumları biliyorum .

Uzun bir hikaye kısaltmak için - işte bunu yapmak istediğiniz ana nedenler:

1) Kapsülleme - Başvurunuzun gizlenmesi

2) Küçük Modeller hızlı seri hale getirilir ve iletilmesi kolaydır

3) Üst üste binmelerine rağmen farklı amaçlara hizmet ederler ve bu nedenle farklı nesneler olmalıdır.

4) Bazen farklı Sorgular için farklı Değer Nesneleri olması mantıklıdır . Nasıl C # bilmiyorum, ama Java sonuçları toplamak için bir POJO kullanmak mümkündür . Eğer tek bir ihtiyacım varsa Order -Entity orderkullanın , ama sadece veri miktarları ile dolu bazı sütunlara ihtiyacım varsa , daha küçük Nesneler kullanmak daha etkilidir.


Varlık çerçevesinin yapılandırılma şekli, varlıklar düz eski C # nesneleridir, bu nedenle bunları tel üzerinden göndermek gerçekten sorun değildir. Bazı durumlarda bir siparişin içeriğinin sadece bir kısmını gönderebilmenin faydasını görüyorum.
Robert Ricketts

Dediğim gibi bir ya da bir grup sorun değil. Ancak MBS verilerinin olduğu ve yükleme sürenizi yavaşlatan durumlar vardır. Mobil yükleme sürelerini düşünün
Thomas Junk

0

(Feragatname: Sadece bu şekilde kullanıldığını gördüm. Bunu yapmanın gerçek amacını yanlış anlamış olabilirim. Bu yanıtı şüphe ile ele alın.)

Arasındaki dönüşüm: İşte başka eksik bit Orderve OrderModel.

Orderİse sınıf, ORM bağlıdır OrderModelsenin Görüntüle Modelinin tasarımına bağlıdır.

Tipik olarak, iki yöntem "sihirli bir şekilde" (bazen DI, IoC, MVVM veya başka bir şey olarak adlandırılır) sağlanacaktır. Yani, bu iki dönüştürme yöntemini bir parçası olarak uygulamak OrderModelyerine, bu şeylerin karşılıklı dönüşümüne adanmış bir sınıfa ait olacaklar; bu sınıf bir şekilde çerçeveye kaydedilecektir, böylece çerçeve kolayca arayabilir.

public class OrderModel {
    ...
    public OrderModel(Order from) { ... }
    public Order ToOrder() { ... }
}

Bunu yapmanın nedeni, 'den' OrderModele ( Orderveya tersi) bir geçiş olduğunda , bazı verilerin ORM'den yüklenmesi veya ORM'ye kaydedilmesi gerektiğini bilmenizdir.


Eğer ikisini de saklıyorsam, kesinlikle dönüşümün daha otomatik olmasını sağlamak için onları kurmak istiyorum
Robert Ricketts

@RobertRicketts Gördüğüm şey şuna benziyor: IMvxValueConverter . Yine de amacını yanlış anlamış olabilirim.
rwong
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.