আমি জানি যে এই থ্রেডটি এই মুহুর্তে বেশ পুরানো, তবে আমি অনুভব করেছি যে আমি এই সম্পর্কে আমার চিন্তাভাবনাগুলি নিয়ে চিমে আছি। টিএল; ডিআর হ'ল জাভাস্ক্রিপ্টের টাইপযুক্ত, গতিশীল প্রকৃতির কারণে, আপনি নির্ভরতা ইনজেকশন (ডিআই) প্যাটার্ন অবলম্বন না করে বা একটি ডিআই ফ্রেমওয়ার্ক ব্যবহার না করে আপনি বেশ কিছু করতে পারেন। তবে, অ্যাপ্লিকেশনটি আরও বড় এবং জটিল আকার ধারণ করার সাথে সাথে ডিআই অবশ্যই আপনার কোডটি বজায় রাখতে সহায়তা করতে পারে।
সি # তে ডিআই
জাভা স্ক্রিপ্টে ডিআই কেন প্রয়োজনের চেয়ে বড় নয় তা বোঝার জন্য, সি # এর মতো দৃ strongly়ভাবে টাইপ করা ভাষার দিকে নজর দেওয়া সহায়ক। (যারা সি # জানেন না তাদের কাছে ক্ষমা, তবে এটি অনুসরণ করা যথেষ্ট সহজ হওয়া উচিত)) বলুন আমাদের কাছে একটি অ্যাপ রয়েছে যা একটি গাড়ি এবং এর শিং বর্ণনা করে। আপনি দুটি শ্রেণি সংজ্ঞায়িত করবেন:
class Horn
{
public void Honk()
{
Console.WriteLine("beep!");
}
}
class Car
{
private Horn horn;
public Car()
{
this.horn = new Horn();
}
public void HonkHorn()
{
this.horn.Honk();
}
}
class Program
{
static void Main()
{
var car = new Car();
car.HonkHorn();
}
}
এইভাবে কোডটি লেখার ক্ষেত্রে কয়েকটি সমস্যা রয়েছে।
Carবর্গ শক্তভাবে মধ্যে শিঙা নির্দিষ্ট বাস্তবায়নে মিলিত হয় Hornবর্গ। যদি আমরা গাড়ীর দ্বারা ব্যবহৃত হর্নের ধরণটি পরিবর্তন করতে চাই, তবে শিংয়ের ব্যবহার পরিবর্তিত না Carহলেও আমাদের ক্লাসটি সংশোধন করতে হবে। এটি পরীক্ষাও কঠিন করে তোলে কারণ আমরা Carক্লাসটিকে তার নির্ভরতা, শ্রেণি থেকে বিচ্ছিন্নভাবে পরীক্ষা করতে পারি না Horn।
Carক্লাসের জীবনচক্র জন্য দায়ী Hornবর্গ। এর মতো সাধারণ উদাহরণে এটি কোনও বড় সমস্যা নয়, তবে বাস্তব প্রয়োগগুলিতে নির্ভরতাগুলির উপর নির্ভরতা থাকবে, যার নির্ভরতা থাকবে etc. ইত্যাদি Cardepend এটি কেবল জটিল এবং পুনরাবৃত্তিমূলক নয়, তবে এটি শ্রেণীর "একক দায়িত্ব" লঙ্ঘন করে। এটি গাড়ি হওয়ার উপর নজর দেওয়া উচিত, দৃষ্টান্ত তৈরি না করে।
- একই নির্ভরতার উদাহরণগুলি পুনরায় ব্যবহার করার কোনও উপায় নেই। আবার, এই খেলনা অ্যাপ্লিকেশনটিতে এটি গুরুত্বপূর্ণ নয়, তবে একটি ডাটাবেস সংযোগ বিবেচনা করুন। আপনার সাধারণত একটি একক দৃষ্টান্ত থাকে যা আপনার অ্যাপ্লিকেশন জুড়ে ভাগ করা হয়।
এখন, নির্ভরতা ইঞ্জেকশন প্যাটার্নটি ব্যবহার করতে এটি রিফ্যাক্টর আসুন।
interface IHorn
{
void Honk();
}
class Horn : IHorn
{
public void Honk()
{
Console.WriteLine("beep!");
}
}
class Car
{
private IHorn horn;
public Car(IHorn horn)
{
this.horn = horn;
}
public void HonkHorn()
{
this.horn.Honk();
}
}
class Program
{
static void Main()
{
var horn = new Horn();
var car = new Car(horn);
car.HonkHorn();
}
}
আমরা এখানে দুটি মূল কাজ করেছি। প্রথমত, আমরা একটি ইন্টারফেস চালু করেছি যা আমাদের Hornক্লাস প্রয়োগ করে। এটি আমাদের Carনির্দিষ্ট প্রয়োগের পরিবর্তে ইন্টারফেসে ক্লাসটি কোড করতে দেয় । এখন কোড প্রয়োগ করতে পারে এমন যে কোনও কিছু নিতে পারে IHorn। দ্বিতীয়ত, আমরা শিঙা ইনস্ট্যান্টেশনটি বাইরে নিয়ে এসে এর Carপরিবর্তে পাস করেছি। এটি উপরের সমস্যাগুলি সমাধান করে এবং সুনির্দিষ্ট দৃষ্টান্ত এবং তার জীবনচক্রগুলি পরিচালনা করার জন্য অ্যাপ্লিকেশনটির মূল ফাংশনে রেখে দেয়।
এর অর্থ কী, এটি Carক্লাসটি স্পর্শ না করে গাড়িটি ব্যবহারের জন্য একটি নতুন ধরণের শিং প্রবর্তন করতে পারে :
class FrenchHorn : IHorn
{
public void Honk()
{
Console.WriteLine("le beep!");
}
}
এর পরিবর্তে প্রধান FrenchHornশ্রেণীর পরিবর্তে কেবলমাত্র উদাহরণটি ইনজেক্ট করতে পারে । এটিও নাটকীয়ভাবে পরীক্ষা সহজতর করে তোলে। আপনি MockHornনির্জনে ইনজেকশনের জন্য একটি ক্লাস তৈরি করতে পারেন Carযাতে আপনি Carবিচ্ছিন্নভাবে কেবল ক্লাসটি পরীক্ষা করছেন ।
উপরের উদাহরণটিতে ম্যানুয়াল নির্ভরতা ইনজেকশন দেখানো হয়েছে। সাধারণত দ্বি একটি কাঠামো (যেমন সঙ্গে সম্পন্ন করা হয় ইউনিটি বা Ninject সি # বিশ্বের)। এই ফ্রেমওয়ার্কগুলি আপনার নির্ভরতা গ্রাফটি হাঁটা এবং প্রয়োজনীয়তা হিসাবে দৃষ্টান্ত তৈরি করে আপনার জন্য সমস্ত নির্ভরতা তারের কাজ করবে।
স্ট্যান্ডার্ড নোড.জেএস ওয়ে
এখন আসুন নোড.জেএস-তে একই উদাহরণটি দেখুন আমরা সম্ভবত আমাদের কোডটি 3 মডিউলগুলিতে বিভক্ত করব:
// horn.js
module.exports = {
honk: function () {
console.log("beep!");
}
};
// car.js
var horn = require("./horn");
module.exports = {
honkHorn: function () {
horn.honk();
}
};
// index.js
var car = require("./car");
car.honkHorn();
জাভাস্ক্রিপ্টটি টাইপযুক্ত না থাকায় আমাদের কাছে আগের মতো একই টাইট কাপলিং নেই। ইন্টারফেসের কোনও প্রয়োজন নেই (না সেগুলির অস্তিত্ব নেই) কারণ carমডিউল কেবল মডিউল honkযেটি hornরফতানি করে তা পদ্ধতিটি কল করার চেষ্টা করবে ।
অতিরিক্তভাবে, নোডের সমস্ত কিছু requireক্যাশে করার কারণে মডিউলগুলি মূলত একটি ধারকটিতে সঞ্চিত হয়। অন্য যে কোনও মডিউল যা মডিউলে একটি সম্পাদন requireকরে hornতা ঠিক একই উদাহরণটি পাবে। এটি ডাটাবেস সংযোগের মতো সিঙ্গলটন অবজেক্টগুলিকে ভাগ করে নেওয়া খুব সহজ করে তোলে।
এখন এখনও সমস্যা আছে যে carমডিউলটি তার নিজস্ব নির্ভরতা আনার জন্য দায়ী horn। আপনি যদি গাড়িটি এর শিংয়ের জন্য আলাদা মডিউল ব্যবহার করতে চান তবে আপনাকে মডিউলে requireবিবৃতিটি পরিবর্তন করতে হবে car। এটি করা খুব সাধারণ জিনিস নয়, তবে এটি পরীক্ষার ক্ষেত্রে সমস্যা সৃষ্টি করে।
লোকেরা টেস্টিংয়ের সমস্যাটি যেভাবে পরিচালনা করে তা হ'ল প্রক্সিওয়্যার । জাভাস্ক্রিপ্টের গতিশীল প্রকৃতির কারণে, প্রক্সিওয়্যারের জন্য কলগুলি বাধা দেয় এবং পরিবর্তে আপনি সরবরাহ করেন এমন কোনও স্টাব / উপহাসকে ফেরত দেয়।
var proxyquire = require('proxyquire');
var hornStub = {
honk: function () {
console.log("test beep!");
}
};
var car = proxyquire('./car', { './horn': hornStub });
// Now make test assertions on car...
বেশিরভাগ অ্যাপ্লিকেশনগুলির জন্য এটি যথেষ্ট পরিমাণে বেশি। এটি যদি আপনার অ্যাপের জন্য কাজ করে তবে তার সাথে যান। যাইহোক, আমার অভিজ্ঞতা হিসাবে অ্যাপ্লিকেশনগুলি আরও বড় এবং আরও জটিল আকার ধারণ করে, এই জাতীয় কোড বজায় রাখা আরও শক্ত হয়।
জাভাস্ক্রিপ্টে ডিআই
নোড.জেএস খুব নমনীয়। আপনি যদি উপরের পদ্ধতিতে সন্তুষ্ট না হন তবে নির্ভরতা ইঞ্জেকশন প্যাটার্নটি ব্যবহার করে আপনি আপনার মডিউলগুলি লিখতে পারেন। এই প্যাটার্নে, প্রতিটি মডিউল একটি কারখানা ফাংশন (বা একটি শ্রেণি নির্মাতা) রফতানি করে।
// horn.js
module.exports = function () {
return {
honk: function () {
console.log("beep!");
}
};
};
// car.js
module.exports = function (horn) {
return {
honkHorn: function () {
horn.honk();
}
};
};
// index.js
var horn = require("./horn")();
var car = require("./car")(horn);
car.honkHorn();
এটি সি # পদ্ধতির সাথে খুব পূর্ববর্তী যে index.jsমডিউলটি উদাহরণস্বরূপ লাইফসাইকেল এবং তারের জন্য দায়ী। ইউনিট টেস্টিং বেশ সহজ কারণ আপনি কেবল মক / স্টাবগুলিতে ফাংশনগুলিতে যেতে পারেন। আবার এটি যদি আপনার অ্যাপ্লিকেশনটির পক্ষে যথেষ্ট ভাল হয় তবে এটি সাথে যান।
বোলাস ডিআই ফ্রেমওয়ার্ক
সি # এর বিপরীতে আপনার নির্ভরতা পরিচালনার জন্য কোনও প্রতিষ্ঠিত স্ট্যান্ডার্ড ডিআই ফ্রেমওয়ার্ক নেই। এনপিএম রেজিস্ট্রিতে বেশ কয়েকটি ফ্রেমওয়ার্ক রয়েছে তবে এর কোনওটিরই ব্যাপক গ্রহণযোগ্যতা নেই। এই বিকল্পগুলির মধ্যে অনেকগুলি ইতিমধ্যে অন্যান্য উত্তরে উদ্ধৃত হয়েছে।
উপলভ্য বিকল্পগুলির মধ্যে আমি বিশেষত খুশি ছিলাম না তাই আমি নিজের নিজস্ব বলিউস লিখেছিলাম । বোলাস উপরের ডিআই স্টাইলে লিখিত কোডের সাথে কাজ করার জন্য ডিজাইন করা হয়েছে এবং খুব ডিআরওয়াই এবং খুব সাধারণ হওয়ার চেষ্টা করে । উপরেরটি ঠিক একই car.jsএবং horn.jsমডিউলগুলি ব্যবহার করে আপনি index.jsমলিউডটি বুলাসের সাথে আবার লিখতে পারেন :
// index.js
var Injector = require("bolus");
var injector = new Injector();
injector.registerPath("**/*.js");
var car = injector.resolve("car");
car.honkHorn();
প্রাথমিক ধারণাটি হ'ল আপনি কোনও ইঞ্জেক্টর তৈরি করেন। আপনি ইনজেক্টারে আপনার সমস্ত মডিউল নিবন্ধন করুন। তারপরে আপনি যা প্রয়োজন তা কেবল সমাধান করুন। বোলাস নির্ভরতা গ্রাফটি হাঁটবেন এবং প্রয়োজনীয়তা নির্ভরতা তৈরি এবং ইনজেকশন করবেন। আপনি এর মতো খেলনার উদাহরণে খুব বেশি সঞ্চয় করতে পারবেন না, তবে জটিল নির্ভরতা গাছ সহ বড় অ্যাপ্লিকেশনগুলিতে সঞ্চয় বিপুল।
Usচ্ছিক নির্ভরতা এবং পরীক্ষার গ্লোবালগুলির মতো একগুচ্ছ নিফটি বৈশিষ্ট্যগুলিকে সমর্থন করে বোলাস, তবে মানক নোড.জেএস পদ্ধতির তুলনায় আমি দুটি মূল সুবিধা পেয়েছি। প্রথমত, আপনার যদি অনেকগুলি অনুরূপ অ্যাপ্লিকেশন থাকে তবে আপনি আপনার বেসের জন্য একটি প্রাইভেট এনপিএম মডিউল তৈরি করতে পারেন যা একটি ইনজেক্টর তৈরি করে এবং এতে দরকারী অবজেক্টগুলি নিবন্ধভুক্ত করে। তারপরে আপনার নির্দিষ্ট অ্যাপ্লিকেশনগুলি অ্যাংুলারজেএস এর মতো সংযুক্ত করতে, ওভাররাইড করতে এবং সমাধান করতে পারেইনজেক্টর কাজ করে। দ্বিতীয়ত, নির্ভরশীলতার বিভিন্ন প্রসঙ্গটি পরিচালনা করতে আপনি বোলাস ব্যবহার করতে পারেন। উদাহরণস্বরূপ, আপনি অনুরোধ অনুযায়ী শিশু ইনজেক্টর তৈরি করতে মিডলওয়্যার ব্যবহার করতে পারেন, ব্যবহারকারী আইডি, সেশন আইডি, লগার ইত্যাদির উপর নির্ভর করে যে কোনও মডিউলগুলির সাথে ইঞ্জেক্টরে রেজিস্ট্রেশন করতে পারেন। তারপরে আপনাকে যা অনুরোধগুলি সরবরাহ করতে হবে তা সমাধান করুন। এটি আপনাকে অনুরোধ অনুযায়ী আপনার মডিউলগুলির উদাহরণ দেয় এবং প্রতিটি মডিউল ফাংশন কলের পাশাপাশি লগার ইত্যাদি পাস করতে বাধা দেয়।