নির্ভরতা বিপরীকরণ কীভাবে উচ্চতর ক্রমের সাথে সম্পর্কিত?


41

আজ আমি এই নিবন্ধটি দেখেছি যা F # বিকাশের ক্ষেত্রে সলাইড নীতিটির প্রাসঙ্গিকতার বর্ণনা দিয়েছে-

এফ # এবং ডিজাইনের নীতিগুলি - সলিড

এবং শেষটিকে সম্বোধন করার সময় - "নির্ভরতা বিপরীতার নীতি", লেখক বলেছেন:

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

তবে তিনি এর আরও ব্যাখ্যা দেননি। সুতরাং, আমার প্রশ্ন হ'ল উচ্চতর আদেশের ক্রিয়াকলাপগুলির সাথে নির্ভরতা বিপরীকরণ কীভাবে সম্পর্কিত?

উত্তর:


38

OOP- এ নির্ভরতা বিপরীকরণের অর্থ হল আপনি কোনও ইন্টারফেসের বিরুদ্ধে কোড করেন যা কোনও বস্তুর প্রয়োগের দ্বারা সরবরাহ করা হয়।

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

এই জাতীয় ভাষায়, ফাংশনের স্বাক্ষরটি ইন্টারফেসে পরিণত হতে পারে এবং পছন্দসই আচরণ প্রদানের জন্য একটি ফাংশন একটি traditionalতিহ্যগত বস্তুর পরিবর্তে পাস করা হয়। মাঝের প্যাটার্নের গর্ত এটির জন্য একটি ভাল উদাহরণ।

এটি আপনাকে কম কোড এবং আরও অভিব্যক্তি সহ একই ফলাফল অর্জন করতে দেয়, কারণ আপনাকে কলারের জন্য কাঙ্ক্ষিত আচরণ প্রদানের জন্য (OOP) ইন্টারফেসের সাথে সঙ্গতিপূর্ণ একটি সম্পূর্ণ শ্রেণি প্রয়োগ করার দরকার নেই। পরিবর্তে, আপনি কেবল একটি সাধারণ ফাংশন সংজ্ঞা পাস করতে পারেন। সংক্ষেপে: কোডটি বজায় রাখা প্রায়শই সহজ, যখন উচ্চতর অর্ডার ফাংশন ব্যবহার করে তখন আরও অভিব্যক্তিপূর্ণ এবং আরও নমনীয়।

সি # তে একটি উদাহরণ

প্রথাগত পদ্ধতি:

public IEnumerable<Customer> FilterCustomers(IFilter<Customer> filter, IEnumerable<Customers> customers)
{
    foreach(var customer in customers)
    {
        if(filter.Matches(customer))
        {
            yield return customer;
        }
    }
}

//now you've got to implement all these filters
class CustomerNameFilter : IFilter<Customer> /*...*/
class CustomerBirthdayFilter : IFilter<Customer> /*...*/

//the invocation looks like this
var filteredDataByName = FilterCustomers(new CustomerNameFilter("SomeName"), customers);
var filteredDataBybirthDay = FilterCustomers(new CustomerBirthdayFilter(SomeDate), customers);

উচ্চতর ক্রমের সাথে:

public IEnumerable<Customer> FilterCustomers(Func<Customer, bool> filter, IEnumerable<Customers> customers)
{
    foreach(var customer in customers)
    {
        if(filter(customer))
        {
            yield return customer;
        }
    }
}

এখন বাস্তবায়ন এবং প্রার্থনা কম জটিল হয়ে ওঠে। আমাদের আর আইফিল্টার বাস্তবায়ন সরবরাহ করার দরকার নেই। ফিল্টারগুলির জন্য আমাদের আর ক্লাস প্রয়োগ করার দরকার নেই।

var filteredDataByName = FilterCustomers(x => x.Name.Equals("CustomerName"), customers);
var filteredDataByBirthday = FilterCustomers(x => x.Birthday == SomeDateTime, customers);

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


