it-swarm.dev

Bir uygulamadaki özel alanları desteklemek için tasarım desenleri nelerdir?

Ticari bir uygulama geliştiriyoruz. Müşterilerimiz özel alan desteği istiyorlar. Örneğin, Müşteri formuna bir alan eklemek istiyorlar.

Alan değerlerini ve alanlarla ilgili meta verileri depolamak için bilinen tasarım desenleri nelerdir?

Şimdilik bu seçenekleri görüyorum:

Seçenek 1 : Müşteri tablomuza varchar türündeki Alan1, Alan2, Alan3, Alan4 sütunlarını ekleyin.

Seçenek 2 : Müşteri tablosuna tek bir XML türü sütunu ekleyin ve özel alanların değerlerini xml olarak saklayın.

Seçenek 3 : varchar türünde bir sütun içeren bir CustomerCustomFieldValue tablosu ekleyin ve değerleri bu sütunda saklayın. Bu tabloda ayrıca bir Müşteri Kimliği, bir CustomFieldID bulunur.

CustomerID,  CustomFieldID, Value
10001,       1001,          '02/12/2009 8:00 AM'
10001,       1002,          '18.26'
10002,       1001,          '01/12/2009 8:00 AM'
10002,       1002,          '50.26'

CustomFieldID, bu sütunlarla CustomField adlı başka bir tablodaki bir kimlik olacaktır: CustomFieldID, FieldName, FieldValueTypeID.

Seçenek 4 : Her olası değer türünde bir sütunu olan bir CustomerCustomFieldValue tablosu ekleyin ve değerleri sağ sütunda saklayın. # 3'e benzer, ancak alan değerleri kesinlikle tür bir sütun kullanılarak depolanır.

CustomerID,  CustomFieldID, DateValue,           StringValue,       NumericValue                 
10001,       1001,          02/12/2009 8:00 AM,  null,              null
10001,       1002,          null,                null,              18.26
10002,       1001,          01/12/2009 8:00 AM,  null,              null
10002,       1002,          null,                null,              50.26

Seçenek 5 : Seçenek 3 ve 4, tek bir konsepte (Müşteri) özgü bir tablo kullanır. Müşterilerimiz de özel formları başka şekillerde istiyorlar. Bunun yerine, sistem genelinde bir özel saha depolama sistemine sahip miyiz? Yani, CustomerCustomFieldValue, ÇalışanCustomFieldValue, InvoiceCustomFieldValue gibi birden fazla tabloya sahip olmak yerine, CustomFieldValue adlı tek bir tabloya sahip olur muyduk? Benim için daha zarif görünse de, bu bir performans darboğazına neden olmaz mı?

Bu yaklaşımlardan herhangi birini kullandınız mı? Başarılı mıydın? Hangi yaklaşımı seçerdiniz? Göz önünde bulundurmam gereken başka bir yaklaşım biliyor musunuz?

Ayrıca, müşterilerim özel alanın diğer tablolardaki verilere başvurabilmesini istiyor. Örneğin, bir müşteri Müşteriye "Favori Ödeme Yöntemi" alanını eklemek isteyebilir. Ödeme yöntemleri, sistemin başka bir yerinde tanımlanmıştır. Bu resimde "yabancı anahtarlar" konusunu getiriyor. Özel alan tablolarında depolanan değerlerin geçerli değerler olmasını sağlamak için kısıtlamalar oluşturmaya çalışmalı mıyım?

Teşekkürler

======================

07-27-2009 EDIT:

Cevaplarınız için teşekkür ederim. Yaklaşımlar listesi artık oldukça kapsamlı görünüyor. Seçenek 2'yi seçtim (tek bir XML sütunu). Şimdilik uygulaması en kolay olanıydı. Gereksinimlerim daha karmaşık hale geleceğinden ve desteklenecek özel alanların sayısı arttıkça, muhtemelen daha güçlü bir şekilde tanımlanmış bir yaklaşıma refrakter olmam gerekecek.

