ধরণের আইডোমেটিক বা দুর্বল নকশার সাথে প্যাটার্ন-মিল কী?


18

দেখে মনে হচ্ছে এফ # কোড প্রায়শই ধরণের সাথে মেলে। অবশ্যই

match opt with 
| Some val -> Something(val) 
| None -> Different()

সাধারণ বলে মনে হচ্ছে

তবে ওওপি দৃষ্টিকোণ থেকে, এটি রানটাইম টাইপ চেকের উপর ভিত্তি করে নিয়ন্ত্রণ-প্রবাহের মতো একটি ভয়ঙ্কর দেখতে পাওয়া যায়, যা সাধারণত নষ্ট হয়ে যায়। এটি বানানটি বলতে, OOP এ আপনি সম্ভবত অতিরিক্ত লোডিং ব্যবহার করতে পছন্দ করবেন:

type T = 
    abstract member Route : unit -> unit

type Foo() = 
    interface T with
        member this.Route() = printfn "Go left"

type Bar() = 
    interface T with
        member this.Route() = printfn "Go right"

এটি অবশ্যই আরও কোড। ওও, আমার OOP-y মনে মনে কাঠামোগত সুবিধাগুলি আছে:

  • একটি নতুন ফর্ম এক্সটেনশন Tসহজ;
  • রুট-বেছে নেওয়া নিয়ন্ত্রণ প্রবাহের সদৃশ সন্ধানের জন্য আমাকে চিন্তার দরকার নেই; এবং
  • রুট পছন্দ এই অর্থে অপরিবর্তনীয় যে একবার আমার Fooহাতে চলে গেলে , Bar.Route()এর বাস্তবায়ন সম্পর্কে আমার কখনই চিন্তা করার দরকার নেই

আমি যে ধরণেরগুলি দেখছি না তার বিপরীতে প্যাটার্ন-মিলের সুবিধা রয়েছে কি? এটিকে কী অহংকার হিসাবে বিবেচনা করা হয় বা এটি এমন একটি দক্ষতা যা সাধারণত ব্যবহৃত হয় না?


4
কোনও ওওপি দৃষ্টিকোণ থেকে একটি কার্যকরী ভাষা দেখার জন্য এটি কতটা অর্থবোধ করে? যাইহোক, প্যাটার্ন মিলের আসল শক্তি নেস্টেড নিদর্শনগুলির সাথে আসে। কেবলমাত্র বহিরাগত নির্মাণকারীকে পরীক্ষা করা সম্ভব, তবে কোনও উপায়ে পুরো গল্পটি নয়।
এংগো

এটি - But from an OOP perspective, that looks an awful lot like control-flow based on a runtime type check, which would typically be frowned on.- খুব কৌতূহলোদ্দীপক শোনায়। কখনও কখনও, আপনি আপনার ওপেনকে আপনার শ্রেণিবিন্যাস থেকে পৃথক করতে চান: সম্ভবত 1) আপনি ক্রমবিন্যাসের জন্য একটি বিকল্প যোগ করতে পারবেন না খ / সি আপনি যে স্তরক্রমের মালিক নন; 2) আপনি যে ক্লাসগুলি পছন্দ করতে চান তা আপনার শ্রেণিবিন্যাসের সাথে মেলে না; 3) আপনি আপনার শ্রেণিবিন্যাসে অপশন যুক্ত করতে পারেন, তবে খ / সি করতে চান না আপনি বেশিরভাগ ক্লায়েন্ট ব্যবহার করেন না এমন গুচ্ছ গুচ্ছ দিয়ে আপনার শ্রেণিবিন্যাসের API এলোমেলো করতে চান না।