3
চমৎকার উদাহরণ। তবে গুলশানের মতো আমি ফাংশনাল প্রোগ্রামিং সম্পর্কে আরও জানার চেষ্টা করছি এবং আমি ভাবছিলাম যে এই জাতীয় "ফাংশনাল ডিআই" "অবজেক্ট ওরিয়েন্টেড ডিআই" এর তুলনায় কিছু কঠোরতা এবং তাত্পর্যকে ত্যাগ না করে। উচ্চতর আদেশের স্বাক্ষর কেবলমাত্র বলেছে যে পাস করা ফাংশনটি অবশ্যই একজন গ্রাহককে প্যারামিটার হিসাবে গ্রহণ করবে এবং একটি বিল ফিরিয়ে দেবে যেখানে ওও সংস্করণটি এই বিষয়টি প্রয়োগ করে যে পাস করা বস্তুটি একটি ফিল্টার (IFilter <কাস্টমোর> প্রয়োগ করে)। এটি ফিল্টারের ধারণাটিও সুস্পষ্ট করে তোলে, এটি যদি ডোমেনের একটি মূল ধারণা (ডিডিডি দেখুন) হয় তবে ভাল জিনিস হতে পারে। আপনি কি মনে করেন ?
guillaume31

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

5
@ আইয়ান 31: আমি সম্পূর্ণরূপে একমত নই। বাস্তবায়ন মোটেই বাস্তবায়ন IFilter<Customer>নয়। উচ্চতর অর্ডার ফাংশনটি আরও বেশি নমনীয়, যা একটি বড় সুবিধা এবং এগুলি ইনলাইনে লিখতে সক্ষম হওয়াই আরেকটি বিশাল সুবিধা। ল্যাম্বডাস স্থানীয় ভেরিয়েবলগুলি ক্যাপচার করতেও অনেক সহজ।
ডেড এমজি

3
@ আইয়ান 31: সংকলন-সময় ফাংশনটিও যাচাই করা যেতে পারে। আপনি কোনও ফাংশনও লিখতে পারেন, নাম রাখতে পারেন এবং যতক্ষণ না এটি সুস্পষ্ট চুক্তি পূরণ করে (গ্রাহক গ্রহণ করেন, প্রত্যাবর্তন শুল্ক গ্রহণ করবে) ততক্ষণ এটিকে যুক্তি হিসাবে পাস করতে পারেন। আপনার অগত্যা ল্যাম্বডা এক্সপ্রেশনটি পাস করার দরকার নেই। সুতরাং আপনি একটি নির্দিষ্ট ডিগ্রীতে মত প্রকাশের অভাবটি আবরণ করতে পারেন। যাইহোক, চুক্তি এবং এর উদ্দেশ্যটি পরিষ্কারভাবে প্রকাশ করা হয়নি not এটি কখনও কখনও একটি বড় অসুবিধা হয়। সব মিলিয়ে এটি ভাববোধ, ভাষা এবং এনক্যাপসুলেশন এর বিষয়। আমি মনে করি আপনাকে প্রতিটি মামলা নিজেই বিচার করতে হবে।
ফ্যালকন

2
আপনি একটি ইনজেকশনের ফাংশনের শব্দার্থিক অর্থ পরিষ্কারভাবে সম্পর্কে জোরালোভাবে মনে করলে আপনাকে হয়ত C # এর নাম ফাংশন স্বাক্ষরে প্রতিনিধিদের ব্যবহার করতে পারেন: public delegate bool CustomerFilter(Customer customer)। হাস্কেলের মতো খাঁটি কার্যকরী ভাষায়, এলিয়াসিং ধরণের ক্ষুদ্রতর:type customerFilter = Customer -> Bool
সারা

8

যদি আপনি কোনও ফাংশনের আচরণ পরিবর্তন করতে চান

doThis(Foo)

আপনি অন্য ফাংশন পাস করতে পারে

doThisWith(Foo, anotherFunction)

যা আপনি আলাদা হতে চান এমন আচরণকে কার্যকর করে।

"doThisWith" একটি উচ্চ-অর্ডার ফাংশন কারণ এটি যুক্তি হিসাবে অন্য ফাংশন নেয়।

