নোডজেএসে কি আমার নির্ভরতা ইনজেকশন দরকার, বা কীভাবে মোকাবেলা করতে হয় ...?


219

আমি বর্তমানে নোডেজ দিয়ে কিছু পরীক্ষামূলক প্রকল্প তৈরি করছি। আমি স্প্রিংয়ের সাথে প্রচুর জাভা ইই ওয়েব অ্যাপ্লিকেশন প্রোগ্রাম করেছি এবং সেখানে নির্ভরতা ইনজেকশনের স্বাচ্ছন্দ্যের প্রশংসা করেছি।

এখন আমি কৌতূহলী: আমি নোডের সাথে নির্ভরতা ইঞ্জেকশনটি কীভাবে করব? বা: আমারও কি এটি দরকার? একটি প্রতিস্থাপন ধারণা আছে, কারণ প্রোগ্রামিং শৈলী পৃথক?

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


1
আপনি ডিআই ব্যবহার করার সিদ্ধান্ত নেওয়ার পরে, ওপেন টেবিলটি সম্প্রতি এটির জন্য একটি লাইব্রেরিটি ওপেন-সোর্স করেছে: github.com/opentable/spur-ioc আমি এটি ব্যবহার করেছি (আমি সেখানে কাজ করি), এবং বলতে পারি এটি পরীক্ষার জন্য বেশ সহজ এবং দুর্দান্ত।
tybro0103

উত্তর:


107

সংক্ষেপে, আপনার সি / জাভাতে যেমন নির্ভরতা ইনজেকশন ধারক বা পরিষেবা লোকেটারের দরকার নেই। যেহেতু নোড.জেএস, এইগুলি উপকৃত করে module pattern, তাই কনস্ট্রাক্টর বা সম্পত্তি ইনজেকশন দেওয়ার প্রয়োজন হয় না। যদিও আপনি এখনও পারেন।

জেএস সম্পর্কে দুর্দান্ত জিনিস হ'ল আপনি যা চান তা অর্জন করতে আপনি যে কোনও কিছুতে পরিবর্তন করতে পারেন। এটি টেস্টিংয়ের ক্ষেত্রে কার্যকর হয়।

আমার খুব লম্পট সংক্ষিপ্ত উদাহরণ দেখুন।

MyClass.js:

var fs = require('fs');

MyClass.prototype.errorFileExists = function(dir) {
    var dirsOrFiles = fs.readdirSync(dir);
    for (var d in dirsOrFiles) {
        if (d === 'error.txt') return true;
    }
    return false;
};

MyClass.test.js:

describe('MyClass', function(){
    it('should return an error if error.txt is found in the directory', function(done){
        var mc = new MyClass();
        assert(mc.errorFileExists('/tmp/mydir')); //true
    });
});

লক্ষ্য করুন কিভাবে মডিউল MyClassউপর নির্ভর করে fs? @ শায়েমশেখর যেমন উল্লেখ করেছেন, আপনি অন্য ভাষাগুলির মতো নির্মাণকারীর বা সম্পত্তি ইনজেকশনটি করতে পারেন। তবে এটি জাভাস্ক্রিপ্টে প্রয়োজনীয় নয়।

এই ক্ষেত্রে, আপনি দুটি জিনিস করতে পারেন।

আপনি fs.readdirSyncপদ্ধতিটি স্তম্ভিত করতে পারেন বা কল করার সময় আপনি সম্পূর্ণ ভিন্ন মডিউলটি ফিরে আসতে পারেন require

পদ্ধতি 1:

var oldmethod = fs.readdirSync;
fs.readdirSync = function(dir) { 
    return ['somefile.txt', 'error.txt', 'anotherfile.txt']; 
};

*** PERFORM TEST ***
*** RESTORE METHOD AFTER TEST ****
fs.readddirSync = oldmethod;

পদ্ধতি 2:

var oldrequire = require
require = function(module) {
    if (module === 'fs') {
        return {
            readdirSync: function(dir) { 
                return ['somefile.txt', 'error.txt', 'anotherfile.txt']; 
            };
        };
    } else
        return oldrequire(module);

}

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

হালনাগাদ:

এটি ডাটাবেস সংযোগ সম্পর্কিত আপনার নির্দিষ্ট প্রশ্নের সমাধান করা উচিত। আমি আপনার ডাটাবেস সংযোগ যুক্তি encapsulate জন্য একটি পৃথক মডিউল তৈরি করতে চাই। এটার মতো কিছু:

MyDbConnection.js: (আরও ভাল নাম চয়ন করতে ভুলবেন না)

var db = require('whichever_db_vendor_i_use');

module.exports.fetchConnection() = function() {
    //logic to test connection

    //do I want to connection pool?

    //do I need only one connection throughout the lifecyle of my application?

    return db.createConnection(port, host, databasename); //<--- values typically from a config file    
}

তারপরে, যে কোনও মডিউল যাতে একটি ডাটাবেস সংযোগ দরকার তা কেবল আপনার MyDbConnectionমডিউলটি অন্তর্ভুক্ত করে ।

SuperCoolWebApp.js:

var dbCon = require('./lib/mydbconnection'); //wherever the file is stored

