আসুন একটি সহজ উদাহরণ গ্রহণ করি - সম্ভবত আপনি লগিংয়ের একটি মাধ্যম ইনজেকশন দিচ্ছেন।
একটি ক্লাস ইনজেকশন
class Worker: IWorker
{
ILogger _logger;
Worker(ILogger logger)
{
_logger = logger;
}
void SomeMethod()
{
_logger.Debug("This is a debug log statement.");
}
}
আমি মনে করি এটি কি চলছে তা বেশ পরিষ্কার। আরও কী, আপনি যদি আইওসি পাত্রে ব্যবহার করেন তবে আপনার স্পষ্টতই কিছু ইনজেক্ট করার দরকার নেই, আপনি কেবল আপনার রচনার মূলটিতে যুক্ত করুন:
container.RegisterType<ILogger, ConcreteLogger>();
container.RegisterType<IWorker, Worker>();
....
var worker = container.Resolve<IWorker>();
ডিবাগ করার সময় Worker
, কোন বিকাশকারীকে ঠিক কী কংক্রিট শ্রেণি ব্যবহার করা হচ্ছে তা নির্ধারণের জন্য কম্পোজিশনের মূলের সাথে পরামর্শ করতে হবে।
যদি কোনও বিকাশকারী আরও জটিল যুক্তি প্রয়োজন, তার সাথে কাজ করার পুরো ইন্টারফেস রয়েছে:
void SomeMethod()
{
if (_logger.IsDebugEnabled) {
_logger.Debug("This is a debug log statement.");
}
}
একটি পদ্ধতি ইনজেকশন
class Worker
{
Action<string> _methodThatLogs;
Worker(Action<string> methodThatLogs)
{
_methodThatLogs = methodThatLogs;
}
void SomeMethod()
{
_methodThatLogs("This is a logging statement");
}
}
প্রথমে লক্ষ্য করুন, কনস্ট্রাক্টর প্যারামিটারটির এখন দীর্ঘ নাম রয়েছে methodThatLogs
,। এটি প্রয়োজনীয় কারণ আপনি কী করতে হবে তা আপনি বলতে পারবেন না Action<string>
। ইন্টারফেসের সাথে এটি সম্পূর্ণ পরিষ্কার ছিল, তবে এখানে আমাদের প্যারামিটার নামকরণের উপর নির্ভর করতে হবে। এটি অন্তর্নিহিতভাবে কম নির্ভরযোগ্য এবং কোনও বিল্ড চলাকালীন কার্যকর করা শক্ত বলে মনে হচ্ছে।
এখন, আমরা এই পদ্ধতিটি কীভাবে ইনজেক্ট করব? আচ্ছা, আইওসি পাত্রে এটি আপনার জন্য করবে না। সুতরাং আপনি তাত্ক্ষণিকভাবে যখন এটি স্পষ্টভাবে ইনজেকশনের বাকি আছে Worker
। এটি কয়েকটি সমস্যা উত্থাপন করে:
- এটি তাত্ক্ষণিক কাজ আরও কাজ
Worker
- ডিবাগ করার চেষ্টা করা বিকাশকারীরা
Worker
খুঁজে পাবেন যে কংক্রিটের উদাহরণটি কী বলা হয় তা নির্ধারণ করা আরও কঠিন। তারা কেবল কম্পোজিশনের মূলের সাথে পরামর্শ করতে পারে না; তাদের কোডের মাধ্যমে ট্রেস করতে হবে।
আমাদের আরও জটিল যুক্তি লাগলে কীভাবে হয়? আপনার কৌশলটি কেবল একটি পদ্ধতি প্রকাশ করে। এখন আমি মনে করি আপনি ল্যাম্বডায় জটিল জিনিসগুলি বেক করতে পারেন:
var worker = new Worker((s) => { if (log.IsDebugEnabled) log.Debug(s) } );
কিন্তু আপনি যখন নিজের ইউনিট পরীক্ষা লিখছেন, আপনি কীভাবে সেই ল্যাম্বডা এক্সপ্রেশনটি পরীক্ষা করেন? এটি বেনামে, তাই আপনার ইউনিট পরীক্ষার কাঠামোটি সরাসরি এটি ইনস্ট্যান্ট করতে পারে না। সম্ভবত আপনি এটি করার জন্য কিছু চতুর উপায়টি বুঝতে পারেন, তবে এটি কোনও ইন্টারফেস ব্যবহার করার চেয়ে সম্ভবত আরও বড় পিটা হবে।
পার্থক্যের সংক্ষিপ্তসার:
- কেবল একটি পদ্ধতিতে ইনজেকশন করা উদ্দেশ্যটিকে অনুমান করা আরও শক্ত করে তোলে, যেখানে একটি ইন্টারফেস স্পষ্টভাবে উদ্দেশ্যটি যোগাযোগ করে।
- কেবল একটি পদ্ধতিতে ইনজেকশন দেওয়ার ফলে ইনজেকশন প্রাপ্ত শ্রেণীর কম কার্যকারিতা প্রকাশিত হয়। আপনার আজকের প্রয়োজন না হলেও আগামীকাল আপনার প্রয়োজন হতে পারে।
- আপনি কেবলমাত্র IoC ধারক ব্যবহার করে কোনও পদ্ধতি স্বয়ংক্রিয়ভাবে ইনজেক্ট করতে পারবেন না।
- কোন নির্দিষ্ট পরিস্থিতিতে কংক্রিটের ক্লাসটি কাজ করছে তা আপনি কম্পোজিশনের মূল থেকে বলতে পারবেন না।
- ল্যাম্বডা এক্সপ্রেশন নিজেই পরীক্ষা করার জন্য এটি সমস্যা।
যদি আপনি উপরের সমস্তটির সাথে ঠিক থাকেন তবে কেবল পদ্ধতিটি ইনজেক করা ঠিক আছে। অন্যথায় আমি আপনাকে traditionতিহ্য ধরে থাকা এবং একটি ইন্টারফেস ইনজেকশনের পরামর্শ দেব।