69
Sylvain

Seçenek 3, 4 veya 5'in uygun olması muhtemel olan aşağıdaki posterlere katılıyorum. Bununla birlikte, önerilen uygulamalarınızın her birinin yararları ve maliyetleri vardır. Özel gereksinimlerinize göre bir tane seçmenizi öneririm. Örneğin:

  1. Seçenek 1 artıları: Uygulaması hızlı. Özel alanlarda DB işlemlerine izin verir (arama, sıralama.)
    Seçenek 1 eksileri: Özel alanlar geneldir, bu nedenle kesinlikle yazılan alanlar yoktur. Veritabanı tablosu hiç kullanılmayacak birçok yabancı alanla birlikte boyutsuzdur. İzin verilen özel alanların sayısı tahmin edilmelidir.
  2. Seçenek 2 artıları: Uygulaması hızlı. Esnek, isteğe bağlı sayı ve özel alan türlerine izin verir.
    Seçenek 2 eksileri: Özel alanlarda DB işlemi yapılamaz. Yapmanız gereken tek şey, daha sonra özel alanları görüntülemek veya daha sonra yalnızca Müşteri bazında verilerin küçük değişikliklerini yapmaktır.
  3. Seçenek 3 artıları: Hem esnek hem de verimli. DB işlemleri gerçekleştirilebilir, ancak boşa alan alanı azaltmak için veriler biraz normalleştirilir. Bilinmeyen (google) tür veya kaynak bilgilerini belirtmek için kullanılabilecek ek bir sütun eklediğiniz önerisine katılıyorum. Seçenek 3 eksileri: Sorgularınızın geliştirme süresinde ve karmaşıklığında biraz artış var, ancak gerçekten Burada çok fazla eksiler değil.
  4. Seçenek 4, Seçenek 3 ile aynıdır, ancak yazdığınız veriler DB düzeyinde çalıştırılabilir. Seçenek 3'teki bağlantı tablosuna tür bilgilerinin eklenmesi, uygulama düzeyimizde daha fazla işlem yapmanıza olanak sağlar, ancak DB örneğin karşılaştırma yapamaz veya sıralayamaz. 3 ile 4 arasındaki seçim bu gereksinime bağlıdır.
  5. Seçenek 5, 3 veya 4 ile aynıdır, ancak çözümü birçok farklı tabloya uygulamak için daha fazla esnekliğe sahiptir. Bu durumda maliyet, bu tablonun büyüklüğünün daha da artacağı olacaktır. Özel alanlarınıza ulaşmak için çok sayıda pahalı birleştirme işlemi gerçekleştiriyorsanız, bu çözüm iyi ölçeklenemeyebilir. 

Not; Aşağıda belirtildiği gibi "tasarım deseni" terimi genellikle nesne yönelimli programlamayı ifade eder. Bir veritabanı tasarımı sorununa çözüm arıyorsunuz, bu da tasarım desenleriyle ilgili tavsiyelerin geçerli olmayacağı anlamına gelir.

14
Eric Nguyen

Başvuru koduyla ilgili olarak emin değilim. Özel alanların veritabanındaki a EAV modelinden - büyük ölçüde faydalandığını biliyorum.

Aşağıdaki yorumlara göre, bu modelde yapabileceğiniz en önemli hata, içine yabancı anahtarlar koymak. Bu modele asla FriendID veya TypeID gibi bir şey koymayın. Bu modeli tipik ilişkisel model ile birlikte kullanın ve yabancı anahtar alanları olması gerektiği gibi tablo sütunlarında tutun. 

