যদি সিঙ্গলেটগুলি খারাপ হয় তবে পরিষেবা কন্টেইনারটি ভাল কেন?


91

আমরা সকলেই জানি সিলেটলেটগুলি কতটা খারাপ, কারণ তারা নির্ভরতা এবং অন্যান্য কারণে লুকায় ।

তবে একটি কাঠামোর মধ্যে অনেকগুলি অবজেক্ট থাকতে পারে যা কেবল একবার ইনস্ট্যান্ট করা দরকার এবং যে কোনও জায়গা থেকে ডেকে আনা দরকার (লগার, ডিবি ইত্যাদি)।

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

তবে কেন কোনও পরিষেবা সরবরাহকারী খাঁটি সিঙ্গলটনের মতো খারাপ নয়?

পরিষেবা সরবরাহকারী নির্ভরতাগুলিও গোপন করে এবং তারা কেবল প্রথম আইসট্যান্স তৈরির বিষয়টি গুটিয়ে রাখে। সুতরাং কেন আমাদের সিঙ্গেলনের পরিবর্তে কোনও পরিষেবা সরবরাহকারী ব্যবহার করা উচিত তা বুঝতে লড়াই করছি ling

পুনশ্চ. আমি জানি যে নির্ভরতা না লুকানোর জন্য আমার ডিআই ব্যবহার করা উচিত (মিসকো বলেছেন)

অ্যাড

আমি যোগ করব: এই দিনগুলিতে সিলেটলেটগুলি খারাপ নয়, পিএইচপিউইনিতের নির্মাতা এটি এখানে ব্যাখ্যা করেছেন:

ডিআই + সিঙ্গেলটন সমস্যা সমাধান করে:

<?php
class Client {

    public function doSomething(Singleton $singleton = NULL){

        if ($singleton === NULL) {
            $singleton = Singleton::getInstance();
        }

        // ...
    }
}
?>

এটি খুব স্মার্ট যদি এমনকি এটি প্রতিটি সমস্যার সমাধান না করে।

ডিআই এবং পরিষেবা কনটেইনার ব্যতীত এই সহায়ক সাহায্যকারী জিনিসগুলি অ্যাক্সেস করার জন্য কোনও ভাল গ্রহণযোগ্য সমাধান রয়েছে কি?


4
@ চোখ আপনার সম্পাদনা মিথ্যা অনুমান করছে। সেবাস্তিয়ান কোনওভাবেই পরামর্শ দিচ্ছেন না যে কোড স্নিপেট সিঙ্গলস ব্যবহার করে কম সমস্যা তৈরি করছে। কোড তৈরির কেবল একটি উপায় যা অন্যথায় আরও পরীক্ষামূলকভাবে পরীক্ষা করা অসম্ভব। তবে এটি এখনও সমস্যাযুক্ত কোড। প্রকৃতপক্ষে, তিনি স্পষ্টভাবে নোট করেছেন: "জাস্ট কারণ আপনি পারবেন, না এর মানে আপনি হওয়া উচিত"। সঠিক সমাধানটি হ'ল সিলেটলেটগুলি মোটেও ব্যবহার না করা।
গর্ডন

4
@ চোখ সলাইড নীতি অনুসরণ করে।
গর্ডন

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

4
@paxdiablo কিন্তু তারা হয় খারাপ। সিঙ্গলেটগুলি এসআরপি, ওসিপি এবং ডিআইপি লঙ্ঘন করে। তারা আপনার অ্যাপ্লিকেশনে গ্লোবাল স্টেট এবং আঁটসাঁটো মিলনের পরিচয় দেয় এবং এটির নির্ভরতা সম্পর্কে আপনার এপিআই মিথ্যা করে। এগুলি আপনার কোডটির রক্ষণাবেক্ষণযোগ্যতা, পঠনযোগ্যতা এবং পরীক্ষামূলকতার উপর negativeণাত্মক প্রভাব ফেলবে। এমন দুর্লভ ঘটনা ঘটতে পারে যেখানে এই অসুবিধাগুলি অল্প উপকারের চেয়ে বেশি, তবে আমি যুক্তি দিয়ে বলব যে 99% এর মধ্যে আপনার একক প্রয়োজন নেই need বিশেষত পিএইচপি যেখানে সিংলেটনগুলি কেবলমাত্র অনুরোধের জন্য অনন্য এবং বিল্ডারের কাছ থেকে সহযোগী গ্রাফগুলি একত্রিত করার পক্ষে এটি ময়লা dirt
গর্ডন

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