//now do something with the connection
var connection = dbCon.fetchConnection(); //mydbconnection.js is responsible for pooling, reusing, whatever your app use case is

//come TEST time of SuperCoolWebApp, you can set the require or return whatever you want, or, like I said, use an actual connection to a TEST database. 

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


42
এটি পরীক্ষার ক্ষেত্রে সত্য, তবে ডিআইয়ের অন্যান্য সুবিধা রয়েছে; ডিআই ব্যবহার করে আপনি কোনও ইন্টারফেসে প্রোগ্রাম করতে পারেন, বাস্তবায়ন নয়।
মোতুটচ

3
@ মোটেটশ নিশ্চিত নন যে আপনি কেন জেএসের কাছে বেশিরভাগ স্থির ভাষার মতো ইন্টারফেসের ধারণা রাখবেন না। আপনার কাছে যা কিছু রয়েছে তা বাস্তবায়ন, এমনকি যদি আপনি কিছু পূর্বনির্ধারিত ডকুমেন্টেড "ইন্টারফেস" ব্যবহার করতে চান।
জে পি রিচার্ডসন

16
@ জেপিআরচার্ডসন আমি কোনও উপাদানটি কীভাবে লিখতে পারি যা কোনও একটি লাইব্রেরির উপর নির্ভর করে লগার ব্যবহার করে? যদি আমি require('my_logger_library'), আমার উপাদান ব্যবহার করে এমন লোকদের তাদের নিজস্ব লাইব্রেরি ব্যবহারের প্রয়োজনগুলিকে ওভাররাইড করতে হবে। পরিবর্তে, আমি লোকেদের একটি কলব্যাক পাস করার অনুমতি দিতে পারি যা লগার প্রয়োগটি "কনস্ট্রাক্টর" বা "init" পদ্ধতিতে আবৃত করে। এটাই ডিআই এর উদ্দেশ্য।
মোতুটচ

4
২০১৪ সালের মাঝামাঝি পর্যন্ত - npmjs.org/package/proxyquire উপহাসকে "প্রয়োজনীয়" নির্ভরতা তুচ্ছ করে তোলে।
আর্কসেল্ডন

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

72

requireহয় Node.js মধ্যে নির্ভরতা পরিচালনার প্রণালী এবং নিশ্চয় এটা স্বজ্ঞাত এবং কার্যকর, কিন্তু এটা তার সীমাবদ্ধতা উপস্থিত রয়েছে।

আমার পরামর্শ হ'ল নোড.জেসের জন্য আজকের উপলভ্য কিছু নির্ভরতা ইনজেকশন কন্টেইনারগুলির দিকে একবার নজর দেওয়া যাক তাদের পক্ষে কি মতামত রয়েছে। এর মধ্যে কয়েকটি হ'ল:

মাত্র কয়েক নাম।

এখন আসল প্রশ্নটি হ'ল, কোনও সাধারণের তুলনায় আপনি নোড.জেএস ডিআই কনটেইনার দিয়ে কী অর্জন করতে পারেন require?

পেশাদাররা:

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

কনস:

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

সফ্টওয়্যার বিকাশের সাথে সম্পর্কিত যে কোনও কিছুর সাথে, ডিআইয়ের মধ্যে নির্বাচন করা বা requireআপনার প্রয়োজনীয়তা, আপনার সিস্টেমের জটিলতা এবং আপনার প্রোগ্রামিং শৈলীর উপর নির্ভর করে।


3
আপনি কি মনে করেন যে '09-এর পরে পরিস্থিতি যথেষ্ট পরিবর্তিত হয়েছে?
জুহো ভেস্পলিনেন

13
আপনি কি 10 দিন আগের কথা বলতে চান? :)
মারিও

2
Nooo। ডিসেম্বর 9 ... জানা উচিত ছিল।
জুহো ভেস্পসালিনেন

4
আমি মডিউল.এক্সপোর্টগুলি = ফাংশন (ডিপ্স)}} ধরণের প্যাটার্ন ব্যবহার করে ডিআই "প্রয়োগ" করেছি। হ্যাঁ, এটি কাজ করে, তবে এটি বেশ আদর্শ নয়।
জুহো ভেস্পসালিনেন

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

53

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

সি # তে ডিআই

জাভা স্ক্রিপ্টে ডিআই কেন প্রয়োজনের চেয়ে বড় নয় তা বোঝার জন্য, সি # এর মতো দৃ 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();
    }
}

এইভাবে কোডটি লেখার ক্ষেত্রে কয়েকটি সমস্যা রয়েছে।

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