İkinci önemli hata, bu modelde her elemanla birlikte raporlanması gereken verileri yerleştirmektir. Örneğin, bu modele Kullanıcı adı gibi bir şey koymak, bir kullanıcıya erişmek istediğinizde ve kullanıcı adınızı bilmeniz gerektiğinde en iyi şekilde bir katılmaya karar verdiğiniz veya n'nin aradığınız kullanıcı sayısı olduğu 2n sorgularında . Her Kullanıcı elemanı için genellikle Username özelliğine ihtiyaç duyacağınızı düşündüğünüzde, bunun da sütun sütunlarında kalması gerektiği açıktır.

Ancak, bu modeli yalnızca özel kullanıcı alanlarıyla kullanıyorsanız, sorun olmaz. Bir kullanıcının ilişkisel verilere girdiği ve EAV modelinin aramalar için çok fazla zararlı olmadığı pek çok durumu hayal edemiyorum.

Son olarak, bu konudaki verilere katılmaya çalışın ve güzel bir kayıt ortamı elde edin. Orijinal kaydı alın ve ardından varlık için kayıt kümesini alın. Kendinizi masalara katılmaya hevesli bulursanız, muhtemelen yukarıda belirtilen ikinci hatayı yaptınız.

10
Spencer Ruport

Nesne yönelimli bir dil geliştiriyorsanız, adaptif nesne modellerinden burada bahsediyoruz. Bunları oo dillerinde nasıl uygulayabileceğinize dair çok az sayıda makale var, ancak veri deposu tarafının nasıl tasarlanacağı hakkında pek fazla bilgi yok.

Çalıştığım şirkette, AOM verilerini depolamak için ilişkisel bir veritabanı kullanarak sorunu çözdük. Alandaki tüm farklı "varlıkları" insanlar, ağ cihazları, şirketler vb. Gibi sunmak için merkezi varlık tablosuna sahibiz ... Asıl "form alanlarını" yazılan veri tablolarına kaydederiz, yani bir tablo var. dizeler, tarihler için biri vb. Tüm veri tablolarının varlık tablosunu gösteren yabancı bir anahtarı vardır. Ayrıca yazı tipini sunmak için tablolara ihtiyacımız var, yani belirli bir varlığın ne tür niteliklere (form alanları) sahip olabileceği ve bu bilgilerin veri tablolarındaki verileri yorumlamak için kullanılması.

Çözümümüzün artıları, varlıklar, çok değerler ve benzerleri arasındaki referanslar da dahil olmak üzere kod değişikliği olmadan modellenebilecek olmasıdır. Ayrıca alanlara işletme kuralları ve onaylamalar eklemek mümkündür ve bunlar her şekilde yeniden kullanılabilir. Eksileri, programlama modelinin anlaşılması çok kolay olmadığı ve performansın sorgulanmasının daha tipik bir DB tasarımından daha kötü olacağı yönündedir. İlişkisel veritabanından başka bir çözüm, AOM için daha iyi ve daha kolay olabilirdi.

Çalışan bir veri deposuyla iyi bir AOM oluşturmak çok iş ve çok yetenekli geliştiricilere sahip değilseniz bunu tavsiye etmem. Belki bir gün bu tür gereksinimler için bir işletim sistemi çözümü olacaktır.

Özel alanlar daha önce SO'da tartışılmıştır:

4
Kaitsu

Seçenek 4 veya 5 benim seçimim olur. Verileriniz önemliyse, seçenek bilgilerinizi 3. Seçenek ile atmaya gitmeyeceğim. (Kendinizin tam kontrolünü kendiniz uygulayabilirsiniz, ancak bu oldukça büyük bir iş ve veritabanı motoru zaten sizin için bunu yapıyor.)

