Çalışma zamanında sınıfa alan ekleme - tasarım deseni


15

Müşterinizin CMS'deki mağazalarında ürüne yeni mülk (örn. Renk) ekleme olanağına sahip olmak istediğini düşünün.

Alan olarak özelliklere sahip olmak yerine:

class Car extends Product {
   protected String type;
   protected int seats;
}

Muhtemelen şöyle bir şey yapardınız:

class Product {
   protected String productName;
   protected Map<String, Property> properties;
}

class Property {
   protected String name;
   protected String value;
}

Yani, mevcut olanın üzerine kendi tip sistemi oluşturmak. Bana bunun etki alanına özgü bir dil oluşturma olarak görülebileceği gibi geliyor, ya da değil mi?

Bu yaklaşım bilinen bir tasarım modeli midir? Sorunu farklı şekilde çözer misiniz? Çalışma zamanında bir alan ekleyebileceğim diller olduğunu biliyorum, ama veritabanı ne olacak? Sütunları eklemek / değiştirmek veya yukarıda gösterildiği gibi bir şey kullanmak ister misiniz?

Zaman ayırdığınız için teşekkür ederim :).



Hangi dili kullandığınızdan emin değilsiniz, ancak C # ise, temelde sözlükte bir KVP'yi ürünlerde yaptığınız gibi depolayan ve bunları doğrudan eklemenize gerek kalmadan özellikleri yapıştırmanıza izin veren dinamik bir tür kullanabilirsiniz. koleksiyon olarak. Yine de güçlü bir yazmaya sahip olmayacaksınız. Bir tasarım deseni istediğini biliyorum ama bunları kullanmak için karmaşık bir şeye ihtiyacın olacağını düşünmüyorum. msdn.microsoft.com/en-us/magazine/gg598922.aspx
Tony

Tony: Burada Java kullanıyorum, ama yalancı coude düşünün :). C # bu dinamik nesneyi veritabanına devam etmeme izin verir mi? Şüpheliyim, çünkü veritabanının verilerin yapısını önceden bilmesi gerekiyor.
Filip

Orada Devlet Desing Desen bir nesne yapar a-la Gang-of-Four, görünür onun değiştirmeye türü veya sınıfı çalışma zamanında. Diğer alternatifler ise Gözlemci Tasarım Deseni veya Proxy Tasarım Deseni
Nikos M.

1
Neden sadece harita veri türünü kullanmıyorsunuz? DB'de, performans istemiyorsanız {id} + {id, anahtar, değer} olarak temsil edilebilir.
Shadows In Rain

Yanıtlar:


4

Tebrikler! Programlama dili / türü sistem dünyasında yeni dolaştınız, ayrıldığınız yerden dünyanın diğer tarafına geldiniz. Dinamik dil / prototip tabanlı nesne diyarının sınırına geldiniz!

Birçok dinamik dil (ör. JavaScript, PHP, Python) birisinin çalışma zamanında nesne özelliklerini genişletmesine veya değiştirmesine izin verir.

Bunun uç şekli, Self veya JavaScript gibi prototip tabanlı bir dildir . Açıkçası, dersleri yok. Kalıtımla sınıf tabanlı, nesne yönelimli programlama gibi görünen şeyler yapabilirsiniz, ancak kurallar Java ve C # gibi daha keskin tanımlanmış, sınıf tabanlı dillere kıyasla büyük ölçüde rahatlar.

PHP ve Python gibi diller orta yerde yaşıyor. Düzenli, deyimsel sınıf tabanlı sistemleri var. Ancak, nesne öznitelikleri, JavaScript'te bulamadığınız bazı kısıtlamalarla ("yerleşik türler hariç" gibi) olsa da, çalışma zamanında eklenebilir, değiştirilebilir veya silinebilir.

