मुझे लगता है कि अशक्त क्यों नहीं है की संक्षिप्त सारांश यह है कि निरर्थक राज्यों का प्रतिनिधित्व नहीं किया जाना चाहिए ।
मान लीजिए मैं एक दरवाजा बना रहा हूं। यह तीन राज्यों में से एक में हो सकता है: खुला, बंद लेकिन खुला, और बंद और बंद। अब मैं इसकी तर्ज पर मॉडलिंग कर सकता था
class Door
private bool isShut
private bool isLocked
और यह स्पष्ट है कि मेरे तीन राज्यों को इन दो बूलियन चर में कैसे मैप किया जाए। लेकिन यह एक चौथा, अवांछित राज्य उपलब्ध है isShut==false && isLocked==true
:। क्योंकि जिन प्रकारों को मैंने अपने प्रतिनिधित्व के रूप में चुना है, वे इस स्थिति को स्वीकार करते हैं, मुझे यह सुनिश्चित करने के लिए मानसिक रूप से प्रयास करना होगा कि वर्ग कभी भी इस स्थिति में न आए (शायद स्पष्ट रूप से एक अपरिवर्तनीय कोडिंग द्वारा)। इसके विपरीत, अगर मैं बीजीय डेटा प्रकारों या चेक किए गए गणनाओं के साथ एक भाषा का उपयोग कर रहा था जो मुझे परिभाषित करने देता है
type DoorState =
| Open | ShutAndUnlocked | ShutAndLocked
तब मैं परिभाषित कर सकता था
class Door
private DoorState state
और कोई चिंता नहीं है। टाइप सिस्टम यह सुनिश्चित करेगा कि इसमें class Door
होने के उदाहरण के लिए केवल तीन संभावित राज्य हैं । यह वह प्रकार है जो सिस्टम में अच्छे हैं - स्पष्ट रूप से संकलन-समय पर त्रुटियों के एक पूरे वर्ग को सत्तारूढ़ करना।
इसके साथ समस्या null
यह है कि प्रत्येक संदर्भ प्रकार को अपने स्थान में यह अतिरिक्त स्थिति मिलती है जो आमतौर पर अवांछित है। एक string
चर वर्णों का कोई भी अनुक्रम हो सकता है, या यह यह पागल अतिरिक्त null
मूल्य हो सकता है जो मेरी समस्या डोमेन में मैप नहीं करता है। एक Triangle
ऑब्जेक्ट में तीन Point
s होते हैं, जो स्वयं के पास होते हैं X
और Y
मान होते हैं, लेकिन दुर्भाग्य से Point
s या Triangle
स्वयं ही यह पागल शून्य मान हो सकता है जो कि मेरे द्वारा काम कर रहे ग्राफिंग डोमेन के लिए अर्थहीन है। आदि।
जब आप एक संभवतः-गैर-मौजूद मूल्य को मॉडल करने का इरादा रखते हैं, तो आपको इसे स्पष्ट रूप से चुनना चाहिए। अगर मैं लोगों को मॉडल करने का इरादा रखता हूं, तो यह है कि हर Person
एक के पास कुछ FirstName
है LastName
, लेकिन केवल कुछ लोग हैं MiddleName
, तो मैं कुछ कहना चाहूंगा
class Person
private string FirstName
private Option<string> MiddleName
private string LastName
जहां string
यहां गैर-व्यर्थ प्रकार माना जाता है। तब NullReferenceException
किसी के नाम की लंबाई की गणना करने की कोशिश करने पर कोई अप्रत्याशित आक्रमण नहीं होता है और न ही कोई अप्रत्याशित एस। प्रकार प्रणाली यह सुनिश्चित करती है कि किसी भी कोड के MiddleName
होने की संभावना के लिए खातों से निपटनाNone
, जबकि किसी भी कोड से निपटने के लिए FirstName
सुरक्षित रूप से मान सकते हैं कि वहाँ एक मूल्य है।
उदाहरण के लिए, उपरोक्त प्रकार का उपयोग करके, हम इस मूर्खतापूर्ण कार्य को लेखक कर सकते हैं:
let TotalNumCharsInPersonsName(p:Person) =
let middleLen = match p.MiddleName with
| None -> 0
| Some(s) -> s.Length
p.FirstName.Length + middleLen + p.LastName.Length
कोई चिंता नहीं है। इसके विपरीत, स्ट्रिंग जैसे प्रकारों के लिए अशक्त संदर्भों वाली भाषा में, फिर ग्रहण करना
class Person
private string FirstName
private string MiddleName
private string LastName
आप सामान की तरह संलेखन समाप्त करते हैं
let TotalNumCharsInPersonsName(p:Person) =
p.FirstName.Length + p.MiddleName.Length + p.LastName.Length
यदि आने वाली व्यक्ति वस्तु में सब कुछ गैर-अशक्त होने या न होने का आवेश नहीं होता है, तो यह सामने आता है
let TotalNumCharsInPersonsName(p:Person) =
(if p.FirstName=null then 0 else p.FirstName.Length)
+ (if p.MiddleName=null then 0 else p.MiddleName.Length)
+ (if p.LastName=null then 0 else p.LastName.Length)
या हो सकता है
let TotalNumCharsInPersonsName(p:Person) =
p.FirstName.Length
+ (if p.MiddleName=null then 0 else p.MiddleName.Length)
+ p.LastName.Length
मानाकि p
पहले / अंतिम हैं, लेकिन मध्य अशक्त हो सकता है, या शायद आप ऐसे चेक करते हैं जो विभिन्न प्रकार के अपवादों को फेंकते हैं, या आप क्या जानते हैं। इन सभी पागल कार्यान्वयन विकल्पों और चीजों को फसल के बारे में सोचने के लिए क्योंकि यह बेवकूफ प्रतिनिधित्व योग्य-मूल्य है जो आपको नहीं चाहिए या आवश्यकता नहीं है।
नल आमतौर पर अनावश्यक जटिलता जोड़ता है। जटिलता सभी सॉफ़्टवेयर का दुश्मन है, और आपको जब भी उचित हो जटिलता को कम करने का प्रयास करना चाहिए।
(अच्छी तरह से ध्यान दें कि इन सरल उदाहरणों के लिए और भी अधिक जटिलता है। भले ही एक FirstName
नहीं हो सकता है null
, एक string
प्रतिनिधित्व कर सकता है ""
(खाली स्ट्रिंग), जो शायद एक व्यक्ति का नाम भी नहीं है जिसे हम मॉडल करना चाहते हैं। जैसे, गैर के साथ भी। अशक्त तार, यह अभी भी मामला हो सकता है कि हम "अर्थहीन मूल्यों का प्रतिनिधित्व" कर रहे हैं। फिर, आप रनटाइम पर इनवियर्स और सशर्त कोड के माध्यम से या तो टाइप सिस्टम (उदाहरण के लिए एक NonEmptyString
प्रकार) का उपयोग करके यह लड़ाई चुन सकते हैं । उत्तरार्द्ध शायद बीमार-सलाह है ("अच्छे" प्रकार आम ऑपरेशन के सेट पर अक्सर "बंद" होते हैं, और जैसे NonEmptyString
बंद नहीं होता है.SubString(0,0)
), लेकिन यह डिज़ाइन स्पेस में अधिक पॉइंट प्रदर्शित करता है। दिन के अंत में, किसी भी प्रकार की प्रणाली में, कुछ जटिलता होती है जो छुटकारा पाने में बहुत अच्छी होगी, और अन्य जटिलता जो छुटकारा पाने के लिए आंतरिक रूप से कठिन है। इस विषय की कुंजी यह है कि लगभग हरप्रकार प्रणाली, "डिफ़ॉल्ट रूप से अशक्त संदर्भों" से "गैर-अशक्त संदर्भों को डिफ़ॉल्ट रूप से" परिवर्तन लगभग हमेशा एक सरल परिवर्तन है जो टाइप प्रणाली को जटिलता से जूझने और कुछ प्रकार की त्रुटियों और निरर्थक राज्यों से बाहर निकालने में काफी हद तक बेहतर बनाता है। इसलिए यह बहुत पागल है कि कई भाषाएं इस त्रुटि को बार-बार दोहराती रहती हैं।)