4
কেবল স্পষ্ট করার জন্য, Someএবং Noneপ্রকার নয়। তারা উভয় নির্মাতা যার প্রকার forall a. a -> option aএবং forall a. option a(দুঃখিত, টাইপ টীকাগুলির জন্য সিনট্যাক্স এফ # তে কী তা নিশ্চিত নন)।

উত্তর:


21

আপনি ঠিক বলেছেন যে ওওপি শ্রেণীর শ্রেণিবিন্যাসগুলি এফ # তে বৈষম্যমূলক ইউনিয়নের সাথে খুব ঘনিষ্ঠভাবে জড়িত এবং সেই প্যাটার্নের মিলটি গতিশীল ধরণের পরীক্ষার সাথে খুব ঘনিষ্ঠভাবে সম্পর্কিত। প্রকৃতপক্ষে, এফ # আসলে বৈষম্যমূলক ইউনিয়নগুলি কে নেট থেকে সংকলন করে!

এক্সটেনসিবিলিটি সম্পর্কে, সমস্যার দুটি দিক রয়েছে:

  • ওও আপনাকে নতুন সাব-ক্লাস যুক্ত করতে দেয়, তবে নতুন (ভার্চুয়াল) ফাংশন যুক্ত করা শক্ত করে তোলে
  • এফপি আপনাকে নতুন ফাংশন যুক্ত করতে দেয়, তবে নতুন ইউনিয়নের ক্ষেত্রে যুক্ত করা শক্ত করে তোলে

এটি বলেছিল, প্যাটার্ন ম্যাচিংয়ের ক্ষেত্রে আপনি কেস মিস করার সময় এফ # আপনাকে সতর্কতা দেবে, সুতরাং নতুন ইউনিয়নের কেস যুক্ত করা আসলে খুব খারাপ নয়।

মূল চয়ন করতে সদৃশ সন্ধানের বিষয়ে - আপনার ডুপ্লিকেট থাকা কোনও ম্যাচ থাকলে F # আপনাকে একটি সতর্কতা দেবে, যেমন:

match x with
| Some foo -> printfn "first"
| Some foo -> printfn "second" // Warning on this line as it cannot be matched
| None -> printfn "third"

"রুটের পছন্দ অপরিবর্তনীয়" এই বিষয়টিও সমস্যাযুক্ত হতে পারে। উদাহরণস্বরূপ, আপনি যদি কেস Fooএবং Barকেসগুলির মধ্যে কোনও ফাংশনটির বাস্তবায়ন ভাগ করতে চান তবে কেসের জন্য অন্য কিছু করেন Zoo, আপনি প্যাটার্ন মেলিং ব্যবহার করে সহজেই এনকোড করতে পারেন:

match x with
| Foo y | Bar y -> y * 20
| Zoo y -> y * 30

সাধারণভাবে, এফপি প্রথমে ধরণের ডিজাইন করা এবং তারপরে ফাংশন যুক্ত করার দিকে বেশি মনোনিবেশ করে। সুতরাং এটি সত্যই উপকার করে যে আপনি নিজের ধরণের (ডোমেন মডেল) একক ফাইলের কয়েকটি লাইনে ফিট করতে পারেন এবং তারপরে ডোমেন মডেলটিতে পরিচালিত ফাংশনগুলি সহজেই যুক্ত করতে পারেন।

দুটি উপায় - ওও এবং এফপি যথেষ্ট পরিপূরক এবং উভয়েরই সুবিধা এবং অসুবিধা রয়েছে। জটিল জিনিস (ওও দৃষ্টিকোণ থেকে আসা) হ'ল এফ # সাধারণত এফপি স্টাইলটি ডিফল্ট হিসাবে ব্যবহার করে। তবে যদি নতুন সাব-ক্লাস যুক্ত করার প্রয়োজন আরও বেশি হয় তবে আপনি সর্বদা ইন্টারফেস ব্যবহার করতে পারেন। তবে বেশিরভাগ সিস্টেমে আপনাকে সমানভাবে প্রকার এবং ফাংশন যুক্ত করতে হবে, তাই পছন্দটি আসলেই তেমন গুরুত্ব দেয় না - এবং এফ # তে বৈষম্যমূলক ইউনিয়নগুলি ব্যবহার করা আরও ভাল।

আমি আরও তথ্যের জন্য এই দুর্দান্ত ব্লগ সিরিজ সুপারিশ করব ।


3
যদিও আপনি সঠিক, আমি যুক্ত করতে চাই যে এটি ওও বনাম এফপি-র কোনও সমস্যা নয় কারণ এটি সমষ্টি ধরণের বনামগুলির ইস্যু। তাদের সাথে ওওপির আবেগকে একপাশে ফেলে রাখা, এমন বস্তুর সম্পর্কে কিছুই নেই যা তাদের অ-কার্যক্ষম করে তোলে। এবং যদি আপনি পর্যাপ্ত হুপের মধ্য দিয়ে ঝাঁপ দেন তবে আপনি মূলধারার ওওপি ভাষায়ও যোগফলগুলি প্রয়োগ করতে পারেন (যদিও এটি সুন্দর হবে না)।
ডোভাল

1
"এবং যদি আপনি পর্যাপ্ত হুপের মধ্য দিয়ে ঝাঁপ দেন তবে আপনি মূলধারার ওওপি ভাষাগুলিতেও যোগফলগুলি প্রয়োগ করতে পারেন (যদিও এটি সুন্দর হবে না)"। -> আমার ধারণা, আপনি কীভাবে নেট # টাইপের সিস্টেমে এফ # যোগ টাইপের এনকোড করা আছে তার অনুরূপ কিছু শেষ করবেন :)
টারমিল

8

আপনি সঠিকভাবে পর্যবেক্ষণ করেছেন যে প্যাটার্ন মিল (মূলত একটি সুপারচার্জড সুইচ বিবৃতি) এবং গতিশীল প্রেরণের মধ্যে মিল রয়েছে। তারা বেশ কয়েকটি উপভোগী ফলাফল সহ কয়েকটি ভাষায় সহাবস্থানও করে। তবে সামান্য পার্থক্য রয়েছে।

আমি টাইপ সিস্টেমটি এমন ধরণের সংজ্ঞা দেওয়ার জন্য ব্যবহার করতে পারি যাতে কেবলমাত্র নির্দিষ্ট সংখ্যক উপ-টাইপ থাকতে পারে:

// pseudocode
data Bool = False | True
data Option a = None | Some item:a
data Tree a = Leaf item:a | Node (left:Tree a) (right:Tree a)

সেখানে হবে না আরেকটি উপপ্রকার হতে Boolবা Option, তাই subclassing দরকারী (Scala মত কিছু কিছু ভাষায় subclassing যে সব ব্যবস্থা করতে সক্ষম এই একটি ধারণা আছে বলে মনে করে না - একটা শ্রেণী হিসেবে বর্তমান সংকলন ইউনিট "চূড়ান্ত" বাহিরে হিসাবে চিহ্নিত করা যাবে, কিন্তু উপশাখাকে এই সংকলন ইউনিটের ভিতরে সংজ্ঞায়িত করা যেতে পারে)।

যেহেতু এ জাতীয় ধরণের সাব টাইপগুলিOption এখন স্ট্যাটিকালি পরিচিত , তাই আমরা আমাদের প্যাটার্ন ম্যাচে কোনও কেস পরিচালনা করতে ভুলে গেলে সংকলক সতর্ক করতে পারে। এর অর্থ হ'ল একটি প্যাটার্ন ম্যাচটি একটি বিশেষ ডাউনকাস্টের মতো যা আমাদের সমস্ত বিকল্প হ্যান্ডেল করতে বাধ্য করে।

তদুপরি, গতিশীল পদ্ধতি প্রেরণ (যা ওওপি জন্য প্রয়োজনীয়) এছাড়াও একটি রানটাইম টাইপ চেক বোঝায়, তবে অন্য ধরণের। এটি অতএব অপ্রাসঙ্গিক যদি আমরা এই ধরণের কোনও প্যাটার্ন ম্যাচের মাধ্যমে স্পষ্টভাবে বা পদ্ধতি কলের মাধ্যমে স্পষ্টভাবে পরীক্ষা করি।


"এর অর্থ হ'ল একটি প্যাটার্ন ম্যাচটি একটি বিশেষ ডাউনকাস্টের মতো যা আমাদের সমস্ত বিকল্প পরিচালনা করতে বাধ্য করে" - আসলে আমি বিশ্বাস করি যে (যতক্ষণ না আপনি কেবল নির্মাতাদের সাথে মিল করছেন এবং মান বা নেস্টেড কাঠামোর সাথে নয়) এটি বিচ্ছিন্ন সুপারক্লাসে একটি বিমূর্ত ভার্চুয়াল পদ্ধতি স্থাপন।
জুলাই

2

এফ # প্যাটার্নের মিলটি ক্লাসের চেয়ে সাধারণত বৈষম্যমূলক ইউনিয়ন দিয়ে করা হয় (এবং এটি প্রযুক্তিগতভাবে কোনও ধরণের চেক নয়)। আপনি যখন কোনও প্যাটার্ন-ম্যাচে কেস অ্যাকাউন্ট না করে রেখেছেন তখন এটি সংকলক আপনাকে একটি সতর্কতা দেওয়ার অনুমতি দেয়।

আরেকটি বিষয় লক্ষণীয় যে একটি কার্যকরী শৈলীতে, আপনি ডেটা না করে কার্যকারিতা দ্বারা জিনিসগুলিকে সংগঠিত করেন, তাই প্যাটার্ন মিলগুলি আপনাকে ক্লাসে ছড়িয়ে ছিটিয়ে বিভিন্ন স্থানে আলাদা কার্যকারিতা এক জায়গায় সংগ্রহ করতে দেয়। এটিরও সুবিধা রয়েছে যে আপনি দেখতে পাচ্ছেন যে যেখানে আপনার পরিবর্তনগুলি করা দরকার তার ঠিক পাশেই অন্যান্য মামলাগুলি কীভাবে পরিচালনা করা হয়।

একটি নতুন বিকল্প যুক্ত করার পরে দেখে মনে হচ্ছে:

  1. আপনার বৈষম্যমূলক ইউনিয়নে একটি নতুন বিকল্প যুক্ত করুন
  2. অসম্পূর্ণ প্যাটার্ন ম্যাচে সমস্ত সতর্কতা ঠিক করুন

2

আংশিকভাবে, আপনি এটি প্রায়শই কার্যকরী প্রোগ্রামিংয়ে দেখেন কারণ আপনি প্রায়শই সিদ্ধান্ত নেওয়ার জন্য ধরণগুলি ব্যবহার করেন। আমি বুঝতে পেরেছি যে আপনি সম্ভবত এলোমেলোভাবে কমবেশি উদাহরণগুলি বেছে নিয়েছেন, তবে আপনার প্যাটার্নের মিলের উদাহরণের সাথে ওওপি সমতুল্য প্রায়শই দেখতে পাবেন:

if (opt != null)
    opt.Something()
else
    Different()

অন্য কথায়, ওওপিতে নাল চেকের মতো রুটিন জিনিসগুলি এড়াতে পলিমারফিজম ব্যবহার করা অপেক্ষাকৃত বিরল। ওও প্রোগ্রামার যেমন প্রতিটি ছোট পরিস্থিতিতে নাল বস্তু তৈরি করে না তেমনি একটি কার্যকরী প্রোগ্রামার সর্বদা একটি ফাংশনকে ওভারলোড করে না, বিশেষত যখন আপনি জানেন যে আপনার নিদর্শনগুলির তালিকাটি সম্পূর্ণরূপে গ্যারান্টিযুক্ত। আপনি যদি আরও পরিস্থিতিতে টাইপ সিস্টেমটি ব্যবহার করেন তবে আপনি এটি ব্যবহার করতে দেখতে যাচ্ছেন আপনি অভ্যস্ত নন।

বিপরীতভাবে, আপনার গলি উদাহরণ কথ্য কার্যকরী প্রোগ্রামিং সমতুল্য সম্ভবত প্যাটার্ন ম্যাচিং ব্যবহার করবেন, কিন্তু হবে fooRouteএবং barRouteফাংশন যে কলিং কোড আর্গুমেন্ট হিসাবে পাস পেতে হবে। যদি কেউ এই পরিস্থিতিতে প্যাটার্ন ম্যাচিং ব্যবহার করে তবে এটি সাধারণত ভুল হিসাবে বিবেচিত হবে, ঠিক যেমন কোনও ব্যক্তি টাইপগুলিতে স্যুইচ করে ওওপি-তে ভুল হিসাবে বিবেচিত হবে।

সুতরাং যখন প্যাটার্ন মিলটি ভাল ফাংশনাল প্রোগ্রামিং কোড হিসাবে বিবেচিত হয়? যখন আপনি কেবল প্রকারগুলি দেখার চেয়ে আরও বেশি কিছু করছেন, এবং প্রয়োজনীয়তাগুলি প্রসারিত করার সময় আরও কেস যুক্ত করার প্রয়োজন হয় না। উদাহরণস্বরূপ, Some valকেবল যা optটাইপ রয়েছে তা যাচাই করে না Some, এটি valঅন্য দিকে টাইপ-নিরাপদ ব্যবহারের জন্য অন্তর্নিহিত ধরণের সাথে আবদ্ধ হয় ->। আপনি জানেন যে আপনার সম্ভবত তৃতীয় কেসের কোনও প্রয়োজন হবে না তাই এটি ভাল ব্যবহার।

প্যাটার্নের মিলটি কোনও বস্তু-ভিত্তিক সুইচ স্টেটমেন্টের সাথে सतर्कভাবে সাদৃশ্যপূর্ণ হতে পারে তবে আরও অনেক কিছু চলছে, বিশেষত দীর্ঘ বা নেস্টেড নিদর্শনগুলির সাথে। নিশ্চিত করে নিন যে এটি কিছু করছে যা আপনি এটি করছেন তা কিছু খারাপ-ডিজাইন করা ওওপি কোডের সমতুল্য ঘোষণার আগে account প্রায়শই, এটি দৃc়ভাবে একটি পরিস্থিতি পরিচালনা করে যা উত্তরাধিকারের শ্রেণিবিন্যাসে পরিষ্কারভাবে প্রতিনিধিত্ব করতে সক্ষম হয় না।


আমি জানি আপনি এটি জানেন, এবং এটি সম্ভবত আপনার উত্তর লেখার সময় আপনার মন কেড়ে নিয়েছিল, তবে এটি নোট করুন Someএবং Noneপ্রকার নয়, তাই আপনি ধরণের সাথে প্যাটার্ন মেলছেন না। উপর আপনি প্যাটার্ন ম্যাচ কনস্ট্রাকটর এর একই ধরনের । এটি "উদাহরণস্বরূপ" জিজ্ঞাসা করার মতো নয়।
আন্দ্রেস এফ।
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.