Bu dinamizmin büyük ödünleşimi performanstır. Dilin ne kadar güçlü veya zayıf yazıldığını veya makine koduna göre ne kadar iyi derlenebileceğini unutun. Dinamik nesneler basit yapılar yerine esnek haritalar / sözlükler olarak temsil edilmelidir. Bu, her nesne erişimine ek yük getirir. Bazı programlar bu yükü azaltmak için büyük çaba sarf etmektedir (örneğin, Python'daki hayalet kwarg ataması ve yuva tabanlı sınıflarla), ancak ekstra yük genellikle kurs ve kabul fiyatı için eşittir.

Tasarımınıza geri dönersek, sınıflarınızın bir alt kümesine dinamik özelliklere sahip olma yeteneğini aşılayabilirsiniz. A Productdeğişken özniteliklere sahip olabilir; muhtemelen bir Invoiceya da bir Orderolur ve yapamadı. Gitmek kötü bir yol değil. Sıkı, disiplinli bir dil ve yazım sisteminde kalırken, ihtiyacınız olan yerde değişiklik yapabilme esnekliği sağlar. Aşağı tarafta, bu esnek özellikleri yönetmekten siz sorumlusunuz ve muhtemelen bunu daha yerel özelliklerden biraz farklı görünen mekanizmalar aracılığıyla yapmanız gerekecektir. p.prop('tensile_strength')ziyade p.tensile_strength, örneğin, ve p.set_prop('tensile_strength', 104.4)yerinep.tensile_strength = 104.4. Ancak standart olmayan özellik türleri için tam olarak bu tür alıcı ayarlayıcı erişimini kullanan Pascal, Ada, C, Java ve hatta dinamik dillerde birçok programla çalıştım ve geliştirdim; yaklaşım açıkça uygulanabilir.

Bununla birlikte, statik tipler ve çok çeşitli bir dünya arasındaki bu gerilim son derece yaygındır. Veritabanı şeması tasarlanırken, özellikle ilişkisel ve ilişkisel veri depoları için benzer bir sorun görülür. Bazen, tüm hayal edilen varyasyonların birleşimini içermek veya tanımlamak için yeterli esneklik içeren "süper-satırlar" oluşturarak ve ardından bu alanlara gelen verileri doldurarak halledilir. WordPress wp_poststablo , örneğin, gibi alanlar vardır comment_count, ping_status, post_parentve post_date_gmtsadece bazı durumlarda ilginç olduğunu ve pratikte sıklıkla boş gitmek. Başka bir yaklaşım, tıpkı sizin gibi çok yedek, normalleştirilmiş bir tablodur wp_options.Propertysınıf. Daha açık bir yönetim gerektirse de, içindeki öğeler nadiren boştur. Nesne yönelimli ve belge veritabanları (örneğin, MongoDB) genellikle seçenekleri değiştirmekle uğraşmak için daha kolay bir zamana sahiptir, çünkü özellikleri istedikleri gibi oluşturabilir ve ayarlayabilirler.


0

Soruyu seviyorum, iki sentim:

İki yaklaşımınız kökten farklıdır:

  • Birincisi OO ans güçlü yazılmıştır - ancak genişletilemez
  • İkincisi zayıf yazılmıştır (dize her şeyi kapsar)

C ++ 'da, çoğu her ikisinin bir karışımını elde etmek için bir std :: boost :: variant haritası kullanır .

Disgression: C # gibi bazı dillerin türlerin dinamik olarak oluşturulmasına izin verdiğini unutmayın. Bu, üyeleri dinamik olarak ekleme genel sorunu için iyi bir çözüm olabilir. Ancak, derlemeden sonra "değiştirme / ekleme" türleri tür sistemini bozar ve "değiştirilmiş" türlerinizi neredeyse işe yaramaz hale getirir (örneğin, var olduklarını bile bilmediğiniz için bu tür ek özelliklere nasıl erişirsiniz? her nesnenin sistematik bir yansıması olun ... saf dinamik bir dil ile bitiyor _ 'dinamik' .NET anahtar sözcüğüne başvurabilirsiniz)


Çalışma zamanında türler oluşturmak ilginç ama benim için çok egzotik (Java'da programlıyorum). Böyle bir çözüm işe yaramaz, eğer nesneyi veritabanında saklamak istersem, her zaman güçlü bir şekilde yazıldığına inanıyorum. Önerdiğim zayıf tip çözüm kolayca veritabanında saklanabilir.
Filip

0

Çalışma zamanında bir tür oluşturmak, sadece bir soyutlama katmanı oluşturmaktan çok daha karmaşıktır. Dekupl sistemleri için bir soyutlama yaratmak çok yaygındır.

Uygulamamdan bir örnek göstereyim. Moskova borsası , trader API'sı ile Plaza2 adlı ticaret çekirdeğine sahiptir. Yatırımcılar finansal verilerle çalışmak için programlarını yazarlar. Sorun, bu verilerin çok büyük, karmaşık ve değişikliklere çok açık olmasıdır. Yeni bir finansal ürün piyasaya sürüldükten veya temizleme rolleri değiştikten sonra değişebilir. Gelecekteki değişikliklerin niteliği tahmin edilemez. Kelimenin tam anlamıyla, her gün değişebilir ve kötü programcılar kodu düzenlemeli ve yeni bir sürüm yayınlamalı ve kızgın yatırımcılar sistemlerini revize etmelidir.

Açık bir karar, soyutlamanın arkasındaki tüm finansal cehennemi gizlemektir. İyi bilinen SQL tabloları soyutlama kullandılar. Çekirdeklerinin en büyük kısmı, herhangi bir geçerli şema ile çalışabilir, trader'ın yazılımı ile aynı şemayı dinamik olarak ayrıştırabilir ve sistemiyle uyumlu olup olmadığını öğrenebilir.

Örneğinize geri dönersek, bazı mantığın önünde soyut bir dil oluşturmak normaldir. "Mülk", "tablo", "mesaj" veya hatta insan dili olabilir, ancak bu yaklaşımın dezavantajlarına dikkat edin:

  • Ayrıştırma ve doğrulama için daha fazla kod (ve ders dışı daha fazla zaman). Derleyicinin statik yazarak sizin için yaptığı her şey çalışma zamanında yapmanız gerekir.
  • Mesajlar, tablolar veya diğer temel öğeler hakkında daha fazla dokümantasyon. Tüm karmaşıklık koddan bir tür şemaya veya standarda gider. Yukarıda belirtilen finansal cehennem şemasına bir örnek: http://ftp.moex.com/pub/FORTS/Plaza2/p2gate_en.pdf (düzinelerce tablo sayfası)

0

Bu yaklaşım bilinen bir tasarım modeli midir?

XML ve HTML'de bunlar bir düğümün / öğenin öznitelikleri olacaktır. Ayrıca genişletilmiş özellikler, ad / değer çiftleri ve parametreler olarak da adlandırdım.

Sorunu farklı şekilde çözer misiniz?

Sorunu bu şekilde çözerdim, evet.

Çalışma zamanında bir alan ekleyebileceğim diller olduğunu biliyorum, ama veritabanı ne olacak?

Bir veritabanı bazı açılardan Java'ya benzer. Peso-sql'de:

TABLE products
(
    product_name VARCHAR(50),
    product_id INTEGER AUTOINCREMENT
)

TABLE attributes
(
    product_id INTEGER,
    name VARCHAR(50),
    value VARCHAR(2000)
)

Bu Java'ya karşılık gelir

class Product {
   protected String productName;
   protected Map<String, String> properties;
}

Harita adı anahtar olarak sakladığından, bir Property sınıfına gerek olmadığını unutmayın.

Sütunları eklemek / değiştirmek veya yukarıda gösterildiği gibi bir şey kullanmak ister misiniz?

Ekleme / değiştirme sütun şey denedim ve bir kabus oldu. Bu yapılabilir, ancak işler senkronizasyondan çıkmaya devam etti ve hiçbir zaman iyi çalışmam. Yukarıda özetlediğim tablo yapısı çok daha başarılı oldu. Eğer yıllardan tarafından aramalar ve düzeni yapmak gerekirse, bir her bir veri türü için (tablo nitelikleri kullanmayı düşünün date_attributes, currency_attributesvs.) veya ürün tablosunda eski güzel veritabanı sütun olarak bazı özelliklerini ekleyerek. Raporların veritabanı sütunlarına ve alt tablolara yazılması genellikle daha kolaydır.

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.