আমি মনে করি কেন নাল অনাকাঙ্ক্ষিত তার সংক্ষিপ্তসারটি হ'ল অর্থহীন রাজ্যগুলি উপস্থাপনযোগ্য হওয়া উচিত নয় ।
মনে করুন আমি একটি দরজা মডেলিং করছি। এটি তিনটি অবস্থার মধ্যে একটিতে থাকতে পারে: খোলা, শাট তবে আনলক করা, এবং বন্ধ এবং লক করা। এখন আমি এর লাইন বরাবর এটি মডেল করতে পারে
class Door
private bool isShut
private bool isLocked
এবং এটি পরিষ্কার যে কীভাবে আমার তিনটি রাজ্যের এই দুটি বুলিয়ান ভেরিয়েবলগুলিতে মানচিত্র করা যায়। কিন্তু এই পাতার একটি চতুর্থ, অবাঞ্ছিত রাষ্ট্র উপলব্ধ: isShut==false && isLocked==true
। যেহেতু আমি আমার প্রতিনিধিত্বকারী হিসাবে যে ধরণের নির্বাচন করেছি সেগুলি এই রাষ্ট্রটিকে স্বীকার করে, আমার অবশ্যই মানসিক প্রয়াস ব্যয় করতে হবে যাতে শ্রেণি যাতে কখনও এই রাজ্যে না আসে (সম্ভবত স্পষ্টতই কোনও আক্রমণকারীকে কোড করে)। বিপরীতে, আমি যদি বীজগণিত ডেটা ধরণের বা চেক করা গণনাগুলির সাহায্যে কোনও ভাষা ব্যবহার করতাম যা আমাকে সংজ্ঞা দিতে দেয়
type DoorState =
| Open | ShutAndUnlocked | ShutAndLocked
তাহলে আমি সংজ্ঞা দিতে পারি
class Door
private DoorState state
আর কোনও উদ্বেগ নেই। টাইপ সিস্টেমটি নিশ্চিত করবে যে কেবলমাত্র তিনটি সম্ভাব্য রাজ্য রয়েছে class Door
যাবার জন্য রয়েছে This এটি টাইপ সিস্টেমগুলিতে ভাল - সংকলন-সময়ে সম্পূর্ণ শ্রেণীর ত্রুটিগুলি স্পষ্টভাবে রায় দেয়।
সমস্যাটি null
হ'ল প্রতিটি রেফারেন্স ধরণটি তার স্পেসে এই অতিরিক্ত অবস্থাটি পায় যা সাধারণত অনাকাঙ্ক্ষিত। একটি string
চলক অক্ষরগুলির যে কোনও ক্রম হতে পারে, বা এটি এই ক্রেজি অতিরিক্ত null
মূল্য হতে পারে যা আমার সমস্যা ডোমেনে ম্যাপ করে না। একটি Triangle
অবজেক্টের তিনটি রয়েছে Point
, যার নিজস্ব X
এবং Y
মান রয়েছে তবে দুর্ভাগ্যক্রমে Point
s বা Triangle
নিজেই এই পাগল নাল মান হতে পারে যা আমি যে গ্রাফিকিং ডোমেনে কাজ করছি তার অর্থহীন E ইত্যাদি t
আপনি যখন সম্ভাব্য-অ-অস্তিত্ব মানকে মডেল করার পরিকল্পনা করেন, তখন আপনাকে এটিকে স্পষ্টভাবে বেছে নেওয়া উচিত। আমি যদি লোকদের মডেল করার ইচ্ছা করি তবে প্রত্যেকটির 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
প্রকারের জন্য) ব্যবহার করে এটির বিরুদ্ধে লড়াই করতে বেছে নিতে পারেন The পরবর্তীকালে সম্ভবত অসুস্থ পরামর্শ দেওয়া হয় ("ভাল" প্রকারগুলি প্রচলিত ক্রিয়াকলাপগুলির একটি সেটের উপরে প্রায়শই "বন্ধ" থাকে এবং উদাহরণস্বরূপ NonEmptyString
বন্ধ হয় না.SubString(0,0)
), তবে এটি নকশার জায়গাতে আরও পয়েন্ট প্রদর্শন করে। দিনের শেষে, যে কোনও প্রকারের সিস্টেমে কিছু জটিলতা রয়েছে এটি থেকে মুক্তি পাওয়া খুব ভাল হবে এবং অন্যান্য জটিলতা যা এ থেকে মুক্তি পাওয়ার পক্ষে কেবল আরও শক্ত। এই বিষয়টির মূল কথাটি হ'ল প্রায় প্রতিটি ধরণের সিস্টেমে "ডিফল্ট অনুসারে নাল রেফারেন্স" থেকে "ডিফল্ট অনুসারে নন-রেফারেন্স রেফারেন্স" এ পরিবর্তন প্রায় সর্বদা একটি সহজ পরিবর্তন যা টাইপ সিস্টেমকে জটিলতার সাথে লড়াই করার ক্ষেত্রে একটি দুর্দান্ত চুক্তি তৈরি করে এবং নির্দিষ্ট ধরণের ত্রুটি এবং অর্থহীন অবস্থার রায় দেওয়া। সুতরাং এটি বেশ উন্মাদ যে এতগুলি ভাষা বার বার এই ত্রুটিটি পুনরাবৃত্তি করে)