এখন, নির্ভরতা ইঞ্জেকশন প্যাটার্নটি ব্যবহার করতে এটি রিফ্যাক্টর আসুন।

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চ্ছিক নির্ভরতা এবং পরীক্ষার গ্লোবালগুলির মতো একগুচ্ছ নিফটি বৈশিষ্ট্যগুলিকে সমর্থন করে বোলাস, তবে মানক নোড.জেএস পদ্ধতির তুলনায় আমি দুটি মূল সুবিধা পেয়েছি। প্রথমত, আপনার যদি অনেকগুলি অনুরূপ অ্যাপ্লিকেশন থাকে তবে আপনি আপনার বেসের জন্য একটি প্রাইভেট এনপিএম মডিউল তৈরি করতে পারেন যা একটি ইনজেক্টর তৈরি করে এবং এতে দরকারী অবজেক্টগুলি নিবন্ধভুক্ত করে। তারপরে আপনার নির্দিষ্ট অ্যাপ্লিকেশনগুলি অ্যাংুলারজেএস এর মতো সংযুক্ত করতে, ওভাররাইড করতে এবং সমাধান করতে পারেইনজেক্টর কাজ করে। দ্বিতীয়ত, নির্ভরশীলতার বিভিন্ন প্রসঙ্গটি পরিচালনা করতে আপনি বোলাস ব্যবহার করতে পারেন। উদাহরণস্বরূপ, আপনি অনুরোধ অনুযায়ী শিশু ইনজেক্টর তৈরি করতে মিডলওয়্যার ব্যবহার করতে পারেন, ব্যবহারকারী আইডি, সেশন আইডি, লগার ইত্যাদির উপর নির্ভর করে যে কোনও মডিউলগুলির সাথে ইঞ্জেক্টরে রেজিস্ট্রেশন করতে পারেন। তারপরে আপনাকে যা অনুরোধগুলি সরবরাহ করতে হবে তা সমাধান করুন। এটি আপনাকে অনুরোধ অনুযায়ী আপনার মডিউলগুলির উদাহরণ দেয় এবং প্রতিটি মডিউল ফাংশন কলের পাশাপাশি লগার ইত্যাদি পাস করতে বাধা দেয়।


1
এটিও সত্য যে এর বিকল্পগুলির proxyquireমতো রয়েছে sinonযা আপনাকে খুব সংক্ষিপ্ত বিদ্রূপ করার অনুমতি দেয়, উদাহরণস্বরূপ let readFileStub = sinon.stub(fs, 'readFile').yields(new Error('something went wrong'));এবং তারপরে পরবর্তী কলগুলি fs.readFileততক্ষণে ফিরে আসবে যতক্ষণ না আপনি স্টাবটি ফেরত না দেন readFileStub.restore()। ব্যক্তিগতভাবে আমি ডিআইকে প্রশ্নবিদ্ধ ব্যবহারের সন্ধান করি কারণ আমার কাছে মনে হয় এটির প্রায়শই ক্লাস / অবজেক্টের ব্যবহার প্রয়োজন, যা জাভাস্ক্রিপ্টের কার্যকরী ঝোঁক প্রদত্ত একটি সন্দেহজনক ধারণা।
কেভিন

এই ভাল + বিস্তারিত উত্তরের জন্য ধন্যবাদ। আমি এটি প্রায় মিস করেছি, আমি প্রথম সি # তে শিরোনাম ডিআই পড়ার পরে ।
কনস্ট্যান্টিন এ। ম্যাগ

1
দুর্দান্ত উত্তর। আমি ভাবছি করছি কি আপনার চিন্তা, ব্যক্তিগত পছন্দ একটি বিষয় হিসাবে, 2019. রয়েছে বড় বড় প্রকল্পের জন্য আপনি যা পছন্দ করেন - দ্বি / আইওসি নোড মধ্যে, বা শুধু stubbing / দিয়ে উপহাস jest, rewire, proxyquire, ইত্যাদি? ধন্যবাদ।
জেমি করখিল

দুর্দান্ত ভারসাম্য উত্তর! ধন্যবাদ.
জনি ওশিকা

36

আমিও, এই কাজ করা সম্ভব একটি মডিউল লিখেছি এটা বলা হচ্ছে বৈদ্যুতিক তার লাগানো । কেবলমাত্র npm install rewireএবং তারপর ব্যবহার করুন :

var rewire = require("rewire"),
    myModule = rewire("./path/to/myModule.js"); // exactly like require()

// Your module will now export a special setter and getter for private variables.
myModule.__set__("myPrivateVar", 123);
myModule.__get__("myPrivateVar"); // = 123


// This allows you to mock almost everything within the module e.g. the fs-module.
// Just pass the variable name as first parameter and your mock as second.
myModule.__set__("fs", {
    readFile: function (path, encoding, cb) {
        cb(null, "Success!");
    }
});
myModule.readSomethingFromFileSystem(function (err, data) {
    console.log(data); // = Success!
});

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


7
২০১৪ সালের মাঝামাঝি পর্যন্ত - npmjs.org/package/proxyquire উপহাসকে "প্রয়োজনীয়" নির্ভরতা তুচ্ছ করে তোলে।
আর্কসেল্ডন

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

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

জন্য proxyquire এটা বিবরণ এটি পরীক্ষার জন্য ব্যবহার করা হয়ে বলেন এর 'Proxy গুলির nodejs অর্ডার সময় নির্ভরতা অগ্রাহ্য করার অনুমতি প্রয়োজন পরীক্ষা ।' ডিআই এর জন্য না, তাই না?
মারওয়েন ট্রাবেলসি

17

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