উত্তর:


76

সার্ভিস লোকেটার বলতে গেলে দু'টি খারাপের চেয়ে কম হয় ser এই চারটি পার্থক্যে "কম" সেদ্ধ হয়ে উঠছে ( কমপক্ষে আমি এখনই অন্য কাউকে ভাবতে পারি না ):

একক দায়িত্বের নীতি

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

কাপলিং

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

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

লুকানো নির্ভরতা

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

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

গ্লোবাল স্টেট

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

আরও গভীরতর আলোচনার জন্য সার্ভিস লোকেটার বনাম নির্ভরশীল ইনজেকশন সম্পর্কিত ফওলারটি দেখুন see


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


4
বিশেষত টেস্টিবিলিটি এখানে প্রয়োগ করা উচিত। আপনি স্থির পদ্ধতি কলগুলি উপহাস করতে পারবেন না। তবে আপনি কনক্ট্রাক্টর বা সেটারের মাধ্যমে ইঞ্জিন করা পরিষেবাগুলিকে মক করতে পারেন।
ডেভিড

44

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

সুতরাং, আপনার প্রশ্নটি হল: কেন পরিষেবা লোকেটারগুলি ভাল? আমার উত্তর: তারা না।

এড়ানো, এড়ানো, এড়ানো।


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

4
@ হ্যাঁ 123: যে লোকেরা বলে যে এটি ভুল, এবং তারা ভুল কারণ এসএল একটি অ্যান্টি-প্যাটার্ন। আপনার প্রশ্ন "এসএল ভাল কেন?" আমার উত্তর: তারা না।
জেসন

4
আমি তর্ক করব না যদি এসএল কোনও অ্যানিট-প্যাটার্ন হয় বা না, তবে আমি যা বলব তা হ'ল সিঙ্গলটন এবং গ্লোবালগুলির সাথে তুলনা করার সময় এটি খুব খারাপ বিষয়গুলি কম। আপনি একটি সিঙ্গলটনের উপর নির্ভর করে এমন কোনও ক্লাস পরীক্ষা করতে পারবেন না, তবে আপনি অবশ্যই একটি ক্লাস যা একটি এসএল উপর নির্ভর করে পরীক্ষা করতে পারেন (আপনি এসএল নকশাটি যে জায়গায় কাজ করতে পারবেন না সেখানে স্ক্রু করতে পারেন) ... সুতরাং এটি মূল্যবান লক্ষণীয় ...
ইরকম্যাক্সেল

4
@ জেসন আপনাকে অবজেক্টটি পাস করতে হবে যা ইন্টারফেস প্রয়োগ করে - এবং এটি কেবল আপনার জানা দরকার। আপনি কেবল ক্লাস কনস্ট্রাক্টরের সংজ্ঞা দিয়ে নিজেকে সীমাবদ্ধ করছেন এবং কনস্ট্রাক্টরে সব ক্লাস (ইন্টারফেস নয়) লিখতে চান - এটি বোকামি ধারণা। আপনার যা দরকার তা হ'ল ইন্টারফেস। আপনি এই ক্লাসটিকে সফলভাবে মক দিয়ে পরীক্ষা করতে পারেন, কোড পরিবর্তন না করে আপনি সহজেই আচরণটি পরিবর্তন করতে পারেন, কোনও অতিরিক্ত নির্ভরতা এবং কাপলিং নেই - এটাই (সাধারণভাবে) Dependency Injection এ আমাদের কী থাকতে হবে।
ওজেড

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

4

সার্ভিস ধারক একক প্যাটার্নের মতো নির্ভরতাগুলি লুকায় ides পরিবর্তে আপনি নির্ভরতা ইনজেকশন পাত্রে ব্যবহার করার পরামর্শ দিতে পারেন, কারণ এতে পরিষেবা ধারকটির সমস্ত সুবিধা রয়েছে তবে পরিষেবা কনটেইনারটির যে অসুবিধা নেই (যতদূর আমি জানি)।

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

