ফলব্যাকস সহ বিশেষ ক্ষেত্রে লিসকোব সাবস্টিটিউশন নীতি লঙ্ঘন করে?


20

ধরা যাক আমার একটি ইন্টারফেস FooInterfaceরয়েছে যার সাথে নিম্নলিখিত স্বাক্ষর রয়েছে:

interface FooInterface {
    public function doSomething(SomethingInterface something);
}

এবং একটি কংক্রিট শ্রেণি ConcreteFooযা সেই ইন্টারফেস প্রয়োগ করে:

class ConcreteFoo implements FooInterface {

    public function doSomething(SomethingInterface something) {
    }

}

আমি ConcreteFoo::doSomething()একটি বিশেষ ধরণের SomethingInterfaceঅবজেক্ট (যদি বলা যাক এটি বলা হয় SpecialSomething) পাস করে তবে অনন্য কিছু করতে চাই ।

আমি যদি পদ্ধতিটির পূর্বশর্তগুলিকে আরও শক্তিশালী করি বা একটি নতুন ব্যতিক্রম ছুঁড়ে ফেলি তবে এটি অবশ্যই একটি এলএসপি লঙ্ঘন, তবে SpecialSomethingজেনেরিক SomethingInterfaceঅবজেক্টগুলির জন্য ফ্যালব্যাক সরবরাহের সময় যদি আমি বিশেষ-কেসযুক্ত বস্তুগুলি করি তবে এটি কি এলএসপি লঙ্ঘন হবে ? কিছুটা এইরকম:

class ConcreteFoo implements FooInterface {

    public function doSomething(SomethingInterface something) {
        if (something instanceof SpecialSomething) {
            // Do SpecialSomething magic
        }
        else {
            // Do generic SomethingInterface magic
        }
    }

}

উত্তর:


19

এটা তোলে পারে আর কি জন্য চুক্তিতে উপর নির্ভর করে LSP লঙ্ঘন হতে doSomethingপদ্ধতি। তবে এটি অবশ্যই কোনও কোডের গন্ধ এমনকি এলএসপি লঙ্ঘন না করে।

উদাহরণস্বরূপ, যদি চুক্তি অংশ doSomethingযে একে ডাকতে হবে something.commitUpdates()একবার ফেরার আগে অন্তত, এবং বিশেষ মামলায় এটা আহ্বান commitSpecialUpdates()পরিবর্তে, তাহলে সেই হয় LSP লঙ্ঘন। এমনকি যদি SpecialSomethingএর commitSpecialUpdates()পদ্ধতি সচেতনভাবে হিসাবে একই জিনিস সব করতে পরিকল্পিত ছিল commitUpdates(), যে শুধু preemptively LSP লঙ্ঘন প্রায় ফাটান, এবং ঠিক গোরুর গাড়ি এক সাজানোর যদি এক LSP ধারাবাহিকভাবে অনুসৃত যা করতে হবে না। আপনার ক্ষেত্রে এই জাতীয় কিছু প্রযোজ্য কিনা তা সেই পদ্ধতির জন্য আপনার চুক্তিটি (স্পষ্ট বা আবদ্ধ কিনা) পরীক্ষা করে আপনাকে বের করতে হবে।

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


ধন্যবাদ! এটি সাহায্য করে। হাইপোথিটিক্যালি, doSomething()পদ্ধতির উদ্দেশ্যটি হ'ল রূপান্তরিত হবে SpecialSomething: এটি যদি এটি গ্রহণ SpecialSomethingকরে তবে কেবল এটি অবাস্তবহীন বস্তুটি ফিরিয়ে দেবে, অন্যদিকে যদি এটি একটি জেনেরিক SomethingInterfaceবস্তু গ্রহণ করে তবে এটি একটি বস্তুর মধ্যে রূপান্তর করতে একটি অ্যালগরিদম চালায় SpecialSomething। পূর্ব শর্ত এবং পোস্টকন্ডিশনগুলি একই থাকায়, আমি বিশ্বাস করি না যে চুক্তি লঙ্ঘিত হয়েছে।
ইভান

