Bir mülkten istisna atmak kötü bir form mudur?


15

Ben her zaman özellikleri (yani, onların set / get işlemleri) hızlı / anında ve hatasız olması zihniyet olmuştur. Bir mülk edinme veya ayarlama konusunda hiçbir zaman denemek / yakalamak zorunda kalmamalısınız.

Ancak bazı nesnelerin özelliklerine rol tabanlı güvenlik uygulamak için bazı yollar arıyorum. Örneğin bir Employee.Salary mülkü. Diğerlerinin denediği bazı çözümler (özellikle burada AOP örneği ), erişimci doğru izinlere sahip değilse bir istisna atmayı içerir - ancak bu, sahip olduğum kişisel bir kurala aykırıdır uzun zamandır.

Bu yüzden soruyorum: yanlış mıyım? Bir şeyler değişti mi? Mülklerin istisnalar atması gerektiği kabul edildi mi?


1
Bu StackOverflow'daki aynı soruyu daha fazla dikkat ve böylece iyi cevaplar aldık.
Roman Starkov

Yanıtlar:


14

bir özelliğin değerini ayarladığınızda, geçersiz bir değere bir istisna atmak iyi olur

bir mülkün değerini elde etmek (neredeyse) asla istisna atmamalıdır

rol tabanlı erişim için farklı / numara arabirimleri veya cepheler kullanın; insanların sahip olamayacakları şeyleri görmelerine izin verme!


5

Çoğunlukla kötü bir form olduğunu düşünüyorum, ancak Microsoft bile bazen istisnalar kullanmanızı önerir. İyi bir örnek, Stream.Length soyut özelliğidir . Yönergeler ilerledikçe, alıcılar üzerinde yan etkilerden kaçınmak ve seterler üzerindeki yan etkileri sınırlamakla daha fazla ilgilenirim.


4

Bir mülk ayarlayıcı veya alıcıdan istisnalar atma ihtiyacını hissediyorsanız, tasarımda bir kusur olduğunu kesinlikle iddia ederim.

Özellik, yalnızca değer olan bir şeyi temsil eden bir soyutlamadır . Ve bunun bir istisna oluşturabileceğinden korkmadan bir değer ayarlayabilmelisiniz. *

Özelliğin ayarlanması bir yan etkiye yol açarsa, bunun gerçekten bir yöntem olarak uygulanması gerekir. Ve eğer herhangi bir yan etki üretmezse, bir istisna atılmamalıdır.

Farklı bir cevapta daha önce bahsedilen bir örnek mülktür Stream.Position. Bu yan etkiler yaratır ve istisnalar atabilir. Ancak bu özellik ayarlayıcı, temelde Stream.Seekbunun yerine arayabileceğiniz bir sarıcıdır.

Şahsen, pozisyonun yazılabilir bir özellik olmaması gerektiğine inanıyorum.

Bir özellik ayarlayıcısından istisna atmak için cazip olabileceğiniz başka bir örnek, verilerin doğrulanmasıdır:

public class User {
    public string Email {
        get { return _email; }
        set { 
            if (!IsValidEmail(value)) throw InvalidEmailException(value);
            _email = value;
        }
    }

Ancak bu soruna daha iyi bir çözüm var. Geçerli bir e-posta adresini temsil eden bir tür girin:

public class Email {
    public Email(string value) {
        if (!IsValidEmail(value)) throw new InvalidEmailException(value);
        ...
    }
    ...
}

public class User {
    public Email Email { get; set; }
}

EmailSınıf geçerli bir e-posta adresi olmayan bir değer tutamayacak sağlar ve sınıflar mağaza e-postalara gerek bunları onaylama görevden ki.

Bu aynı zamanda daha yüksek bir bütünlüğe (iyi yazılım tasarımının bir göstergesi) yol açar - bir e-posta adresinin ne olduğu ve nasıl doğrulandığına dair bilgi Email, yalnızca bu endişeye sahip olan sınıfta bulunur.

* ObjectDisposedException şu anda düşünebildiğim tek geçerli istisnadır (pun amaçlı değil).


2

Sorunuzun .NET'e özgü olduğunu biliyorum , ancak C # Java ile bazı geçmişi paylaştığından, ilginizi çekebileceğini düşündüm. Ben değil bir şey Java yapılır, bunun nedeni C # yapılması gerektiğini ima hiçbir şekilde. İkisinin çok farklı olduğunu biliyorum, özellikle de C # özellikleri için çok gelişmiş dil seviyesi desteğine sahip. Sadece bir bağlam ve perspektif veriyorum.

Gönderen JavaBeans şartname :

Kısıtlı özellikler Bazen bir özellik değişikliği meydana geldiğinde başka bir fasulye de değişikliği doğrulamak ve uygun değilse reddetmek isteyebilir. Bu tür bir denetime tabi tutulan özelliklere kısıtlanmış özellikler olarak atıfta bulunuyoruz. Java Beans'te, PropertyVetoException özelliğini desteklemek için kısıtlanmış özellik ayarlayıcı yöntemleri gerekir. Bu belgeler, güncelleme girişiminde bulunan kısıtlanmış mülkün kullanıcılarına veto edilebilir. Yani basit bir kısıtlanmış özellik şöyle görünebilir:

PropertyType getFoo();
void setFoo(PropertyType value) throws PropertyVetoException;

Bütün bunları bir tane tuzla al, lütfen. JavaBeans belirtimi eskidir ve C # Özellikleri (IMO) Java'nın sahip olduğu "adlandırma kuralı" tabanlı özellikler üzerinde büyük bir gelişmedir. Sadece küçük bir bağlam vermeye çalışıyorum, hepsi bu!


İyi bir nokta, ama bir ayarlayıcı yöntemi ve ac # özellik ayarlayıcı arasındaki ayrım benim için farklı bir durum olacak kadar önemlidir. Benzer şekilde, Java'nın işaretli istisnaları, arama kodunu bir istisnanın atılabileceğinin farkında olmaya zorlar, bu nedenle bunun kimseyi şaşırtması için daha az şans vardır.
Steven Evers

2

Bir özelliğin noktası Tekdüzen Erişim İlkesi'dir , yani depolama veya hesaplama tarafından uygulanan aynı değere bir değerin erişilebilir olması gerekir. Mülkünüz, programcının denetiminin ötesinde bir hata koşulunu temsil eden bir istisna atıyorsa, yakalanması ve ele alınması gereken tür, istemcinizi değerin hesaplama yoluyla elde edildiğini bilmeye zorlarsınız.

Öte yandan, API'nin programcıya yanlış bir şekilde kullanılmasından ziyade programcıya yanlış kullanımını bildirmek amacıyla ekler veya iddia benzeri istisnalar kullanmayla ilgili herhangi bir sorun görmüyorum. Bu durumlarda, API kullanıcısının bakış açısından doğru cevap istisnayı ele almaz (dolayısıyla değerin hesaplama veya depolama yoluyla elde edilip edilmediğine dair dolaylı bir şekilde ilgilenmek). Bu, kodunu düzeltmek için nesnenin geçersiz bir duruma gelmemesini veya kodunuzu düzeltmenizi sağlayarak iddianın tetiklenmemesini sağlar.


“Müşterinizi, değerin hesaplama yoluyla elde edildiğini bilmeye nasıl zorladığınızı” görmüyorum. Kesinlikle depolamaya erişim de bir istisna oluşturabilir. Aslında, ikisi arasındaki farkı nasıl tanımlarsınız?
Timwi

Yaptığım ayrımın sadece bir alandan (depolama) bir değer almanın ve onunla zararsız bir şey yapmanın, örneğin uygun tipte bir değişkene (yani döküm olmadan) bir istisna atamayacağına inanıyorum. Bu durumda bir istisna ancak daha sonra değerle ilgili bir şey yaptıysanız ortaya çıkabilir. Bir özellik alıcısında bir istisna atılıyorsa, o zaman sadece değeri alma ve bir değişkene yerleştirme eylemi bir istisnaya neden olabilir.
Dr.Wily's Apprentice

1

AFAIK, bu rehberlik öncelikle özelliklerin tasarım zamanında kullanılabileceği düşüncesinden kaynaklanmaktadır . (Örneğin, bir TextBox üzerindeki Text özelliği) Bir tasarımcının erişmeye çalıştığında özellik bir istisna atarsa, VS iyi bir gün geçirmeyecektir. Sadece tasarımcıyı kullanmaya çalışırken bir sürü hata alırsınız ve UI tasarımcıları için oluşturmazlar. Hata ayıklama zamanı için de geçerlidir, ancak bir istisna senaryosunda göreceğiniz şey sadece "xxx İstisna" dır ve VS IIRC'yi hızlandırmaz.

POCO'lar için, gerçekten herhangi bir zarar vermez, ama yine de kendim yapmaktan utanıyorum. İnsanların mülklere daha sık erişmek isteyeceğini düşünüyorum, bu yüzden normalde düşük maliyetli olmalılar. Özellikler yöntemlerin işini yapmamalı, sadece bazı bilgileri almalı / ayarlamalı ve genel bir kural olarak yapılmalıdır.


0

Her ne kadar çok şey bağlama bağlı olsa da genellikle her türlü kırılabilir mantığı (istisnalar dahil) özelliklere koymaktan kaçınırım. Bir örnek olarak, sizin (veya kullandığınız bir kütüphanenin) yapabileceği birçok şey vardır, bu özellik tasarım üzerinde tahmin etmediğiniz hatalarla sonuçlanan özellikleri yinelemek için yansımayı kullanır.

Ben genellikle, kesinlikle, kesinlikle, sonuçları hakkında çok fazla endişelenmeden bir şeyi engellemek istediğiniz zamanlar olabileceğini söylüyorum. Güvenlik sanırım orada klasik bir durum olurdu.

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.