ইলেক্ট্রোলাইটগুলি মডিউলগুলি আলিঙ্গন করে, বিশেষত যারা আপনার "কানেক্ট / এক্সপ্রেস মিডলওয়্যারের মতো দেখতে" সেটআপ "ফাংশন রফতানি করে। মূলত, এই ধরণের মডিউলগুলি কিছু ফ্যাক্টরি যা তারা ফিরে আসে return

উদাহরণস্বরূপ, একটি মডিউল যা একটি ডাটাবেস সংযোগ তৈরি করে:

var mysql = require('mysql');

exports = module.exports = function(settings) {
  var connection = mysql.createConnection({
    host: settings.dbHost,
    port: settings.dbPort
  });

  connection.connect(function(err) {
    if (err) { throw err; }
  });

  return connection;
}

exports['@singleton'] = true;
exports['@require'] = [ 'settings' ];

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

একটি ডাটাবেস সংযোগ তৈরি করতে:

var db = electrolyte.create('database');

ইলেক্ট্রোলাইট ট্রান্সজিটিভলি @require'ডি নির্ভরতাগুলি ট্র্যাভার করে এবং রফতানি কার্যের আর্গুমেন্ট হিসাবে উদাহরণগুলিকে ইনজেক্ট করে।

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

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


1
কল connect()ছুড়ানোর সময় আপনি যে কোড পোস্ট করেছেন তাতে কি ঘটেছিল তা আপনি পরিষ্কার করতে পারবেন ? যদিও আমি নোডের জন্য মাইএসকিএল এপিআইয়ের সাথে পরিচিত নই, আমি এই কলটি অ্যাসিক্রোনাসের আশা করব, তাই চিত্রণটি খুব পরিষ্কার নয়।
আন্দ্রে আগিবালোভ