উদাহরণস্বরূপ আপনি থাকতে পারে

storeValues(Foo, writeToDatabase)
storeValues(Foo, imitateDatabase)

5

সংক্ষিপ্ত উত্তর:

ক্লাসিকাল নির্ভরতা ইনজেকশন / নিয়ন্ত্রণের বিপরীততা নির্ভরশীল কার্যকারিতার জন্য স্থানধারক হিসাবে একটি শ্রেণিক ইন্টারফেস ব্যবহার করে। এই ইন্টারফেসটি একটি শ্রেণীর দ্বারা প্রয়োগ করা হয়।

ইন্টারফেস / শ্রেণি প্রয়োগের পরিবর্তে একটি প্রতিনিধি কার্যক্রমে অনেকগুলি নির্ভরশীলতা সহজভাবে প্রয়োগ করা যেতে পারে implemented

আপনি আইও-কারখানার-পেশাদার-এবং-বিপরীতে-ইন্টারফেস-বনাম-প্রতিনিধিদের জন্য সি # তে উভয়ের উদাহরণ খুঁজে পান ।


0

এর সাথে তুলনা করুন:

String[] names = {"Fred", "Susan"};
List<String> namesBeginningWithS = new LinkedList<String>();
for (String name : names) {
    if (name.startsWith("S")) {
        namesBeginningWithS.add(name);
    }
}

সঙ্গে:

String[] names = {"Fred", "Susan"};
List<String> namesBeginningWithS = names.stream().filter(n <- n.startsWith("S")).collect();

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


0

পিগি-ব্যাকিং অফ লেনিপ্রগ্রামের উদাহরণগুলি ...

অন্যান্য উদাহরণগুলি যেগুলি মিস করেছে সেগুলির মধ্যে একটি হ'ল আপনি একটি নতুন ফাংশন তৈরি করতে আংশিক ফাংশন অ্যাপ্লিকেশন (পিএফএ) এর সাথে আংশিক ফাংশন অ্যাপ্লিকেশন (পিএফএ) এর সাথে একটি ফাংশনে নির্ভরতা (তার যুক্তি তালিকার মাধ্যমে) আবদ্ধ করতে উচ্চতর অর্ডার ফাংশনগুলি ব্যবহার করতে পারেন।

পরিবর্তে যদি:

doThisWith(Foo, anotherFunction)

আমাদের (পিএফএ সাধারণত কীভাবে করা হয় তার মধ্যে প্রচলিত হতে হবে) নিম্ন স্তরের কর্মী (আর্গ ক্রম অদলবদল) হিসাবে রয়েছে:

doThisWith( anotherFunction, Foo )

তারপরে আমরা আংশিকভাবে doTisWith এর মতো প্রয়োগ করতে পারি :

doThis = doThisWith( anotherFunction )  // note that "Foo" is still missing, argument list is partial

যা আমাদের পরবর্তীকালে নতুন ফাংশনটি ব্যবহার করতে দেয়:

doThis(Foo)

অথবা এমনকি:

doThat = doThisWith( yetAnotherDependencyFunction )
...
doThat( Bar )

আরও দেখুন: https://ramdajs.com/docs/#partial

... এবং হ্যাঁ, সংযোজক / গুণকগুলি অকল্পনীয় উদাহরণ। এর চেয়ে ভাল উদাহরণ হ'ল একটি ফাংশন যা বার্তাগুলি গ্রহণ করে এবং লগ করে বা ইমেল করে "ভোক্তা" ফাংশন নির্ভরতার হিসাবে কীভাবে পাস করেছে তার উপর নির্ভর করে।

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

ওওপি যদি আপনার একাধিক ঘনিষ্ঠভাবে সম্পর্কিত অপারেশনগুলির সাথে জিনিসগুলির একটি বান্ডিলের প্রয়োজন হয় তবে এটি মেক-ওয়ার্কে পরিণত হয় প্রতিটি একক জনসাধারণকে "এটি করুন" পদ্ধতি দিয়ে একটি ক্লাস তৈরি করার জন্য, "লা কিংডম অফ নউনস" তৈরি করে।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.