Bazı düşünceler:

  • CustomFieldsname __ 'in DataTypesütununda olduğundan emin olun.
    • CustomFields.DataType tarafından belirtilen sütunun boş olmadığından emin olmak için CustomFieldValuesüzerinde UDF tabanlı bir kontrol kısıtlaması kullanın.
    • Ayrıca tam olarak boş olmayan bir değere sahip olduğunuzdan emin olmak için standart bir kontrol kısıtlaması isteyeceksiniz.
  • Yabancı anahtarlarla ilgili olarak, bunları ayrı bir DataTypename __. Olarak modelleyeceğim.
    • Her potansiyel çapraz tablo referansı kendi sütununu gerektirir. Bu iyi çünkü referans bütünlüğünü koruyor.
    • Yine de bu ilişkileri uygulama kodunda desteklemeniz gerekir, bu nedenle veritabanında kodlanmış olmaları aslında işlevselliği sınırlamaz.
    • Bu, bir tane kullanıyorsanız, ORM'nizle de iyi bir şekilde çakışacaktır.
  • Seçenek 5 için, ilişkileri modellemek için aracı tabloları kullanın.
    • Hala bir CustomerCustomFieldValueolurdu, ancak bunun yerine sadece CustomerIDve CustomFieldValueIDsütunlarına sahip olacaksınız.
  • Her adımda kısıtlamalarınız hakkında uzun ve sıkı düşünün. Bu aldatıcı şeyler ve bir yanlış adım çizginin tamamen bozulmasına neden olabilir.

Bunu şu anda geliştirilmekte olan bir uygulamada kullanıyorum. Henüz bir sorun olmadı, ancak EAV tasarımları hala gün ışığımdan korkuyor. Sadece dikkatli ol.

Bir kenara, XML de iyi bir seçim olabilir. Doğrudan deneyimden bu konuda pek bir şey bilmiyorum, ancak veri tasarımına başlarken düşündüğüm seçeneklerden biriydi ve oldukça umut verici görünüyordu.

3
WCWedin

Seçenek 3 gibi bir şey gitmek yoludur ve ben bu yöntemi daha önce kullandım. Ek özellikler ve bunlara karşılık gelen değerleri tanımlamak için tek bir tablo oluşturun. Bu, Müşteri ile CustomerCustomField tablosu arasındaki (1) 1-N'lik bir ilişki olacaktır. Özel mülklerle ilişkileri tanımlamaya ilişkin ikinci sorunuz, düşünülmesi gereken bir şey olacaktır. Akla gelen ilk şey, özellik değerinin bağlı olduğu tabloyu içeren bir DataSource alanı eklemek. Yani aslen CustomerCustomField'iniz şöyle görünür:

  1. Müşteri Kimliği
  2. özellik
  3. Değer
  4. ValueDataSource (null)

Bu, ya belirli bir veri yapısına bağlanmanıza ya da sınırsız değerleri belirlemenize izin vermelidir. Bu modeli daha da normalleştirebilirsiniz, ancak bunun gibi bir şey işe yarayabilir ve kodda işlemek için yeterince kolay olmalıdır. 

3
Sergey

Şu anda aynı problemi olan bir proje üzerinde çalışıyorum ve 3. seçeneği kullanmayı seçtim, ancak FieldType = "list" olması durumunda bir FieldType alanı ve ListSource alanı ekledim. ListSource alanı bir sorgu, bir sql görünümü, bir işlev adı veya liste için bir seçenek listesi ile sonuçlanan bir şey olabilir. Benim durumumda böyle alanları depolamaya çalışmakla ilgili en büyük sorun, bu alan listesinin değişebilmesi ve kullanıcıların daha sonra verileri düzenlemelerine izin verilmesidir. Öyleyse, eğer alan listesi değiştiyse ve düzenlemeye gittiyse ne yapmalı. Bu senaryoya benim çözümüm, yalnızca liste değişmediyse düzenlemeye izin vermek ve varsa salt okunur verileri görüntülemekti.

0
jbair

eğer bu 'ekstra' alanlar tesadüfi ise ve üzerlerinde arama yapmak istemiyorsa, genellikle seçenek 2'ye giderim (fakat JSON'u XML'den daha iyi). Özel alanlarda arama yapılacaksa, seçenek 3'ün yapılması zor değildir ve genellikle SQL optimize edici bunun dışında makul bir performans elde eder.

0
Javier