Sakıncalıysanız, ikisini de kullanmayın. Bir seçenek türü, bir değer veya özel bir toplam türü döndüren bir fabrika işlevi kullanın. Başka bir deyişle, varsayılan olarak garanti edilmemiş bir değerden farklı bir türde potansiyel olarak varsayılan değeri temsil eder.
Öncelikle desiderata'yı listeleyelim, sonra bunu birkaç dilde nasıl ifade edebileceğimizi düşünelim (C ++, OCaml, Python)
- Derleme zamanında varsayılan bir nesnenin istenmeyen kullanımını yakalamak.
- Verilen bir değerin kodu okurken potansiyel olarak varsayılan olup olmadığını açıkça belirtin.
- mümkünse her tür için bir kez mantıklı varsayılan değerimizi seçin . Kesinlikle her arama sitesinde potansiyel olarak farklı bir varsayılan seçmeyin .
- Statik analiz araçlarının veya bir insanın
grep
olası hatalar için avlanmasını kolaylaştırır .
- Bazı uygulamalarda , beklenmedik şekilde varsayılan bir değer verilirse program normal şekilde devam etmelidir. Diğer uygulamalarda , ideal olarak bilgilendirici bir şekilde, varsayılan bir değer verilirse program derhal durmalıdır.
Boş Nesne Deseni ile boş işaretçiler arasındaki gerilimin (5) geldiğini düşünüyorum. Hataları yeterince erken tespit edersek, (5) tartışılmaz hale gelir.
Bu dili dile göre düşünelim:
C ++
Bence, bir C ++ sınıfı genellikle kütüphanelerle etkileşimi kolaylaştırdığı ve sınıfı kaplarda kullanmayı kolaylaştıracağı için varsayılan olarak yapılandırılabilir olmalıdır. Aynı zamanda kalıtımı kolaylaştırır, çünkü hangi süper sınıf yapıcısını arayacağınızı düşünmeniz gerekmez.
Ancak bu, bir tür değerin MyClass
"varsayılan durumda" olup olmadığından emin olamayacağınız anlamına gelir . Çalışma bool nonempty
süresinde yüzey varsayılanlığı değerine benzer bir alana koymanın yanı sıra , yapabileceğiniz en iyi şey , kullanıcıyı kontrol etmeye zorlayacak şekilde yeni örnekler üretmektirMyClass
.
Bir döndüren bir fabrika işlevini kullanarak öneriyoruz std::optional<MyClass>
, std::pair<bool, MyClass>
bir veya bir r değeri referans std::unique_ptr<MyClass>
mümkünse.
Fabrika işlevinizin, varsayılan olarak oluşturulmuş olandan farklı bir tür "yer tutucu" durumu döndürmesini istiyorsanız, a MyClass
kullanın std::pair
ve işlevinizin bunu yaptığını belgelemeye dikkat edin.
Eğer fabrika fonksiyonu benzersiz bir isme sahipse grep
, isim için kolaylık ve isim bulması kolaydır . Ancak, grep
programcının fabrika işlevini kullandığı, ancak kullanmadığı durumlar için zordur .
OCaml
OCaml gibi bir dil kullanıyorsanız, o zaman bir option
tür (OCaml standart kütüphanesinde) veya bir either
tür kullanabilirsiniz (standart kütüphanede değil, kendi dilinizi kolayca kullanabilirsiniz). Veya bir defaultable
tür (Terim uyduruyorum defaultable
)
type 'a option =
| None
| Some of 'a
type ('a, 'b) either =
| Left of 'a
| Right of 'b
type 'a defaultable =
| Default of 'a
| Real of 'a
defaultable
Yukarıda gösterilen A , bir çiftten daha iyidir, çünkü kullanıcının, deseni çıkarmak için eşleşmesi gerekir 'a
ve çiftin ilk öğesini görmezden gelemez.
defaultable
Yukarıda gösterilen tipe eşdeğer std::variant
, aynı tipte iki örneği olan bir c kullanarak C ++ 'da kullanılabilir , ancak std::variant
her iki tip de aynıysa API'nin parçaları kullanılamaz. Ayrıca std::variant
, tür kurucularının isimlendirilmemesi nedeniyle garip bir kullanımdır .
piton
Python için herhangi bir derleme zamanı denetimi alamazsınız. Ancak, dinamik olarak yazıldığından, derleyiciyi yerleştirmek için bir tür yer tutucu örneğine ihtiyaç duyduğunuz durumlar genellikle yoktur.
Varsayılan bir örnek oluşturmaya zorlandığınızda sadece bir istisna atmanızı tavsiye ederim.
Bu kabul edilebilir değilse, DefaultedMyClass
miras alan bir şeyi yaratmanızı MyClass
ve fabrika işlevinizden geri almanızı öneririm . İhtiyaç duyduğunuzda, varsayılan durumlarda "inatçılık" işlevselliği açısından size esneklik kazandırır.