यदि आप इससे बच सकते हैं तो या तो उपयोग न करें। एक विकल्प प्रकार, एक टुपल, या एक समर्पित योग प्रकार लौटाते हुए फ़ैक्टरी फ़ंक्शन का उपयोग करें। दूसरे शब्दों में, गारंटीकृत न होने वाले डिफ़ॉल्ट मान से भिन्न प्रकार के साथ संभावित-डिफ़ॉल्ट मान का प्रतिनिधित्व करें।
पहले, आइए desiderata को सूचीबद्ध करें फिर सोचें कि हम इसे कुछ भाषाओं में कैसे व्यक्त कर सकते हैं (C ++, OCaml, Python)
- संकलन समय पर किसी डिफ़ॉल्ट वस्तु का अवांछित उपयोग करना।
- यह स्पष्ट करें कि कोड को पढ़ते समय किसी दिए गए मूल्य में संभावित रूप से चूक हुई है या नहीं।
- हमारे समझदार डिफ़ॉल्ट मान चुनें, यदि लागू हो, एक बार प्रति प्रकार । निश्चित रूप से हर कॉल साइट पर संभावित रूप से अलग डिफ़ॉल्ट नहीं चुना जाता है ।
grep
संभावित गलतियों के शिकार के लिए स्थैतिक विश्लेषण टूल या मानव के लिए इसे आसान बनाएं ।
- कुछ अनुप्रयोगों के लिए , प्रोग्राम को सामान्य रूप से जारी रखना चाहिए अगर अप्रत्याशित रूप से डिफ़ॉल्ट मान दिया जाए। अन्य अनुप्रयोगों के लिए , यदि डिफ़ॉल्ट रूप से, सूचनात्मक तरीके से आदर्श रूप में दिया गया है, तो कार्यक्रम को तुरंत रोक देना चाहिए।
मुझे लगता है कि अशक्त वस्तु पैटर्न और अशक्त बिंदुओं के बीच तनाव (5) से आता है। यदि हम त्रुटियों का शीघ्र पता लगा सकते हैं, हालाँकि, (5) मूट हो जाता है।
आइए इस भाषा पर विचार करें:
सी ++
मेरी राय में, एक C ++ वर्ग आमतौर पर डिफ़ॉल्ट-निर्माण योग्य होना चाहिए क्योंकि यह पुस्तकालयों के साथ बातचीत को आसान बनाता है और कंटेनरों में वर्ग का उपयोग करना आसान बनाता है। यह वंशानुक्रम को भी सरल करता है क्योंकि आपको यह सोचने की आवश्यकता नहीं है कि किस सुपरक्लास कंस्ट्रक्टर को कॉल करना है।
हालाँकि, इसका मतलब यह है कि आप निश्चित रूप से नहीं जान सकते हैं कि प्रकार MyClass
का मान "डिफ़ॉल्ट स्थिति" में है या नहीं। bool nonempty
रनटाइम के दौरान डिफ़ॉल्ट-नेस को एक समान क्षेत्र में रखने के अलावा , आप जो सबसे अच्छा कर सकते हैं वह इस तरह से नए उदाहरणों का उत्पादन MyClass
करता है जो उपयोगकर्ता को इसे जांचने के लिए मजबूर करता है ।
मैं एक फ़ैक्टरी फ़ंक्शन का उपयोग करने की सलाह दूंगा जो यदि संभव हो तो एक std::optional<MyClass>
, std::pair<bool, MyClass>
या एक आर-मान संदर्भ देता std::unique_ptr<MyClass>
है।
यदि आप चाहते हैं कि आपका फ़ैक्टरी फ़ंक्शन किसी प्रकार के "प्लेसहोल्डर" राज्य को वापस लौटाए, जो डिफ़ॉल्ट-निर्माण से अलग हो MyClass
, तो ए का उपयोग करें std::pair
और यह सुनिश्चित करें कि आपका फ़ंक्शन ऐसा करता है।
यदि फैक्ट्री फ़ंक्शन का एक अद्वितीय नाम है, तो यह नाम के लिए आसान है grep
और ढलान के लिए देखो। हालाँकि, grep
उन मामलों के लिए कठिन है जहाँ प्रोग्रामर को फ़ैक्टरी फ़ंक्शन का उपयोग करना चाहिए था, लेकिन नहीं किया ।
OCaml
यदि आप OCaml जैसी भाषा का उपयोग कर रहे हैं, तो आप केवल एक option
प्रकार (OCaml मानक पुस्तकालय में) या एक either
प्रकार का उपयोग कर सकते हैं (मानक पुस्तकालय में नहीं, बल्कि अपना स्वयं का रोल करने में आसान)। या एक defaultable
प्रकार (मैं शब्द बना रहा हूं 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
है क्योंकि उपयोगकर्ता चाहिए पैटर्न मैच को निकालने के लिए के रूप में ऊपर दिखाए गए एक जोड़ी की तुलना में बेहतर है 'a
और बस जोड़ी के पहले तत्व नजरअंदाज नहीं कर सकते।
defaultable
ऊपर दिखाए गए प्रकार के बराबर का उपयोग C ++ में एक std::variant
ही प्रकार के दो उदाहरणों के साथ किया जा सकता है , लेकिन std::variant
यदि दोनों प्रकार समान हैं तो API के भाग अनुपयोगी हैं। यह भी एक अजीब उपयोग है std::variant
क्योंकि इसके प्रकार के निर्माता अनाम हैं।
अजगर
आप पायथन के लिए वैसे भी किसी भी संकलन-समय की जाँच नहीं करते हैं। लेकिन, गतिशील रूप से टाइप किया जा रहा है, आम तौर पर ऐसी परिस्थितियां नहीं होती हैं जहां आपको कंपाइलर को गिराने के लिए किसी प्रकार के प्लेसहोल्डर उदाहरण की आवश्यकता होती है।
मैं सिर्फ एक अपवाद फेंकने की सलाह दूंगा जब आप एक डिफ़ॉल्ट उदाहरण बनाने के लिए मजबूर होंगे।
यदि यह स्वीकार्य नहीं है, तो मैं आपके कारखाने के कार्य DefaultedMyClass
से उस विरासत को बनाने MyClass
और वापस करने की सिफारिश करूंगा । यदि आपको आवश्यकता हो तो डिफ़ॉल्ट रूप से "स्टबिंग आउट" कार्यक्षमता के संदर्भ में आपको लचीलापन मिलता है।