ঠিক আছে, আপনার শোনার মতো ডোমেনের একটি আইএস-এ সম্পর্ক রয়েছে বলে মনে হচ্ছে তবে আপনি মডেল করতে সাব টাইপ / উত্তরাধিকার ব্যবহার সম্পর্কে কিছুটা সতর্ক রয়েছেন — বিশেষত রানটাইম টাইপের প্রতিচ্ছবিটির কারণে। তবে আমি মনে করি যে আপনি ভুল জিনিস থেকে ভয় পেয়েছেন - সাবটাইপিং সত্যিকার অর্থেই বিপদগুলির সাথে আসে তবে আপনি রানটাইমে কোনও বিষয় অনুসন্ধান করছেন তা সমস্যা নয় the আপনি যা বলতে চাইছেন তা আপনি দেখতে পাবেন।
অবজেক্ট-ওরিয়েন্টেড প্রোগ্রামিং আইএস-এ সম্পর্কের ধারণার উপর প্রচুর ঝোঁক ফেলেছে, এটি যুক্তিযুক্তভাবে এটির উপর খুব বেশি ঝোঁক দিয়েছে, যার ফলে দুটি বিখ্যাত সমালোচনা ধারণার জন্ম দেয়:
তবে আমি মনে করি আইএস-এ সম্পর্কের দিকে নজর দেওয়ার আরও একটি কার্যকরী-প্রোগ্রামিং-ভিত্তিক উপায় রয়েছে যা সম্ভবত এই সমস্যাগুলির মধ্যে নেই। প্রথমত, আমরা আমাদের প্রোগ্রামে ঘোড়া এবং ইউনিকর্নদের মডেল করতে চাই, সুতরাং আমরা একটি Horseএবং একটি Unicornটাইপ করতে যাচ্ছি । এই ধরণের মানগুলি কী? ঠিক আছে, আমি এটি বলতে পারি:
- এই ধরণের মান হ'ল ঘোড়া এবং ইউনিকর্নের উপস্থাপনা বা বর্ণনা (যথাক্রমে);
- তারা হয় schematized , তারা খুব কঠোর নিয়ম অনুযায়ী নির্মাণ করছি উপস্থাপনা বা বর্ণনা-they're না মুক্ত-ফর্ম।
এটি সুস্পষ্ট মনে হতে পারে, তবে আমি মনে করি যে বৃত্ত-উপবৃত্ত সমস্যার মতো সমস্যাগুলিতে লোকেরা প্রবেশের অন্যতম উপায় হ'ল সেই বিষয়গুলি সাবধানতার সাথে বিবেচনা না করে by প্রতিটি চেনাশোনা একটি উপবৃত্তাকার, তবে এর অর্থ এই নয় যে একটি বৃত্তের প্রতিটি স্কিমাইটাইজড বিবরণ স্বয়ংক্রিয়ভাবে একটি পৃথক স্কিমা অনুযায়ী উপবৃত্তির একটি স্কিমাইটিস বিবরণ। অন্য কথায়, কেবল একটি বৃত্তটি উপবৃত্তের অর্থ এই নয় যে Circleএটি একটি Ellipse, তাই কথা বলা। তবে এর অর্থ এই:
- একটি মোট ফাংশন রয়েছে যা কোনও
Circle(স্কিমাইটেড সার্কেলের বর্ণনা) কে Ellipse(বর্ণনার বিভিন্ন ধরণের ) রূপান্তর করে যা একই বৃত্তকে বর্ণনা করে;
- একটি আংশিক ফাংশন রয়েছে যা একটি গ্রহণ করে
Ellipseএবং, যদি একটি বৃত্তের বর্ণনা দেয় তবে সংশ্লিষ্টটি ফিরিয়ে দেয় Circle।
সুতরাং, কার্যনির্বাহী প্রোগ্রামিংয়ের ক্ষেত্রে, আপনার Unicornধরণের মোটেও একটি উপ-টাইপ হওয়ার দরকার নেই Horse, আপনার কেবল এই জাতীয় ক্রিয়াকলাপ প্রয়োজন:
-- Convert any unicorn-description of into a horse-description that
-- describes the same unicorns.
toHorse :: Unicorn -> Horse
-- If the horse described by the given horse-description is a unicorn,
-- then return a unicorn-description of that unicorn, otherwise return
-- nothing.
toUnicorn :: Horse -> Maybe Unicorn
এবং এর toUnicornসঠিক বিপরীত হওয়া দরকার toHorse:
toUnicorn (toHorse x) = Just x
Maybeঅন্যান্য ভাষার ভাষাগুলি "অপশন" টাইপকে হ্যাস্কেলের ধরণ বলে। উদাহরণস্বরূপ, জাভা 8 Optional<Unicorn>টাইপ হয় হয় Unicornবা কিছুই নয়। নোট করুন যে আপনার দুটি বিকল্প- একটি ব্যতিক্রম ছুঁড়ে ফেলা বা "ডিফল্ট বা ম্যাজিক মান" ফিরিয়ে দেওয়া —অন্য বিকল্পগুলির সাথে খুব মিল।
সুতরাং মূলত আমি এখানে যা করেছি তা হ'ল সাব-টাইপ বা উত্তরাধিকার ব্যবহার না করে ধরণ এবং প্রকারের ক্ষেত্রে IS-A সম্পর্কটিকে পুনর্গঠন করা। আমি এ থেকে যা নেব তা হ'ল:
- আপনার মডেল একটি
Horseপ্রকারের প্রয়োজন;
Horseটাইপ চাহিদা unambiguously কিনা তা নির্ধারণ করতে কোনো মান একটি unicorn বর্ণনা যথেষ্ট তথ্য এনকোড করা;
Horseপ্রকারের কিছু ক্রিয়াকলাপগুলিতে সেই তথ্যটি প্রকাশ করা দরকার যাতে প্রকারের ক্লায়েন্টরা প্রদত্ত Horseএকটি ইউনিকর্ন কিনা তা পর্যবেক্ষণ করতে পারেন ;
Horseধরণের ক্লায়েন্টদের ইউনিকর্ন এবং ঘোড়ার মধ্যে বৈষম্যের জন্য রানটাইমের সময়গুলিতে এই উত্তরোত্তর অপারেশনগুলি ব্যবহার করতে হবে।
সুতরাং এটি মৌলিকভাবে " Horseএটি একটি ইউনিকর্ন কিনা " প্রত্যেককে জিজ্ঞাসা করুন । আপনি সেই মডেল সম্পর্কে সতর্ক, তবে আমি ভুলভাবে এটি মনে করি। আমি যদি আপনাকে একটি তালিকা দিয়ে থাকি Horseতবে ধরণের গ্যারান্টিযুক্ত হ'ল তালিকার আইটেমগুলি যে জিনিসগুলি বর্ণনা করে তা হ'ল ঘোড়া — সুতরাং অনিবার্যভাবে আপনি রানটাইমের সময় কিছু করার প্রয়োজন যা তাদের কোনটি ইউনিকর্ন নয় tell সুতরাং এটির কাছাকাছি কিছু নেই, আমি মনে করি — আপনার এমন অপারেশনগুলি প্রয়োগ করা দরকার যা এটি আপনার জন্য করবে।
অবজেক্ট-ওরিয়েন্টেড প্রোগ্রামিংয়ে এটি করার পরিচিত উপায়টি নিম্নলিখিত:
- একটি
Horseপ্রকার আছে;
- আছে
Unicornএকটি উপপ্রকার হিসাবে Horse;
- ক্লায়েন্ট-প্রবেশযোগ্য অপারেশন নির্ণয় একটি প্রদত্ত কিনা হিসেবে ব্যবহার করবেন রানটাইম টাইপ প্রতিফলন
Horseএকটি হল Unicorn।
এটির উপরে একটি বড় দুর্বলতা রয়েছে, যখন আপনি উপরে বর্ণিত "জিনিস বনাম বিবরণ" কোণ থেকে দেখেন:
- আপনার যদি এমন কোনও
Horseউদাহরণ রয়েছে যা ইউনিকর্নের বর্ণনা দেয় তবে Unicornউদাহরণ না হয়?
শুরুতে ফিরে যাওয়া, আমি মনে করি এটি হ'ল এই IS-A সম্পর্কের মডেলিংয়ের জন্য সাব টাইপিং এবং ডাউনকাস্টগুলি ব্যবহার করা সম্পর্কে সত্যই ভয়ঙ্কর অংশ - এটি আপনাকে রানটাইম চেক করতে হবে এমন নয়। টাইপোগ্রাফিকে কিছুটা অপব্যবহার করা, এটি জিজ্ঞাসা করা Horseযে এটি কোনও Unicornউদাহরণ নয় Horseকিনা এটি জিজ্ঞাসা করার জন্য এটি ইউনিকর্ন কিনা (এটি Horseঘোড়াটির একটি বিবরণ যা একটি ইউনিকর্ণও নয়) সমার্থক নয় কিনা । আপনার প্রোগ্রামটি কোড তৈরির কোডটি এনপ্যাপুলেট করার জন্য যথেষ্ট পরিমাণে না চলে যায় না যতক্ষণ না Horsesপ্রতি ক্লায়েন্ট যখন Horseকোনও ইউনিকর্ন বর্ণনা করে এমন কোনও নির্মাণের চেষ্টা করে , Unicornক্লাসটি তাত্ক্ষণিক হয়। আমার অভিজ্ঞতায় খুব কমই প্রোগ্রামাররা এগুলি সাবধানতার সাথে করে।
তাই আমি পদ্ধতির সঙ্গে যেতে চাই যেখানে কোনো স্পষ্ট, অ-হতাশ অপারেশন যে ধর্মান্তরিত নেই Horseগুলি Unicornগুলি। এটি হয় এই Horseধরণের একটি পদ্ধতি হতে পারে :
interface Horse {
// ...
Optional<Unicorn> toUnicorn();
}
... বা এটি কোনও বাহ্যিক বস্তু হতে পারে (আপনার "ঘোড়ার উপর পৃথক বস্তু যা আপনাকে জানায় যে ঘোড়াটি যদি এককৃমি বা না হয়"):
class HorseToUnicornCoercion {
Optional<Unicorn> convert(Horse horse) {
// ...
}
}
এর মধ্যে পছন্দটি আপনার প্রোগ্রামটি কীভাবে সংগঠিত হয়েছে - এটি উভয় ক্ষেত্রেই Horse -> Maybe Unicornউপরে থেকে আমার অপারেশনের সমতুল্য রয়েছে , আপনি কেবল এটি বিভিন্ন উপায়ে প্যাকেজিং করছেন (এটি স্বীকার করবে যে টাইপটির কী কী অপারেশন Horseদরকার তা স্বীকার করতে পারে) এর ক্লায়েন্টদের কাছে প্রকাশ করা)।