এটি উভয়ের পার্থক্যের ব্যাখ্যা করে SO- তে একটি ভাল প্রশ্ন: নির্ভরতা ইনজেকশন এবং পরিষেবা লোকেটারের ধরণগুলির মধ্যে পার্থক্য কী?


"ডিআইসি আপনার জন্য উপযুক্ত নির্ভরতাগুলিকে ইনজেকশন দেয়" সিঙ্গলটনের সাথেও কি এটি ঘটে না?
গতিশীল

4
@ হ্যাঁ 123 - আপনি যদি কোনও সিঙ্গেলটন ব্যবহার করেন তবে আপনি এটিতে ইনজেকশন দেবেন না, বেশিরভাগ সময় আপনি কেবল বিশ্বব্যাপী এটি অ্যাক্সেস করতে চান (এটি সিঙ্গেলনের মূল বিষয়)। আমি মনে করি আপনি যদি বলেন যে আপনি যদি সিঙ্গলটন ইনজেক্ট করেন তবে এটি নির্ভরতাগুলি গোপন করবে না, তবে এটি একরকম একক প্যাটার্নের মূল উদ্দেশ্যকে হারাবে - আপনি নিজেকে জিজ্ঞাসা করবেন, বিশ্বব্যাপী এই শ্রেণীর অ্যাক্সেস করার জন্য আমার যদি প্রয়োজন হয় না, তবে কেন আমার কি এটি সিঙ্গলটন তৈরি করতে হবে?
রিক্রিস্টি

2

কারণ আপনি সহজেই পরিষেবা কনটেইনারগুলিতে
1 দ্বারা উত্তোলন করতে পারেন ) উত্তরাধিকার (অবজেক্ট ম্যানেজার শ্রেণি উত্তরাধিকার সূত্রে প্রাপ্ত হতে পারে এবং পদ্ধতিগুলি ওভাররাইড করা যেতে পারে)
2) কনফিগারেশন পরিবর্তন করা (সিমফোনির ক্ষেত্রে)

এবং, সিঙ্গললেটগুলি কেবলমাত্র উচ্চ সংশ্লেষের কারণে খারাপ নয়, কারণ তারা _ সিঙ্গল _ টন। এটি প্রায় সব ধরণের বস্তুর জন্য ভুল স্থাপত্য।

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


0

আমার জন্য, আমি একটি সাধারণ কারণে বিশ্বব্যাপী ধ্রুবকগুলি, সিলেটলেটগুলি এড়াতে চেষ্টা করি, এমন কিছু ঘটনা ঘটে যখন আমার এপিআই চলতে পারে।

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

$frontend = new Frontend();
$frontend->auth->login($_GET['user']);
$frontend->redirect('/');

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

আমার সিঙ্গলটনের ধারণাটি হ'ল - আপনি প্যারেন্টের ভিতরে দু'বার একই জিনিস যুক্ত করতে পারবেন না। এই ক্ষেত্রে

$logger1=$api->add('Logger');
$logger2=$api->add('Logger');

আপনাকে একটি একক উদাহরণ এবং উভয় ভেরিয়েবল এতে নির্দেশ করবে।

অবশেষে যদি আপনি অবজেক্ট ওরিয়েন্টেড ডেভলপমেন্ট ব্যবহার করতে চান তবে ক্লাসের সাথে নয়, অবজেক্টের সাথে কাজ করুন।


4
সুতরাং আপনার পদ্ধতিটি $api আপনার কাঠামোর চারপাশে বিভিন্ন পাস করা ? আপনি যা বলতে চাইছেন তা আমি ঠিক পাইনি। কল এছাড়াও যদি add('Logger')মূলত একই উদাহরণস্বরূপ ফেরৎ আপনি একটি পরিষেবা cotainer আছে
গতিশীল

হ্যাঁ, ওটা ঠিক আছে. আমি তাদের "সিস্টেম কন্ট্রোলার" হিসাবে উল্লেখ করি এবং এগুলি এপিআইয়ের কার্যকারিতা বাড়ানোর জন্য to একইভাবে কোনও মডেলে দু'বার "অডেবল" নিয়ন্ত্রক যুক্ত করা ঠিক একইভাবে কাজ করবে - কেবলমাত্র একটি উদাহরণ এবং নিরীক্ষণের ক্ষেত্রগুলির একটি সেট তৈরি করুন।
রোমানিশ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.