İntegral tanımlayıcıları numaralandırmalarla eşlemenin dezavantajları nelerdir?


16

Bunun gibi tanımlayıcılar için özel türler oluşturmayı düşünüyorum:

public enum CustomerId : int { /* intentionally empty */ }
public enum OrderId : int { }
public enum ProductId : int { }

Bunun için birincil motivasyonum, bir orderItemId öğesini orderItemDetailId bekleyen bir işleve yanlışlıkla geçirdiğiniz hata türlerini önlemektir.

Sıralamalar tipik bir .NET web uygulamasında kullanmak istediğim her şeyle sorunsuz çalışıyor gibi görünüyor:

  • MVC yönlendirme iyi çalışıyor
  • JSON serileştirmesi iyi çalışıyor
  • Aklıma gelen her ORM iyi çalışıyor

Şimdi merak ediyorum, "Bunu neden yapmamalıyım?" Aklıma gelen tek dezavantaj bunlar:

  • Diğer geliştiricileri karıştırabilir
  • Entegre olmayan tanımlayıcılarınız varsa sisteminizde tutarsızlık sağlar.
  • Gibi ekstra döküm gerektirebilir (CustomerId)42. Ancak bunun bir sorun olacağını düşünmüyorum, çünkü ORM ve MVC yönlendirmesi genellikle size doğrudan enum tipinin değerlerini verecek.

Benim sorum şu: Neyi kaçırıyorum? Bu muhtemelen kötü bir fikir, ama neden?



3
Buna "mikrotipleme" denir, Google'da
dolaşabilirsiniz

İki kısmi cevap yazdım ve sonra sildim çünkü bunu yanlış düşündüğümü fark ettim. "Bu muhtemelen kötü bir fikir, ama neden?"
user2023861

Yanıtlar:


7

Başlıca belirttiğiniz nedenlerle, her tanımlayıcı türü için tür oluşturmak harika bir fikirdir . Bunu enum olarak uygulayarak yapmazdım çünkü uygun bir yapı veya sınıf yapmak size daha fazla seçenek sunar:

  • İnt içine örtülü dönüşüm ekleyebilirsiniz. Bunu düşündüğünüzde, diğer yön, int -> CustomerId, tüketiciden açıkça onaylamayı gerektiren sorunlu olan budur.
  • Hangi tanımlayıcıların kabul edilebilir ve hangilerinin kabul edilemez olduğunu belirten iş kuralları ekleyebilirsiniz. Sadece int'in pozitif olup olmadığı zayıf bir kontrolle ilgili değildir: bazen, tüm olası kimliklerin listesi veritabanında tutulur, ancak yalnızca dağıtım sırasında değişir. Daha sonra, verilen kimliğin uygun sorgunun önbelleğe alınmış sonucuna karşı var olduğunu kolayca kontrol edebilirsiniz. Bu şekilde, geçersiz veri olduğunda uygulamanızın hızlı bir şekilde başarısız olacağını garanti edebilirsiniz .
  • Tanımlayıcıdaki yöntemler, pahalı DB varlığı denetimleri yapma veya ilgili varlık / etki alanı nesnesini edinme konusunda size yardımcı olabilir.

Bunu uygulama hakkında İşlevsel C #: İlkel saplantı makalesinde okuyabilirsiniz .


1
i neredeyse kesinlikle öyle bir sınıfta ama bir yapı içinde her int sarmak istemiyor derdim
jk.

İyi not, cevabı biraz güncelledim.
Lukáš Lánský

3

Akıllı bir hack'tir, ancak yine de bir hack, amaçlanan amaç olmayan bir şey için bir özelliği kötüye kullanır. Hack'lerin sürdürülebilirlik maliyeti vardır, bu nedenle başka dezavantajlar bulamazsınız , aynı sorunu çözmenin daha deyimsel yoluna kıyasla önemli faydalara sahip olması gerekir .

Deyimsel yol, tek bir alanla sarıcı tipi veya yapı oluşturmaktır. Bu size daha açık ve deyimsel bir şekilde aynı tip güvenliği sağlayacaktır. Teklifiniz kuşkusuz akıllı olsa da, ambalaj türlerini kullanmanın önemli bir avantajını görmüyorum.


1
Bir enum en büyük avantajı "sadece MVC, serileştirme, ORM, vb ile istediğiniz şekilde çalışır" geçmişte özel türleri (yapıları ve sınıfları) oluşturduk ve sizden daha fazla kod yazma sonunda bu çerçevelerin / kitaplıkların özel türlerinizle çalışmasını sağlamak için gerekir.
default.kramer