ইলেক্ট্রোলাইট ব্যবহার বর্তমানে। আপনি দাবী করেন যে রফতানি ['@ જરૂર'] এর মাধ্যমে ইনজেক্ট মডিউলগুলি সহজ। তবে আমাকে যদি প্রয়োজনীয় মডিউলগুলির একটিতে স্টাব করতে হয় তবে তা কীভাবে বৈদ্যুতিনের ক্ষেত্রে অর্জনযোগ্য। বর্তমানে আমাদের মডিউলগুলির প্রয়োজন হলে এটি সহজেই অর্জন করা যায়। তবে ইলেক্ট্রোলাইটের জন্য এটি একটি বিশাল নেতিবাচক .... আপনার কি এমন উদাহরণ রয়েছে যেখানে আমরা মডিউলগুলির স্ট্যাবড সংস্করণ ব্যবহার করতে পারি এবং পরীক্ষার কেসগুলি থেকে তাত্ক্ষণিকভাবে / ioc.use চলাকালীন সময়ে এটি পাস করতে পারি। সুতরাং মূলত ইউনিট পরীক্ষায়, আমরা যদি ioc.create ('মডিউলনাম') করতে পারি এবং তারপরে নির্ভরশীল মডিউলগুলির ইনজেকশন (তবে
স্ট্যাবডগুলি

1
আপনি ioc.createইউনিট পরীক্ষা থেকে কল করবেন না । একটি ইউনিট পরীক্ষায় কেবলমাত্র মডিউলটিকে পরীক্ষার অধীনে পরীক্ষা করা উচিত, এবং বৈদ্যুতিন সহ অন্যান্য নির্ভরতা আনতে হবে না। এই পরামর্শ অনুসরণ করে, আপনি করবেনobjToTest = require('modulename')(mockObj1, mockObj2);
জারেড হ্যানসন

8

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

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

এখানে একটি উদাহরণ:

import foo from './utils/foo';
import bob from './utils/bob';

// We export a factory which accepts our dependencies.
export const factory = (dependencies = {}) => {
  const {
    // The 'bob' dependency.  We default to the standard 'bob' imp if not provided.
    $bob = bob, 
    // Instead of exposing the whole 'foo' api, we only provide a mechanism
    // with which to override the specific part of foo we care about.
    $doSomething = foo.doSomething // defaults to standard imp if none provided.
  } = dependencies;  

  return function bar() {
    return $bob($doSomething());
  }
}

// The default implementation, which would end up using default deps.
export default factory();

এবং এটির ব্যবহারের উদাহরণ এখানে

import { factory } from './bar';

const underTest = factory({ $bob: () => 'BOB!' }); // only override bob!
const result = underTest();

এটির সাথে অপরিচিতদের জন্য ES6 সিনট্যাক্সটি ক্ষমা করুন।


সত্যিই খুব বুদ্ধিমান!
আর্নল্ড

4

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

একটি এক্সপ্রেস অ্যাপ্লিকেশন প্রসঙ্গে - আমি একটি বুটস্ট্র্যাপ.জেএস ফাইলটিতে app.js মোড়ানো:

var path = require('path');
var myapp = require('./app.js');

var loader = require('./server/services/loader.js');

// give the loader the root directory
// and an object mapping module names 
// to paths relative to that root
loader.init(path.normalize(__dirname), require('./server/config/loader.js')); 

myapp.start();

লোডারকে দেওয়া বস্তুর মানচিত্রটি দেখতে এরকম দেখাচ্ছে:

// live loader config
module.exports = {
    'dataBaseService': '/lib/dataBaseService.js'
}

// test loader config
module.exports = {
    'dataBaseService': '/mocks/dataBaseService.js'
    'otherService' : {other: 'service'} // takes objects too...
};

তারপরে, সরাসরি কল করার চেয়ে ...

var myDatabaseService = loader.load('dataBaseService');

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

আমি সুবিধার জন্য সবেমাত্র একটি এনএমপি মডিউল প্রকাশ করেছি:

https://npmjs.org/package/nodejs-simple-loader


3

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

নিম্নোক্ত বিবেচনা কর:

import UserRepository from "./dal/user_repository";

class UserController {
    constructor() {
        this._repository = new UserRepository();
    }
    getUsers() {
        this._repository.getAll();
    }
}

export default UserController;

সুতরাং আপনি রান-টাইমে উপাদানগুলির মধ্যে সংযোগকে ওভাররাইড করতে পারেন। আমি ভাবতে চাই যে আমাদের জাভাস্ক্রিপ্ট মডিউলগুলি ডিকুয়াল করা উচিত।

আসল decoupling অর্জনের একমাত্র উপায় হ'ল রেফারেন্সটি সরিয়ে ফেলা UserRepository:

class UserController {
    constructor(userRepository) {
        this._repository = userRepository;
    }
    getUsers() {
        this._repository.getAll();
    }
}

export default UserController;

এর অর্থ হ'ল অন্য কোথাও আপনাকে অবজেক্ট রচনাটি করতে হবে:

import UserRepository from "./dal/user_repository";
import UserController from "./dal/user_controller";

export default new UserController(new UserRepository());

আমি আইওসি পাত্রে অবজেক্ট রচনাটি অর্পণ করার ধারণাটি পছন্দ করি। আপনি নিবন্ধে এই ধারণাটি সম্পর্কে আরও শিখতে পারেন জাভাস্ক্রিপ্টে নির্ভরতা বিপর্যয়ের বর্তমান অবস্থা । নিবন্ধটি কিছু "জাভাস্ক্রিপ্ট আইওসি ধারক কল্পকাহিনী" নষ্ট করার চেষ্টা করেছে:

মিথ 1: জাভাস্ক্রিপ্টে আইওসি পাত্রে কোনও স্থান নেই

মিথ 2: আমাদের আইওসি পাত্রে দরকার নেই, আমাদের ইতিমধ্যে মডিউল লোডার রয়েছে!

মিথ 3: নির্ভরতা বিপরীততা === ইনজেকশন নির্ভরতা

আপনি যদি আইওসি পাত্রে ব্যবহার করার ধারণাও পছন্দ করেন তবে আপনি ইনভারসিফাইজেএস এ একবার দেখতে পারেন। সর্বশেষ প্রকাশ (2.0.০) অনেকগুলি ব্যবহারের ক্ষেত্রে সমর্থন করে:

  • কার্নেল মডিউলগুলি
  • কার্নেল মিডওয়্যার
  • নির্ভরতা শনাক্তকারী হিসাবে ক্লাস, স্ট্রিং লিটারেল বা সিম্বল ব্যবহার করুন
  • ধ্রুবক মানের ইনজেকশন
  • শ্রেণি নির্মাতাদের ইনজেকশন
  • কারখানার ইনজেকশন
  • অটো কারখানা
  • সরবরাহকারীদের ইনজেকশন (অ্যাসিঙ্ক কারখানা)
  • অ্যাক্টিভেশন হ্যান্ডলারগুলি (প্রক্সি ইনজেক্ট করতে ব্যবহৃত)
  • মাল্টি ইনজেকশন
  • বাঁধা বাঁধাই
  • কাস্টম ট্যাগ সজ্জকার
  • নামকরণ বাঁধাই
  • প্রাসঙ্গিক বাঁধাই
  • বন্ধুত্বপূর্ণ ব্যতিক্রম (যেমন বিজ্ঞপ্তি নির্ভরতা)

আপনি এটি সম্পর্কে InversifyJS এ আরও শিখতে পারেন ।


2

ES6 এর জন্য আমি এই ধারকটি তৈরি করেছি https://github.com/zazoomauro/node-d dependency-inication

import {ContainerBuilder} from 'node-dependency-injection'

let container = new ContainerBuilder()
container.register('mailer', 'Mailer')

তারপরে আপনি সেট করতে পারেন, উদাহরণস্বরূপ, ধারকটিতে পরিবহণের পছন্দ:

import {ContainerBuilder} from 'node-dependency-injection'

let container = new ContainerBuilder()
container
  .register('mailer', 'Mailer')
  .addArgument('sendmail')

আপনি বাস্তবায়নের বাইরে এবং পাত্রে পরিবহণের পছন্দকে পৃথক করেছেন বলে এই শ্রেণিটি এখন আরও নমনীয়।

এখন যে মেইলারের পরিষেবাটি ধারকটিতে রয়েছে আপনি অন্যান্য ক্লাসের নির্ভরতা হিসাবে এটি ইনজেকশন করতে পারেন। আপনার যদি নিউজলেটার ম্যানেজার ক্লাস থাকে তবে:

class NewsletterManager {
    construct (mailer, fs) {
        this._mailer = mailer
        this._fs = fs
    }
}

export default NewsletterManager

নিউজলেটার_ম্যানেজার পরিষেবা সংজ্ঞায়িত করার সময়, মেলারের পরিষেবাটি এখনও বিদ্যমান নেই। নিউজলেটার ম্যানেজারটি যখন আরম্ভ করে তখন মেইল ​​পরিষেবাটি ইনজেক্ট করতে কনটেইনারটি বলতে রেফারেন্স ক্লাসটি ব্যবহার করুন:

import {ContainerBuilder, Reference, PackageReference} from 'node-dependency-injection'
import Mailer from './Mailer'
import NewsletterManager from './NewsletterManager'

let container = new ContainerBuilder()

container
  .register('mailer', Mailer)
  .addArgument('sendmail')

container
  .register('newsletter_manager', NewsletterManager)
  .addArgument(new Reference('mailer'))
  .addArgument(new PackageReference('fs-extra'))

আপনি ইয়ামল, জসন বা জেএস ফাইলগুলির মতো কনফিগারেশন ফাইল সহ ধারকও সেট আপ করতে পারেন

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

container.compile()

1

এটি আপনার আবেদনের নকশার উপর নির্ভর করে। আপনি স্পষ্টতই ইনজেকশনের মতো একটি জাভা করতে পারেন যেখানে আপনি নির্ধারকটির মতো নির্ভরতার সাথে কোনও শ্রেণীর একটি অবজেক্ট তৈরি করেন।

function Cache(store) {
   this._store = store;
}

var cache = new Cache(mysqlStore);

আপনি যদি জাভাস্ক্রিপ্টে ওওপি না করে থাকেন তবে আপনি একটি ডিআইআই ফাংশন তৈরি করতে পারেন যা সবকিছু সেট আপ করে।

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


আপনার উত্তরের জন্য ধন্যবাদ, তবে আমি আপনার উত্তরের দ্বিতীয় অংশটি পুরোপুরি বুঝতে পারি না।
এরিক

1

আমি সর্বদা আইওসি ধারণার সরলতা পছন্দ করেছিলাম - "আপনাকে পরিবেশ সম্পর্কে কিছু জানার দরকার নেই, যখন প্রয়োজন হবে তখন আপনাকে কেউ ডাকবে"

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

এটি মনোজজেএস ওয়েব ফ্রেমওয়ার্ক http: //monojs.org- এ ব্যবহৃত হয়

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

এটি এটির মতো হয়ে গেছে - কনফিগারেশনে একবার উপাদান নিবন্ধ করুন।

app.register 'db', -> 
  require('mongodb').connect config.dbPath

এবং এটি যে কোনও জায়গায় ব্যবহার করুন

app.db.findSomething()

আপনি সম্পূর্ণ উপাদান সংজ্ঞা কোড দেখতে পাবেন (ডিবি সংযোগ এবং অন্যান্য উপাদান সহ) এখানে https://github.com/sinizinairina/mono/blob/master/mono.coffee

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

আইওসি নিজেই https://github.com/alexeypetrushin/miconjs


6
ডিআই হিসাবে বিজ্ঞাপন দেওয়া সত্ত্বেও এটি অনেকটা সার্ভিস লোকেটারের মতো বলে মনে হয়।
কিওরকোড

2
দুর্দান্ত দেখে মনে হচ্ছে, এটি কেবল কফসক্রিপ্টে লজ্জাজনক
রাফায়েল পি। মিরান্ডা

1

আমি মনে করি আমাদের এখনও নোডেজে নির্ভরতা ইনজেকশন দরকার কারণ এটি পরিষেবার মধ্যে নির্ভরতা আলগা করে অ্যাপ্লিকেশনকে আরও স্পষ্ট করে তোলে।

স্প্রিং ফ্রেমওয়ার্ক দ্বারা অনুপ্রাণিত হয়ে আমি নোডেজে নির্ভরতা ইনজেকশন সমর্থন করার জন্য আমার নিজস্ব মডিউলটিও প্রয়োগ করি। আমার মডিউলটি আপনার অ্যাপ্লিকেশন পুনরায় আরম্ভ না করে code changesএবং auto reloadপরিষেবাগুলি সনাক্ত করতে সক্ষম ।

আমার প্রকল্পটি এখানে দেখুন: বুঞ্চা - আইওসি ধারক

ধন্যবাদ!


0

ডিপগুলি দেখুন (নোড.জেএস এর জন্য একটি সহজ তবে শক্তিশালী নির্ভরতা ইনজেকশন এবং সত্তা (ফাইল) পরিচালনার কাঠামো)

https://github.com/devcrust/node-dips


0

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

আপনি যদি ডিআই-র সন্ধান করেন তবে একবার চেষ্টা করে দেখুন। এটি এখানে পাওয়া যাবে: https://github.com/robo-creative/nodejs-robo-container । এটি সম্পূর্ণ নথিভুক্ত। এটি ডিআই-র এবং কিছুটা ওওপি উপায়গুলিতে কীভাবে সমাধান করতে হয় সে সম্পর্কে কিছু সাধারণ সমস্যাগুলি সম্বোধন করে। আশা করি এটা সাহায্য করবে.


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

-1

আমি সম্প্রতি সার্কিটবক্স নামে একটি লাইব্রেরি তৈরি করেছি যা আপনাকে node.js. এর সাথে নির্ভরতা-ইনজেকশন ব্যবহার করতে দেয় এটি সত্যিকারের নির্ভরতা-ইনজেকশন বনাম তৈরি করে। সার্কিটবক্স অ্যাসিক্রোনাস ক্রিয়েশন এবং ইনিশিয়ালাইজেশন রুটিনগুলিকে সমর্থন করে। নীচে একটি উদাহরণ দেওয়া হল:

ধরুন নিম্নলিখিত কোডটি কনসোলমেসেজপ্রিন্টার.জেএস নামে একটি ফাইলে রয়েছে

'use strict';

// Our console message printer
// deps is injected by circuitbox with the dependencies
function ConsoleMessagePrinter(deps) {
  return {
    print: function () {
      console.log(deps.messageSource.message());
    }
  };
}

module.exports = ConsoleMessagePrinter;

ধরুন নিম্নলিখিত ফাইলটি মেইন.জেএস-এ রয়েছে

'use strict';

// our simple message source
// deps is injected by circuitbox with the dependencies
var simpleMessageSource = function (deps) {
  return {
    message: function () {
      return deps.message;
    }
  };
};

// require circuitbox
var circuitbox = require('../lib');

// create a circuitbox
circuitbox.create({
  modules: [
    function (registry) {
      // the message to be used
      registry.for('message').use('This is the message');

      // define the message source
      registry.for('messageSource').use(simpleMessageSource)
        .dependsOn('message');

      // define the message printer - does a module.require internally
      registry.for('messagePrinter').requires('./consoleMessagePrinter')
        .dependsOn('messageSource');
    }
  ]
}).done(function (cbx) {

  // get the message printer and print a message
  cbx.get('messagePrinter').done(function (printer) {
    printer.print();
  }, function (err) {
    console.log('Could not recieve a printer');
    return;
  });

}, function (err) {
  console.log('Could not create circuitbox');
});

সার্কিটবক্স আপনাকে আপনার উপাদানগুলি সংজ্ঞায়িত করতে এবং তাদের নির্ভরতাগুলি মডিউল হিসাবে ঘোষণা করতে দেয়। এটি আরম্ভ করার পরে এটি আপনাকে কোনও উপাদান পুনরুদ্ধার করতে দেয়। সার্কিটবক্স লক্ষ্য উপাদানটি প্রয়োজনীয় সমস্ত উপাদান স্বয়ংক্রিয়ভাবে সংক্রামিত করে এবং এটি আপনাকে ব্যবহারের জন্য দেয়।

প্রকল্পটি আলফা সংস্করণে রয়েছে। আপনার মন্তব্য, ধারণা এবং প্রতিক্রিয়া স্বাগত।

আশা করি এটা সাহায্য করবে!


-1

আমি মনে করি ডিআইআই ব্যবহারের যুক্তিতে অন্য পোস্টগুলি দুর্দান্ত কাজ করেছে। আমার জন্য কারণগুলি

  1. তাদের পথ না জেনে নির্ভরতা ইনজেকশন করুন। এর অর্থ হ'ল আপনি যদি ডিস্কে কোনও মডিউল অবস্থান পরিবর্তন করেন বা এটিকে অন্যের সাথে অদলবদল করেন তবে আপনার উপর নির্ভর করে এমন প্রতিটি ফাইল স্পর্শ করার দরকার নেই।

  2. requireসমস্যা ছাড়াই কাজ করে এমনভাবে বৈশ্বিক ফাংশনকে ওভাররাইড করার ব্যথা ব্যতীত পরীক্ষার জন্য নির্ভরতাগুলি উপহাস করা অনেক সহজ করে তোলে ।

  3. এটি আপনাকে আলগাভাবে কাপল মডিউল হিসাবে অ্যাপ্লিকেশনটি সংগঠিত করতে এবং যুক্তিসঙ্গত করতে সহায়তা করে।

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

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

-1

এটি এর মতো নমনীয় এবং সহজ হওয়া উচিত:

var MyClass1 = function () {}
var MyClass2 = function (myService1) {
    // myService1.should.be.instanceof(MyClass1); 
}


container.register('myService1', MyClass1);
container.register('myService2', MyClass2, ['myService1']);

আমি node.js. তে নির্ভরতা ইনজেকশন সম্পর্কে নিবন্ধ লিখেছি।

আমি আশা করি এটি এর সাথে আপনাকে সহায়তা করতে পারে।


-1

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

উদাহরণস্বরূপ, আপনার ডাটাবেস স্তর মডিউলগুলি কেবল আপনার ব্যবসায়ের কোড মডিউলগুলির প্রয়োজন হবে না কারণ, যখন ইউনিট এই ব্যবসায়িক কোড মডিউলগুলির পরীক্ষা করে, ডઓসগুলি লোড হবে এবং ডাটাবেসের সাথে সংযুক্ত হবে।

একটি সমাধান মডিউল পরামিতি হিসাবে নির্ভরতা পাস করা হবে:

module.exports = function (dep1, dep2) {
// private methods

   return {
    // public methods
       test: function(){...}
   }
}

এইভাবে নির্ভরতাগুলি সহজে এবং প্রাকৃতিকভাবে উপহাস করা যায় এবং আপনি কোনও তৃতীয় পক্ষের লাইব্রেরি ব্যবহার না করেই আপনার কোডটি পরীক্ষায় মনোনিবেশ করতে পারেন।

সেখানে অন্যান্য সমাধান রয়েছে (ব্রডওয়ে, আর্কিটেক্ট ইত্যাদি) যা আপনাকে এটিতে সহায়তা করতে পারে। যদিও তারা আপনি যা চান তার চেয়ে বেশি কিছু করতে পারে বা আরও বিশৃঙ্খলা ব্যবহার করতে পারে।


প্রায় প্রাকৃতিক বিবর্তনের মাধ্যমে আমি একই কাজ শেষ করেছি। আমি পরামিতি হিসাবে একটি নির্ভরতা পাস এবং এটি পরীক্ষার জন্য দুর্দান্ত কাজ করে।
মুঙ্কি

-1

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

ক্লার্কজেএস-এ আরও পড়ুন

সংক্ষিপ্ত উদাহরণ:

KlarkModule(module, 'myModuleName1', function($nodeModule1, myModuleName2) {
    return {
        log: function() { console.log('Hello from module myModuleName1') }
    };
});
  • myModuleName1 মডিউলটির নাম।
  • $nodeModule1এটি একটি বাহ্যিক গ্রন্থাগার node_module। নামটির সমাধান হয় node-module1। উপসর্গটি $নির্দেশ করে যে এটি বাহ্যিক মডিউল।
  • myModuleName2 একটি অভ্যন্তরীণ মডিউলটির নাম।
  • নিয়ামকের রিটার্ন মানটি অন্যান্য অভ্যন্তরীণ মডিউলগুলি থেকে ব্যবহৃত হয়, যখন তারা প্যারামিটারটি সংজ্ঞায়িত করে myModuleName1

-1

নোডজেএস প্রোগ্রামিংয়ের জন্য কেন কোনও ডিআই সিস্টেমের প্রয়োজন হবে তা জানতে নিজের ডিআই মডিউলে একটি সমস্যার উত্তর দেওয়ার সময় আমি এই প্রশ্নটি আবিষ্কার করেছি ।

এই থ্রেডটিতে দেওয়া উত্তরগুলির পরিষ্কারভাবে উত্তর দেওয়া হয়েছিল: এটি নির্ভর করে। উভয় পদ্ধতির জন্য এই অফার রয়েছে এবং এই প্রশ্নের উত্তরগুলি পড়লে সেগুলি একটি ভাল আকার দেয়।

সুতরাং, এই প্রশ্নের আসল উত্তরটি এমন হওয়া উচিত যে কোনও কোনও পরিস্থিতিতে আপনি একটি ডিআই সিস্টেম ব্যবহার করবেন, অন্যথায় নয়।

এটি বলেছিল, আপনি বিকাশকারী হিসাবে যা চান তা হ'ল নিজেকে পুনরাবৃত্তি না করা এবং আপনার বিভিন্ন অ্যাপ্লিকেশন জুড়ে আপনার পরিষেবাগুলি পুনরায় ব্যবহার করা।

এর অর্থ হ'ল আমাদের এমন পরিষেবাগুলি লিখতে হবে যা ডিআই সিস্টেমে ব্যবহারের জন্য প্রস্তুত তবে ডিআই লাইব্রেরিতে আবদ্ধ নয়। আমার কাছে, এর অর্থ হ'ল আমাদের এইরকম পরিষেবা লিখতে হবে:

module.exports = initDBService;

// Tells any DI lib what it expects to find in it context object
// The $inject prop is the de facto standard for DI imo 
initDBService.$inject = ['ENV'];

// Note the context object, imo, a DI tool should bring
// services in a single context object
function initDBService({ ENV }) {
/// actual service code
}

আপনি যদি কোনও ডিআই সরঞ্জাম ব্যবহার করে বা না ব্যবহার করেন তবে আপনার পরিষেবাটি কার্যকর হয় না।


-1

টাইপডিআই এখানে উল্লিখিত সমস্তগুলির মধ্যে মধুরতম, টাইপডিআই-তে এই কোডটি দেখুন

import "reflect-metadata";
import {Service, Container} from "typedi";

@Service()
class SomeClass {

    someMethod() {
    }

}

let someClass = Container.get(SomeClass);
someClass.someMethod();

এই কোডটিও দেখুন:

import {Container, Service, Inject} from "typedi";

// somewhere in your global app parameters
Container.set("authorization-token", "RVT9rVjSVN");

@Service()
class UserRepository {

    @Inject("authorization-token")
    authorizationToken: string;

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