1
@ ইভান ওহ বাহ ... এটি একটি আকর্ষণীয় ঘটনা। এটি আসলে সম্পূর্ণ অপ্রয়োজনীয় হতে পারে। কেবলমাত্র আমি ভাবতে পারি যে আপনি যদি নতুন অবজেক্ট তৈরির পরিবর্তে বিদ্যমান অবজেক্টটি ফিরিয়ে দিচ্ছেন তবে হয়ত কেউ এই পদ্ধতির উপর নির্ভর করে একটি নতুন নতুন অবজেক্ট ফিরিয়ে দেবে ... তবে এই ধরণের জিনিসটি মানুষকে ভেঙে ফেলতে পারে কিনা তার উপর নির্ভর করে ভাষা. এটা কি সম্ভব কেউ কল করার জন্য y = doSomething(x), তারপর x.setFoo(3), এবং তারপর যে এটি y.getFoo()আয় 3?
Ixrec

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

1

এটি এলএসপির লঙ্ঘন নয়। তবে এটি এখনও "টাইপ চেক করবেন না" নিয়মের লঙ্ঘন। কোডটি এমনভাবে ডিজাইন করা আরও ভাল হবে যে বিশেষটি স্বাভাবিকভাবে উত্থিত হয়; হতে SomethingInterfaceপারে অন্য কোনও সদস্যের প্রয়োজন হয় যা এটি সম্পাদন করতে পারে, অথবা হতে পারে আপনাকে কোথাও একটি বিমূর্ত কারখানাটি ইনজেক্ট করতে হবে।

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


1

না, কোনও প্রদত্ত যুক্তি কেবল ইন্টারফেস এ সরবরাহ করে না, তবে এ 2ও, এলএসপি লঙ্ঘন করে না এই বিষয়টি গ্রহণ করে।

কেবলমাত্র নিশ্চিত হয়ে নিন যে বিশেষ পথে আরও শক্তিশালী প্রাক-শর্ত না রয়েছে (এটি গ্রহণের সিদ্ধান্ত নেওয়ার পরে পরীক্ষা করা লোকদের বাদে), বা কোনও দুর্বল পোস্ট-শর্ত নয়।

সি ++ টেমপ্লেটগুলি প্রায়শই আরও ভাল পারফরম্যান্স প্রদানের জন্য এটি করে, উদাহরণস্বরূপ প্রয়োজন InputIteratorএস এর প্রয়োজনে , তবে RandomAccessIteratorএস এর সাথে ডাকলে অতিরিক্ত গ্যারান্টি দেওয়া ।

যদি পরিবর্তে রানটাইমে সিদ্ধান্ত নিতে হয় (উদাহরণস্বরূপ ডায়নামিক ingালাই ব্যবহার করে), আপনার সমস্ত সম্ভাব্য লাভ বা আরও বেশি কী পরিমাণ গ্রাস করতে হবে সেই পথটি সম্পর্কে সতর্ক থাকুন be

বিশেষ ক্ষেত্রে সদ্ব্যবহার করা প্রায়শই ডিআরওয়াই (নিজেকে পুনরাবৃত্তি করবেন না), কারণ আপনার কোডটি নকল করতে হতে পারে এবং কেআইএসএসের (এটি সহজ রাখুন) বিরুদ্ধে, কারণ এটি আরও জটিল।


0

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

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


0

লিসকভের প্রতিস্থাপনের নীতিটি তাদের উপকারের চুক্তি অনুসারে সাব টাইপগুলি অভিনয় সম্পর্কে about সুতরাং, যেমন Ixrec লিখেছেন, এটি কোনও LSP লঙ্ঘন কিনা তা উত্তর দেওয়ার জন্য পর্যাপ্ত তথ্য নেই।

এখানে যা লঙ্ঘন করা হয়েছে তা একটি মুক্ত বদ্ধ নীতি। যদি আপনার একটি নতুন প্রয়োজনীয়তা থাকে - বিশেষত যাদু করুন - এবং আপনাকে বিদ্যমান কোডটি সংশোধন করতে হবে, তবে আপনি অবশ্যই ওসিপি লঙ্ঘন করছেন

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