Serileştirme her iki şekilde de şeffaf bir şekilde çalışmalıdır, ancak örneğin. ORM'ler bir tür açık dönüşüm yapılandırmanız gerekir. Ancak bu, güçlü bir şekilde yazılmış bir dilin fiyatıdır.
JacquesB

2

POV'umdan, fikir iyi. İlişkisiz tanımlayıcı sınıflarına farklı türler verme, aksi takdirde türler aracılığıyla anlambilimi ifade etme ve derleyicinin kontrol etmesine izin verme niyeti iyi bir şeydir.

.NET performans açısından nasıl çalıştığını bilmiyorum, örneğin enum değerleri mutlaka kutulu. Bir veritabanı ile çalışan OTOH kodu zaten I / O-bağlı olması muhtemeldir ve kutulu tanımlayıcılar herhangi bir darboğaz olmayacaktır.

Mükemmel bir dünyada, tanımlayıcılar değişmez ve sadece eşitlikle karşılaştırılabilir; gerçek baytlar bir uygulama detayı olacaktır. İlişkisiz tanımlayıcıların uyumsuz türleri olabilir, bu nedenle yanlışlıkla başka birini kullanamazsınız. Çözümünüz pratik olarak faturaya uyuyor.


-1

Bunu yapamazsınız, numaralandırmalar önceden tanımlanmalıdır. Dolayısıyla, müşteri kimliklerinin olası değerlerinin tüm spektrumunu önceden tanımlamak istemiyorsanız, türünüz işe yaramaz olacaktır.

Eğer yayınlarsanız, yanlışlıkla B tipi kimliğe A tipi bir kimlik atamayı önleme birincil hedefinize meydan okuyorsunuz. Bu yüzden numaralandırmalar amacınıza yardımcı olmaz.

Bu, Int32'den (veya Guid'den) inerek müşteri kimliği, sipariş kimliği ve ürün kimliği için türlerinizi oluşturmanıza yardımcı olursa soruyu gündeme getirir. Bunun yanlış olmasının nedenlerini düşünebilirim.

Bir kimliğin amacı tanımlamadır. İntegral tipleri zaten bunun için mükemmeldir, onlardan inerek daha fazla tanımlamazlar. Hiçbir uzmanlık gerektirmez veya arzu edilmez, tanımlayıcılar için farklı türlere sahip olarak dünyanız daha iyi temsil edilmeyecektir. OO açısından bakıldığında kötü olur.

Önerinizle tip güvenliğinden daha fazlasını, değer güvenliğini istiyorsunuz ve bu da modelleme alanının ötesinde, yani operasyonel bir sorun.


1
Hayır, numaralandırmaların .NET'te önceden tanımlanması gerekmez. Ve mesele şu ki, döküm yapmak neredeyse hiç gerçekleşmez, örneğin public ActionResult GetCustomer(CustomerId custId)hiçbir dökümde gerekli değildir - MVC çerçevesi değeri sağlayacaktır.
default.kramer

2
Kabul etmiyorum. Benim için OO perspektifinden mükemmel mantıklı. Int32 hiçbir anlambilimine sahip değildir, tamamen "teknik" tiptedir. Ancak nesneleri tanımlama amacına hizmet eden ve Int32 olarak uygulanacak olan (ancak uzun ya da her neyse, gerçekten önemli değil) soyut Tanımlayıcı tipine ihtiyacım var. ProductId'ın somut örneğini tanımlayan Tanımlayıcı'dan gelen ProductId gibi somut uzmanlıklarımız var. ProductId'ye OrderItemId değerini atamak mantıklı değildir (bu açıkça bir hatadır), bu nedenle tür sisteminin bizi bundan koruyabilmesi harika.
qbd

1
C # enum kullanımı konusunda bu esnek olduğunu bilmiyordum. Enumların olası değerlerin sıralaması olduğu gerçeğine (?) Alışkın olan bir geliştirici olarak kesinlikle kafa karıştırıcı. Genellikle bir dizi adlandırılmış kimlik belirtirler. Yani şimdi bu tür aralık yok ve isim yok anlamında "istismar ediliyor", sadece tür kaldı. Ve görünüşe göre, tip de o kadar güvenli değil. Başka bir şey: örnek açıkça bir veritabanı uygulamasıdır ve bir noktada "enum" nuzun, tahmin ettiğiniz türünüzü her şeyden sonra güvenli bir şekilde kaybedeceğiniz ayrılmaz bir tür alanına eşlenir.
Martin Maat
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.